smart pathing waypoints

This commit is contained in:
Bob 2023-09-23 23:34:22 +02:00
parent bb591306db
commit f5c17f8bd7
30 changed files with 550 additions and 124 deletions

View File

@ -821,6 +821,7 @@ public class ModBlocks {
public static Block crane_splitter;
public static Block drone_waypoint;
public static Block drone_waypoint_request;
public static Block drone_crate;
public static Block fan;
@ -1994,6 +1995,7 @@ public class ModBlocks {
piston_inserter = new PistonInserter().setBlockName("piston_inserter").setHardness(5.0F).setResistance(10.0F).setCreativeTab(MainRegistry.machineTab).setBlockTextureName(RefStrings.MODID + ":block_steel");
drone_waypoint = new DroneWaypoint().setBlockName("drone_waypoint").setHardness(0.1F).setResistance(10.0F).setCreativeTab(MainRegistry.machineTab).setBlockTextureName(RefStrings.MODID + ":drone_waypoint");
drone_waypoint_request = new DroneWaypointRequest().setBlockName("drone_waypoint_request").setHardness(0.1F).setResistance(10.0F).setCreativeTab(MainRegistry.machineTab).setBlockTextureName(RefStrings.MODID + ":drone_waypoint_request");
drone_crate = new DroneCrate().setBlockName("drone_crate").setHardness(0.1F).setResistance(10.0F).setCreativeTab(MainRegistry.machineTab);
chain = new BlockChain(Material.iron).setBlockName("dungeon_chain").setHardness(0.25F).setResistance(2.0F).setCreativeTab(MainRegistry.blockTab).setBlockTextureName(RefStrings.MODID + ":chain");
@ -3256,6 +3258,7 @@ public class ModBlocks {
register(conveyor_lift);
register(crane_splitter);
register(drone_waypoint);
register(drone_waypoint_request);
register(drone_crate);
register(fan);
register(piston_inserter);

View File

@ -6,6 +6,7 @@ import java.util.Random;
import com.hbm.blocks.ILookOverlay;
import com.hbm.blocks.ITooltipProvider;
import com.hbm.items.ModItems;
import com.hbm.lib.RefStrings;
import com.hbm.main.MainRegistry;
import com.hbm.tileentity.network.TileEntityDroneCrate;
@ -59,6 +60,9 @@ public class DroneCrate extends BlockContainer implements ILookOverlay, ITooltip
@Override
public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int side, float hitX, float hitY, float hitZ) {
if(player.getHeldItem() != null && player.getHeldItem().getItem() == ModItems.drone_linker) return false;
if(world.isRemote) {
return true;
} else if(!player.isSneaking()) {

View File

@ -0,0 +1,100 @@
package com.hbm.blocks.network;
import com.hbm.tileentity.network.TileEntityDroneWaypointRequest;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.block.Block;
import net.minecraft.block.BlockContainer;
import net.minecraft.block.material.Material;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.Vec3;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
public class DroneWaypointRequest extends BlockContainer {
public DroneWaypointRequest() {
super(Material.circuits);
}
@Override
public TileEntity createNewTileEntity(World world, int meta) {
return new TileEntityDroneWaypointRequest();
}
@Override
public int getRenderType() {
return RadioTorchBase.renderID;
}
@Override
public boolean isOpaqueCube() {
return false;
}
@Override
public boolean renderAsNormalBlock() {
return false;
}
@Override
@SideOnly(Side.CLIENT)
public boolean shouldSideBeRendered(IBlockAccess world, int x, int y, int z, int side) {
return true;
}
@Override
public AxisAlignedBB getCollisionBoundingBoxFromPool(World world, int x, int y, int z) {
return null;
}
@Override
public MovingObjectPosition collisionRayTrace(World world, int x, int y, int z, Vec3 vec0, Vec3 vec1) {
int meta = world.getBlockMetadata(x, y, z) & 7;
ForgeDirection dir = ForgeDirection.getOrientation(meta);
this.setBlockBounds(
dir.offsetX == 1 ? 0F : 0.375F,
dir.offsetY == 1 ? 0F : 0.375F,
dir.offsetZ == 1 ? 0F : 0.375F,
dir.offsetX == -1 ? 1F : 0.625F,
dir.offsetY == -1 ? 1F : 0.625F,
dir.offsetZ == -1 ? 1F : 0.625F
);
return super.collisionRayTrace(world, x, y, z, vec0, vec1);
}
@Override
public int onBlockPlaced(World world, int x, int y, int z, int side, float fX, float fY, float fZ, int meta) {
return side;
}
@Override
public void onNeighborBlockChange(World world, int x, int y, int z, Block block) {
int meta = world.getBlockMetadata(x, y, z);
ForgeDirection dir = ForgeDirection.getOrientation(meta);
Block b = world.getBlock(x - dir.offsetX, y - dir.offsetY, z - dir.offsetZ);
if(!b.isSideSolid(world, x - dir.offsetX, y - dir.offsetY, z - dir.offsetZ, dir) && (!b.renderAsNormalBlock() || b.isAir(world, x, y, z))) {
this.dropBlockAsItem(world, x, y, z, meta, 0);
world.setBlockToAir(x, y, z);
}
}
@Override
public boolean canPlaceBlockOnSide(World world, int x, int y, int z, int side) {
if(!super.canPlaceBlockOnSide(world, x, y, z, side)) return false;
ForgeDirection dir = ForgeDirection.getOrientation(side);
Block b = world.getBlock(x - dir.offsetX, y - dir.offsetY, z - dir.offsetZ);
return b.isSideSolid(world, x - dir.offsetX, y - dir.offsetY, z - dir.offsetZ, dir) || (b.renderAsNormalBlock() && !b.isAir(world, x, y, z));
}
}

View File

@ -1,28 +1,25 @@
package com.hbm.entity.item;
import com.hbm.entity.logic.IChunkLoader;
import com.hbm.inventory.FluidStack;
import com.hbm.inventory.fluid.Fluids;
import com.hbm.main.MainRegistry;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.util.Vec3;
import net.minecraft.world.ChunkCoordIntPair;
import net.minecraft.world.World;
import net.minecraftforge.common.ForgeChunkManager;
import net.minecraftforge.common.ForgeChunkManager.Ticket;
import net.minecraftforge.common.ForgeChunkManager.Type;
public class EntityDeliveryDrone extends Entity implements IInventory {
protected int turnProgress;
protected double syncPosX;
protected double syncPosY;
protected double syncPosZ;
@SideOnly(Side.CLIENT) protected double velocityX;
@SideOnly(Side.CLIENT) protected double velocityY;
@SideOnly(Side.CLIENT) protected double velocityZ;
public class EntityDeliveryDrone extends EntityDroneBase implements IInventory, IChunkLoader {
protected ItemStack[] slots = new ItemStack[this.getSizeInventory()];
public FluidStack fluid;
@ -31,10 +28,24 @@ public class EntityDeliveryDrone extends Entity implements IInventory {
public double targetY = -1;
public double targetZ = -1;
private Ticket loaderTicket;
public boolean isChunkLoading = false;
public EntityDeliveryDrone(World world) {
super(world);
this.setSize(1.5F, 2.0F);
}
@Override
protected void entityInit() {
super.entityInit();
this.dataWatcher.addObject(11, new Byte((byte) 0));
}
public EntityDeliveryDrone setChunkLoading() {
init(ForgeChunkManager.requestTicket(MainRegistry.instance, worldObj, Type.ENTITY));
return this;
}
public void setTarget(double x, double y, double z) {
this.targetX = x;
@ -42,68 +53,11 @@ public class EntityDeliveryDrone extends Entity implements IInventory {
this.targetZ = z;
}
@Override
public boolean canBeCollidedWith() {
return true;
}
@Override
public boolean canAttackWithItem() {
return true;
}
@Override
public boolean hitByEntity(Entity attacker) {
if(attacker instanceof EntityPlayer) {
this.setDead();
}
return false;
}
@Override
protected boolean canTriggerWalking() {
return true;
}
@Override
protected void entityInit() {
this.dataWatcher.addObject(10, new Byte((byte) 0));
}
/**
* 0: Empty<br>
* 1: Crate<br>
* 2: Barrel<br>
*/
public void setAppearance(int style) {
this.dataWatcher.updateObject(10, (byte) style);
}
public int getAppearance() {
return this.dataWatcher.getWatchableObjectByte(10);
}
@Override
public void onUpdate() {
super.onUpdate();
if(worldObj.isRemote) {
if(this.turnProgress > 0) {
double interpX = this.posX + (this.syncPosX - this.posX) / (double) this.turnProgress;
double interpY = this.posY + (this.syncPosY - this.posY) / (double) this.turnProgress;
double interpZ = this.posZ + (this.syncPosZ - this.posZ) / (double) this.turnProgress;
--this.turnProgress;
this.setPosition(interpX, interpY, interpZ);
} else {
this.setPosition(this.posX, this.posY, this.posZ);
}
worldObj.spawnParticle("smoke", posX + 1.125, posY + 0.75, posZ, 0, -0.2, 0);
worldObj.spawnParticle("smoke", posX - 1.125, posY + 0.75, posZ, 0, -0.2, 0);
worldObj.spawnParticle("smoke", posX, posY + 0.75, posZ + 1.125, 0, -0.2, 0);
worldObj.spawnParticle("smoke", posX, posY + 0.75, posZ - 1.125, 0, -0.2, 0);
} else {
if(!worldObj.isRemote) {
this.motionX = 0;
this.motionY = 0;
@ -122,12 +76,15 @@ public class EntityDeliveryDrone extends Entity implements IInventory {
}
}
loadNeighboringChunks((int)Math.floor(posX / 16D), (int)Math.floor(posZ / 16D));
this.moveEntity(motionX, motionY, motionZ);
}
}
@Override
public double getSpeed() {
return 0.125D;
return this.dataWatcher.getWatchableObjectByte(11) == 1 ? 0.375 : 0.125;
}
@Override
@ -154,6 +111,9 @@ public class EntityDeliveryDrone extends Entity implements IInventory {
nbt.setString("fluidType", fluid.type.getUnlocalizedName());
nbt.setInteger("fluidAmount", fluid.fill);
}
nbt.setByte("app", this.dataWatcher.getWatchableObjectByte(10));
nbt.setByte("load", this.dataWatcher.getWatchableObjectByte(11));
}
@Override
@ -180,13 +140,9 @@ public class EntityDeliveryDrone extends Entity implements IInventory {
if(nbt.hasKey("fluidType")) {
this.fluid = new FluidStack(Fluids.fromName(nbt.getString("fluidType")), nbt.getInteger("fluidAmount"));
}
}
@SideOnly(Side.CLIENT)
public void setVelocity(double motionX, double motionY, double motionZ) {
this.velocityX = this.motionX = motionX;
this.velocityY = this.motionY = motionY;
this.velocityZ = this.motionZ = motionZ;
this.dataWatcher.updateObject(10, nbt.getByte("app"));
this.dataWatcher.updateObject(11, nbt.getByte("load"));
}
@SideOnly(Side.CLIENT)
@ -258,4 +214,38 @@ public class EntityDeliveryDrone extends Entity implements IInventory {
@Override public void markDirty() { }
@Override public void openInventory() { }
@Override public void closeInventory() { }
public void loadNeighboringChunks(int newChunkX, int newChunkZ) {
if(!worldObj.isRemote && loaderTicket != null) {
clearChunkLoader();
ForgeChunkManager.forceChunk(loaderTicket, new ChunkCoordIntPair(newChunkX, newChunkZ));
ForgeChunkManager.forceChunk(loaderTicket, new ChunkCoordIntPair(newChunkX + (int) Math.ceil((this.posX + this.motionX) / 16D), newChunkZ + (int) Math.ceil((this.posZ + this.motionZ) / 16D)));
}
}
@Override
public void setDead() {
super.setDead();
this.clearChunkLoader();
}
public void clearChunkLoader() {
if(!worldObj.isRemote && loaderTicket != null) {
for(ChunkCoordIntPair chunk : loaderTicket.getChunkList()) {
ForgeChunkManager.unforceChunk(loaderTicket, chunk);
}
}
}
@Override
public void init(Ticket ticket) {
if(!worldObj.isRemote && ticket != null) {
if(loaderTicket == null) {
loaderTicket = ticket;
loaderTicket.bindEntity(this);
loaderTicket.getModData();
}
ForgeChunkManager.forceChunk(loaderTicket, new ChunkCoordIntPair(chunkCoordX, chunkCoordZ));
}
}
}

View File

@ -0,0 +1,97 @@
package com.hbm.entity.item;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.world.World;
public abstract class EntityDroneBase extends Entity {
protected int turnProgress;
protected double syncPosX;
protected double syncPosY;
protected double syncPosZ;
@SideOnly(Side.CLIENT) protected double velocityX;
@SideOnly(Side.CLIENT) protected double velocityY;
@SideOnly(Side.CLIENT) protected double velocityZ;
public EntityDroneBase(World world) {
super(world);
}
@Override
public boolean canBeCollidedWith() {
return true;
}
@Override
public boolean canAttackWithItem() {
return true;
}
@Override
public boolean hitByEntity(Entity attacker) {
if(attacker instanceof EntityPlayer) {
this.setDead();
}
return false;
}
@Override
protected boolean canTriggerWalking() {
return true;
}
@Override
protected void entityInit() {
this.dataWatcher.addObject(10, new Byte((byte) 0));
}
/**
* 0: Empty<br>
* 1: Crate<br>
* 2: Barrel<br>
*/
public void setAppearance(int style) {
this.dataWatcher.updateObject(10, (byte) style);
}
public int getAppearance() {
return this.dataWatcher.getWatchableObjectByte(10);
}
@Override
public void onUpdate() {
if(worldObj.isRemote) {
if(this.turnProgress > 0) {
double interpX = this.posX + (this.syncPosX - this.posX) / (double) this.turnProgress;
double interpY = this.posY + (this.syncPosY - this.posY) / (double) this.turnProgress;
double interpZ = this.posZ + (this.syncPosZ - this.posZ) / (double) this.turnProgress;
--this.turnProgress;
this.setPosition(interpX, interpY, interpZ);
} else {
this.setPosition(this.posX, this.posY, this.posZ);
}
worldObj.spawnParticle("smoke", posX + 1.125, posY + 0.75, posZ, 0, -0.2, 0);
worldObj.spawnParticle("smoke", posX - 1.125, posY + 0.75, posZ, 0, -0.2, 0);
worldObj.spawnParticle("smoke", posX, posY + 0.75, posZ + 1.125, 0, -0.2, 0);
worldObj.spawnParticle("smoke", posX, posY + 0.75, posZ - 1.125, 0, -0.2, 0);
}
}
public double getSpeed() {
return 0.125D;
}
@SideOnly(Side.CLIENT)
public void setVelocity(double motionX, double motionY, double motionZ) {
this.velocityX = this.motionX = motionX;
this.velocityY = this.motionY = motionY;
this.velocityZ = this.motionZ = motionZ;
}
}

View File

@ -225,10 +225,6 @@ public class GUIMachineTurbineGas extends GuiInfoContainer {
int firstDigitX = 66;
int firstDigitY = 62;
int width = 5;
int height = 11;
int spaceBetweenBumbers = 3;
int[] digit = new int[6];
for(int i = 5; i >= 0; i--) { //creates an array of digits that represent the numbers

View File

@ -1038,6 +1038,7 @@ public class ModItems {
public static Item cart;
public static Item train;
public static Item drone;
public static Item coin_creeper;
public static Item coin_radiation;
@ -3456,6 +3457,7 @@ public class ModItems {
cart = new ItemModMinecart().setUnlocalizedName("cart");
train = new ItemTrain().setUnlocalizedName("train");
drone = new ItemDrone().setUnlocalizedName("drone");
coin_creeper = new ItemCustomLore().setRarity(EnumRarity.uncommon).setUnlocalizedName("coin_creeper").setCreativeTab(MainRegistry.consumableTab).setTextureName(RefStrings.MODID + ":coin_creeper");
coin_radiation = new ItemCustomLore().setRarity(EnumRarity.uncommon).setUnlocalizedName("coin_radiation").setCreativeTab(MainRegistry.consumableTab).setTextureName(RefStrings.MODID + ":coin_radiation");
@ -7696,6 +7698,7 @@ public class ModItems {
//Minecarts
GameRegistry.registerItem(cart, cart.getUnlocalizedName());
GameRegistry.registerItem(train, train.getUnlocalizedName());
GameRegistry.registerItem(drone, drone.getUnlocalizedName());
//High Explosive Lenses
GameRegistry.registerItem(early_explosive_lenses, early_explosive_lenses.getUnlocalizedName());

View File

@ -1,33 +0,0 @@
package com.hbm.items.special;
import com.hbm.items.ItemCustomLore;
import net.minecraft.entity.Entity;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
public class ItemAntiCheat extends ItemCustomLore {
@Override
public void onUpdate(ItemStack stack, World world, Entity entity, int j, boolean b) {
/*if(stack.getItemDamage() != 34) {
if(entity instanceof EntityPlayer) {
EntityPlayer player = (EntityPlayer)entity;
for(ItemStack s : player.inventory.mainInventory) {
player.inventory.consumeInventoryItem(ModItems.ingot_euphemium);
player.inventory.consumeInventoryItem(ModItems.nugget_euphemium);
}
}
//entity.attackEntityFrom(ModDamageSource.cheater, Float.POSITIVE_INFINITY);
for(int i = 0; i < 100; i++)
entity.attackEntityFrom(ModDamageSource.cheater, 10000);
//if(!world.isRemote)
// ExplosionChaos.antiCheat(world, (int)entity.posX, (int)entity.posY, (int)entity.posZ, 20);
}*/
}
}

View File

@ -0,0 +1,50 @@
package com.hbm.items.tool;
import com.hbm.entity.item.EntityDeliveryDrone;
import com.hbm.items.ItemEnumMulti;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
public class ItemDrone extends ItemEnumMulti {
public ItemDrone() {
super(EnumDroneType.class, true, true);
}
public static enum EnumDroneType {
PATROL,
PATROL_CHUNKLOADING,
PATROL_EXPRESS,
PATROL_EXPRESS_CHUNKLOADING,
REQUEST
}
@Override
public boolean onItemUse(ItemStack stack, EntityPlayer entity, World world, int x, int y, int z, int side, float fx, float fy, float fz) {
if(side != 1) return false;
if(world.isRemote) return true;
Entity toSpawn = null;
if(stack.getItemDamage() < 4) {
toSpawn = new EntityDeliveryDrone(world);
if(stack.getItemDamage() % 2 == 0) {
((EntityDeliveryDrone) toSpawn).setChunkLoading();
}
if(stack.getItemDamage() > 1) {
((EntityDeliveryDrone) toSpawn).getDataWatcher().updateObject(11, (byte) 1);
}
}
if(toSpawn != null) {
toSpawn.setPosition(x + 0.5, y + 1, z + 0.5);
world.spawnEntityInWorld(toSpawn);
}
return false;
}
}

View File

@ -1371,6 +1371,7 @@ public class ResourceManager {
//Drone
public static final ResourceLocation delivery_drone_tex = new ResourceLocation(RefStrings.MODID, "textures/models/machines/drone.png");
public static final ResourceLocation delivery_drone_express_tex = new ResourceLocation(RefStrings.MODID, "textures/models/machines/drone_express.png");
//ISBRHs
public static final IModelCustom scaffold = AdvancedModelLoader.loadModel(new ResourceLocation(RefStrings.MODID, "models/blocks/scaffold.obj"));

View File

@ -19,7 +19,11 @@ public class RenderDeliveryDrone extends Render {
GL11.glDisable(GL11.GL_CULL_FACE);
GL11.glShadeModel(GL11.GL_SMOOTH);
bindTexture(ResourceManager.delivery_drone_tex);
if(entity.getDataWatcher().getWatchableObjectByte(11) == 1)
bindTexture(ResourceManager.delivery_drone_express_tex);
else
bindTexture(ResourceManager.delivery_drone_tex);
ResourceManager.delivery_drone.renderPart("Drone");
EntityDeliveryDrone drone = (EntityDeliveryDrone) entity;

View File

@ -48,12 +48,9 @@ public class RenderGlyphid extends RenderLiving {
EntityLivingBase living = (EntityLivingBase) entity;
byte armor = living.getDataWatcher().getWatchableObjectByte(17);
//MainRegistry.proxy.displayTooltip("" + limbSwingAmount, 999);
double walkCycle = limbSwing;
double speed = 100000D;
double chewing = 200000D;
double cy0 = Math.sin(walkCycle % (Math.PI * 2));
double cy1 = Math.sin(walkCycle % (Math.PI * 2) - Math.PI * 0.5);
double cy2 = Math.sin(walkCycle % (Math.PI * 2) - Math.PI);

View File

@ -108,8 +108,6 @@ public class RenderGlyphidNuclear extends RenderLiving {
double walkCycle = limbSwing;
double speed = 100000D;
double chewing = 200000D;
double cy0 = Math.sin(walkCycle % (Math.PI * 2));
double cy1 = Math.sin(walkCycle % (Math.PI * 2) - Math.PI * 0.5);
double cy2 = Math.sin(walkCycle % (Math.PI * 2) - Math.PI);

View File

@ -393,6 +393,7 @@ public class TileMappings {
put(TileEntityRadioTelex.class, "tileentity_rtty_telex");
put(TileEntityDroneWaypoint.class, "tileentity_drone_waypoint");
put(TileEntityDroneWaypointRequest.class, "tileentity_drone_waypoint_request");
put(TileEntityDroneCrate.class, "tileentity_drone_crate");
}

View File

@ -19,7 +19,8 @@ public class TileEntityDroneWaypoint extends TileEntity implements INBTPacketRec
public int nextX = -1;
public int nextY = -1;
public int nextZ = -1;
@Override
public void updateEntity() {
ForgeDirection dir = ForgeDirection.getOrientation(this.getBlockMetadata());
@ -82,7 +83,8 @@ public class TileEntityDroneWaypoint extends TileEntity implements INBTPacketRec
@Override
public void readFromNBT(NBTTagCompound nbt) {
super.readFromNBT(nbt);
this.height = nbt.getInteger("height");
int[] pos = nbt.getIntArray("pos");
this.nextX = pos[0];
this.nextY = pos[1];
@ -92,7 +94,8 @@ public class TileEntityDroneWaypoint extends TileEntity implements INBTPacketRec
@Override
public void writeToNBT(NBTTagCompound nbt) {
super.writeToNBT(nbt);
nbt.setInteger("height", height);
nbt.setIntArray("pos", new int[] {nextX, nextY, nextZ});
}
}

View File

@ -0,0 +1,189 @@
package com.hbm.tileentity.network;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import com.hbm.util.ParticleUtil;
import com.hbm.util.fauxpointtwelve.BlockPos;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.MathHelper;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.Vec3;
import net.minecraft.world.ChunkCoordIntPair;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
public class TileEntityDroneWaypointRequest extends TileEntity {
public static HashMap<World, HashMap<ChunkCoordIntPair, Set<BlockPos>>> activeWaypoints = new HashMap();
public static HashMap<BlockPos, Long> lastActive = new HashMap();
public static long lastWipe = 0;
public Set<BlockPos> reachableNodes = new HashSet();
public Set<BlockPos> knownNodes = new HashSet();
public static final int maxRange = 24;
public static final int maxAge = 1_000;
public int height = 5;
@Override
public void updateEntity() {
if(!worldObj.isRemote) {
if(worldObj.getTotalWorldTime() % 20 == 0) {
BlockPos pos = getCoord();
push(worldObj, pos);
for(BlockPos known : knownNodes) {
ParticleUtil.spawnDebugLine(worldObj,
pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5,
(known.getX() - pos.getX()) / 2D, (known.getY() - pos.getY()) / 2D, (known.getZ() - pos.getZ()) / 2D,
reachableNodes.contains(known) ? 0x00ff00 : 0xff0000);
}
//rescan known nodes
if(worldObj.getTotalWorldTime() % 40 == 0 && knownNodes.size() > 0) {
BlockPos node = (BlockPos) new ArrayList(knownNodes).get(knownNodes.size() > 1 ? worldObj.rand.nextInt(knownNodes.size() - 1) : 0);
if(node != null) {
Long timestamp = lastActive.get(node);
if(timestamp == null || timestamp < System.currentTimeMillis() - maxAge) {
knownNodes.remove(node);
reachableNodes.remove(node);
lastActive.remove(node);
} else if(!hasPath(worldObj, pos, node)) {
reachableNodes.remove(node);
} else {
reachableNodes.add(node);
}
}
//discover new nodes
} else {
Set<BlockPos> nodes = getAllLocalNodes(worldObj, pos.getX(), pos.getZ());
for(BlockPos node : nodes) {
if(!knownNodes.contains(node) && !node.equals(pos)) {
knownNodes.add(node);
if(hasPath(worldObj, pos, node)) reachableNodes.add(node);
break;
}
}
}
}
}
}
public BlockPos getCoord() {
ForgeDirection dir = ForgeDirection.getOrientation(this.getBlockMetadata());
return new BlockPos(xCoord + dir.offsetX * height, yCoord + dir.offsetY * height, zCoord + dir.offsetZ * height);
}
public static boolean hasPath(World world, BlockPos pos1, BlockPos pos2) {
Vec3 vec1 = Vec3.createVectorHelper(pos1.getX() + 0.5, pos1.getY() + 0.5, pos1.getZ() + 0.5);
Vec3 vec2 = Vec3.createVectorHelper(pos2.getX() + 0.5, pos2.getY() + 0.5, pos2.getZ() + 0.5);
Vec3 vec3 = vec1.subtract(vec2);
if(vec3.lengthVector() > maxRange) return false;
//for some fucking reason beyond any human comprehension, this function will randomly yield incorrect results but only from one side
//therefore we just run the stupid fucking thing twice and then compare the results
//thanks for this marvelous piece of programming, mojang
MovingObjectPosition mop0 = world.func_147447_a(vec1, vec2, false, true, false);
MovingObjectPosition mop2 = world.func_147447_a(vec2, vec1, false, true, false);
return (mop0 == null || mop0.typeOfHit == mop0.typeOfHit.MISS) && (mop2 == null || mop2.typeOfHit == mop2.typeOfHit.MISS);
}
public void addHeight(int h) {
height += h;
height = MathHelper.clamp_int(height, 1, 15);
}
@Override
public void readFromNBT(NBTTagCompound nbt) {
super.readFromNBT(nbt);
this.height = nbt.getInteger("height");
}
@Override
public void writeToNBT(NBTTagCompound nbt) {
super.writeToNBT(nbt);
nbt.setInteger("height", height);
}
/**
* Adds the position to that chunk's node list.
* @param world
* @param x
* @param y
* @param z
*/
public static void push(World world, BlockPos pos) {
HashMap<ChunkCoordIntPair, Set<BlockPos>> coordMap = activeWaypoints.get(world);
if(coordMap == null) {
coordMap = new HashMap();
activeWaypoints.put(world, coordMap);
}
ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(pos.getX() >> 4, pos.getZ() >> 4);
Set<BlockPos> posList = coordMap.get(chunkPos);
if(posList == null) {
posList = new HashSet();
coordMap.put(chunkPos, posList);
}
posList.add(pos);
lastActive.put(pos, System.currentTimeMillis());
}
/**
* Gets all active nodes in a 5x5 chunk area, centered around the given position.
* Used for finding neighbors to check connections to.
* @param world
* @param x
* @param z
* @return
*/
public static Set<BlockPos> getAllLocalNodes(World world, int x, int z) {
Set<BlockPos> nodes = new HashSet();
x >>= 4;
z >>= 4;
HashMap<ChunkCoordIntPair, Set<BlockPos>> coordMap = activeWaypoints.get(world);
if(coordMap == null) return nodes;
for(int i = -2; i <= 2; i++) {
for(int j = -2; j <= 2; j++) {
Set<BlockPos> posList = coordMap.get(new ChunkCoordIntPair(x + i, z + j));
if(posList != null) for(BlockPos node : posList) {
Long timestamp = lastActive.get(node);
if(timestamp != null && timestamp >= System.currentTimeMillis() - maxAge) {
nodes.add(node);
}
}
}
}
return nodes;
}
}

View File

@ -27,4 +27,22 @@ public class ParticleUtil {
PacketDispatcher.wrapper.sendToAllAround(new AuxParticlePacketNT(data, x, y, z), new TargetPoint(world.provider.dimensionId, x, y, z, 150));
}
}
public static void spawnDebugLine(World world, double x, double y, double z, double x0, double y0, double z0, int color) {
NBTTagCompound data = new NBTTagCompound();
data.setString("type", "debugline");
data.setDouble("mX", x0);
data.setDouble("mY", y0);
data.setDouble("mZ", z0);
data.setInteger("color", color);
if(world.isRemote) {
data.setDouble("posX", x);
data.setDouble("posY", y);
data.setDouble("posZ", z);
MainRegistry.proxy.effectNT(data);
} else {
PacketDispatcher.wrapper.sendToAllAround(new AuxParticlePacketNT(data, x, y, z), new TargetPoint(world.provider.dimensionId, x, y, z, 150));
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 469 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 262 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 B

View File

@ -0,0 +1,5 @@
{
"animation": {
"frametime": 10
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 364 B

View File

Before

Width:  |  Height:  |  Size: 267 B

After

Width:  |  Height:  |  Size: 267 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 284 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB