diff --git a/src/main/java/noppes/npcs/DataAI.java b/src/main/java/noppes/npcs/DataAI.java index cf0c00a88..5011b9ce7 100644 --- a/src/main/java/noppes/npcs/DataAI.java +++ b/src/main/java/noppes/npcs/DataAI.java @@ -13,7 +13,7 @@ import noppes.npcs.constants.EnumStandingType; import noppes.npcs.entity.EntityNPCInterface; public class DataAI { - private EntityNPCInterface npc; + private EntityNPCInterface npc; public int onAttack = 0; //0:fight 1:panic 2:retreat 3:nothing public int doorInteract = 2; @@ -34,7 +34,7 @@ public class DataAI { public int tacticalRadius = 8; // Fly Change -// public int movementType = 0; + public int movementType = 0; public EnumAnimation animationType = EnumAnimation.NONE; public EnumStandingType standingType = EnumStandingType.RotateBody; @@ -96,6 +96,7 @@ public class DataAI { setMovingPath(NBTTags.getIntegerArraySet(compound.getTagList("MovingPathNew",10))); movingPos = compound.getInteger("MovingPos"); movingPattern = compound.getInteger("MovingPatern"); + movementType = compound.getInteger("MovingType"); startPos = compound.getIntArray("StartPosNew"); if (startPos == null || startPos.length != 3){ @@ -142,6 +143,7 @@ public class DataAI { compound.setTag("MovingPathNew", NBTTags.nbtIntegerArraySet(movingPath)); compound.setInteger("MovingPos", movingPos); compound.setInteger("MovingPatern", movingPattern); + compound.setInteger("MovingType", movementType); npc.setAvoidWater(avoidsWater); diff --git a/src/main/java/noppes/npcs/ai/EntityAIWander.java b/src/main/java/noppes/npcs/ai/EntityAIWander.java index f43cec6d1..7913edff5 100644 --- a/src/main/java/noppes/npcs/ai/EntityAIWander.java +++ b/src/main/java/noppes/npcs/ai/EntityAIWander.java @@ -50,6 +50,9 @@ public class EntityAIWander extends EntityAIBase else{ this.xPosition = vec.xCoord; this.yPosition = vec.yCoord; + // FLY CHANGE + if(entity.canFly()) + this.yPosition = entity.getStartYPos() + entity.getRNG().nextFloat() * 0.75 * entity.ai.walkingRange; this.zPosition = vec.zCoord; } } diff --git a/src/main/java/noppes/npcs/ai/pathfinder/FlyNodeProcessor.java b/src/main/java/noppes/npcs/ai/pathfinder/FlyNodeProcessor.java new file mode 100644 index 000000000..eecc15ddb --- /dev/null +++ b/src/main/java/noppes/npcs/ai/pathfinder/FlyNodeProcessor.java @@ -0,0 +1,73 @@ +package noppes.npcs.ai.pathfinder; + +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; +import net.minecraft.entity.Entity; +import net.minecraft.pathfinding.PathPoint; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.MathHelper; +import net.minecraft.util.math.BlockPos; +import noppes.npcs.entity.EntityNPCInterface; + +public class FlyNodeProcessor extends NodeProcessor{ + + public PathPoint getPathPointTo(Entity p_176161_1_) + { + return this.openPoint(MathHelper.floor_double(p_176161_1_.boundingBox.minX), MathHelper.floor_double(p_176161_1_.boundingBox.minY + 0.5D), MathHelper.floor_double(p_176161_1_.boundingBox.minZ)); + } + + public PathPoint getPathPointToCoords(Entity p_176160_1_, double p_176160_2_, double p_176160_4_, double p_176160_6_) + { + return this.openPoint(MathHelper.floor_double(p_176160_2_ - (double)(p_176160_1_.width / 2.0F)), MathHelper.floor_double(p_176160_4_ + 0.5D), MathHelper.floor_double(p_176160_6_ - (double)(p_176160_1_.width / 2.0F))); + } + + public int findPathOptions(PathPoint[] p_176164_1_, Entity p_176164_2_, PathPoint p_176164_3_, PathPoint p_176164_4_, float p_176164_5_) + { + int i = 0; + EnumFacing[] aenumfacing = EnumFacing.values(); + int j = aenumfacing.length; + + for (int k = 0; k < j; ++k) + { + EnumFacing enumfacing = aenumfacing[k]; + PathPoint pathpoint2 = this.getSafePoint(p_176164_2_, p_176164_3_.xCoord + enumfacing.getFrontOffsetX(), p_176164_3_.yCoord + enumfacing.getFrontOffsetY(), p_176164_3_.zCoord + enumfacing.getFrontOffsetZ()); + + if (pathpoint2 != null && !pathpoint2.isFirst && pathpoint2.distanceTo(p_176164_4_) < p_176164_5_) + { + p_176164_1_[i++] = pathpoint2; + } + } + + return i; + } + + private PathPoint getSafePoint(Entity p_176185_1_, int p_176185_2_, int p_176185_3_, int p_176185_4_) + { + int l = this.func_176186_b(p_176185_1_, p_176185_2_, p_176185_3_, p_176185_4_); + return l == -1 ? this.openPoint(p_176185_2_, p_176185_3_, p_176185_4_) : null; + } + + private int func_176186_b(Entity entityIn, int x, int y, int z) + { + + for (int i = x; i < x + this.entitySizeX; ++i) + { + for (int j = y; j < y + this.entitySizeY; ++j) + { + for (int k = z; k < z + this.entitySizeZ; ++k) + { + Block block = this.blockaccess.getBlock(i, j, k); + if(block.getMaterial() == Material.water && entityIn instanceof EntityNPCInterface && ((EntityNPCInterface)entityIn).ai.canSwim) + continue; + + if (block.getMaterial() != Material.air) + { + return 0; + } + } + } + } + + return -1; + } +} diff --git a/src/main/java/noppes/npcs/ai/pathfinder/FlyingMoveHelper.java b/src/main/java/noppes/npcs/ai/pathfinder/FlyingMoveHelper.java new file mode 100644 index 000000000..7031a9e00 --- /dev/null +++ b/src/main/java/noppes/npcs/ai/pathfinder/FlyingMoveHelper.java @@ -0,0 +1,67 @@ +package noppes.npcs.ai.pathfinder; + +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.EntityMoveHelper; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.MathHelper; +import noppes.npcs.entity.EntityNPCInterface; + +// Fly Change + +public class FlyingMoveHelper extends EntityMoveHelper { + private EntityNPCInterface entity; + + private int field_179928_h; + protected boolean update; + + public double posX; + public double posY; + public double posZ; + + public FlyingMoveHelper(EntityNPCInterface entity){ + super(entity); + this.entity = entity; + } + + public void onUpdateMoveHelper(){ + if (this.update){ + double d0 = this.posX - this.entity.posX; + double d1 = this.posY - this.entity.posY; + double d2 = this.posZ - this.entity.posZ; + double d3 = d0 * d0 + d1 * d1 + d2 * d2; + + if (this.field_179928_h-- <= 0){ + this.field_179928_h += this.entity.getRNG().nextInt(5) + 2; + d3 = (double) MathHelper.sqrt_double(d3); + + if (d3 > 1 && this.func_179926_b(this.posX, this.posY, this.posZ, d3)){ + double speed = entity.getEntityAttribute(SharedMonsterAttributes.movementSpeed).getAttributeValue() / 2.5; + this.entity.motionX += d0 / d3 * speed; + this.entity.motionY += d1 / d3 * speed; + this.entity.motionZ += d2 / d3 * speed; + this.entity.renderYawOffset = this.entity.rotationYaw = -((float)Math.atan2(this.entity.motionX, this.entity.motionZ)) * 180.0F / (float)Math.PI; + } + else{ + this.update = false; + } + } + } + } + + private boolean func_179926_b(double p_179926_1_, double p_179926_3_, double p_179926_5_, double p_179926_7_){ + double d4 = (p_179926_1_ - this.entity.posX) / p_179926_7_; + double d5 = (p_179926_3_ - this.entity.posY) / p_179926_7_; + double d6 = (p_179926_5_ - this.entity.posZ) / p_179926_7_; + AxisAlignedBB axisalignedbb = this.entity.getBoundingBox(); + + for (int i = 1; (double)i < p_179926_7_; ++i){ + axisalignedbb = axisalignedbb.offset(d4, d5, d6); + + if (!this.entity.worldObj.getCollidingBoundingBoxes(this.entity, axisalignedbb).isEmpty()){ + return false; + } + } + + return true; + } +} diff --git a/src/main/java/noppes/npcs/ai/pathfinder/NPCPathFinder.java b/src/main/java/noppes/npcs/ai/pathfinder/NPCPathFinder.java new file mode 100644 index 000000000..8383397d1 --- /dev/null +++ b/src/main/java/noppes/npcs/ai/pathfinder/NPCPathFinder.java @@ -0,0 +1,146 @@ +package noppes.npcs.ai.pathfinder; + +import net.minecraft.block.Block; +import net.minecraft.entity.Entity; +import net.minecraft.init.Blocks; +import net.minecraft.pathfinding.Path; +import net.minecraft.pathfinding.PathEntity; +import net.minecraft.pathfinding.PathFinder; +import net.minecraft.pathfinding.PathPoint; +import net.minecraft.util.MathHelper; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IBlockAccess; + +public class NPCPathFinder extends PathFinder +{ + + public IBlockAccess worldMap; + + public Path path = new Path(); + public NPCPathPoint[] pathOptions = new NPCPathPoint[32]; + + private final NodeProcessor nodeProcessor; + + public NPCPathFinder(NodeProcessor nodeProcessorIn) + { + super(nodeProcessorIn.blockaccess, true, true, false, false); + this.nodeProcessor = nodeProcessorIn; + } + + /** + * Creates a path from one entity to another within a minimum distance + */ + public PathEntity createEntityPathTo(Entity p_75856_1_, Entity p_75856_2_, float p_75856_3_) + { + return this.createEntityPathTo(p_75856_1_, p_75856_2_.posX, p_75856_2_.boundingBox.minY, p_75856_2_.posZ, p_75856_3_); + } + + /** + * Creates a path from an entity to a specified location within a minimum distance + */ + public PathEntity createEntityPathTo(Entity p_75859_1_, int p_75859_2_, int p_75859_3_, int p_75859_4_, float p_75859_5_) + { + return this.createEntityPathTo(p_75859_1_, (double)((float)p_75859_2_ + 0.5F), (double)((float)p_75859_3_ + 0.5F), (double)((float)p_75859_4_ + 0.5F), p_75859_5_); + } + + /** + * Internal implementation of creating a path from an entity to a point + */ + public PathEntity createEntityPathTo(Entity p_75857_1_, double p_75857_2_, double p_75857_4_, double p_75857_6_, float p_75857_8_) + { + this.path.clearPath(); + this.nodeProcessor.initProcessor(worldMap, p_75857_1_); + NPCPathPoint pathpoint = (NPCPathPoint) this.nodeProcessor.getPathPointTo(p_75857_1_); + NPCPathPoint pathpoint1 = (NPCPathPoint) this.nodeProcessor.getPathPointToCoords(p_75857_1_, p_75857_2_, p_75857_4_, p_75857_6_); + PathEntity pathentity = this.addToPath(p_75857_1_, pathpoint, pathpoint1, p_75857_8_); + this.nodeProcessor.postProcess(); + return pathentity; + } + + public PathEntity addToPath(Entity entityIn, NPCPathPoint pathpointStart, NPCPathPoint pathpointEnd, float maxDistance) + { + pathpointStart.totalPathDistance = 0.0F; + pathpointStart.distanceToNext = pathpointStart.distanceToSquared(pathpointEnd); + pathpointStart.distanceToTarget = pathpointStart.distanceToNext; + this.path.clearPath(); + this.path.addPoint(pathpointStart); + NPCPathPoint pathpoint = pathpointStart; + + while (!this.path.isPathEmpty()) + { + NPCPathPoint pathpoint1 = (NPCPathPoint) this.path.dequeue(); + + if (pathpoint1.equals(pathpointEnd)) + { + return this.createEntityPath(pathpointStart, pathpointEnd); + } + + if (pathpoint1.distanceToSquared(pathpointEnd) < pathpoint.distanceToSquared(pathpointEnd)) + { + pathpoint = pathpoint1; + } + + pathpoint1.isFirst = true; + int i = this.nodeProcessor.findPathOptions(this.pathOptions, entityIn, pathpoint1, pathpointEnd, maxDistance); + + for (int j = 0; j < i; ++j) + { + NPCPathPoint pathpoint2 = (NPCPathPoint) this.pathOptions[j]; + float f = pathpoint1.totalPathDistance + pathpoint1.distanceToSquared(pathpoint2); + + if (f < maxDistance * 2.0F && (!pathpoint2.isAssigned() || f < pathpoint2.totalPathDistance)) + { + pathpoint2.previous = pathpoint1; + pathpoint2.totalPathDistance = f; + pathpoint2.distanceToNext = pathpoint2.distanceToSquared(pathpointEnd); + + if (pathpoint2.isAssigned()) + { + this.path.changeDistance(pathpoint2, pathpoint2.totalPathDistance + pathpoint2.distanceToNext); + } + else + { + pathpoint2.distanceToTarget = pathpoint2.totalPathDistance + pathpoint2.distanceToNext; + this.path.addPoint(pathpoint2); + } + } + } + } + + if (pathpoint == pathpointStart) + { + return null; + } + else + { + return this.createEntityPath(pathpointStart, pathpoint); + } + } + + + /** + * Returns a new PathEntity for a given start and end point + */ + private PathEntity createEntityPath(NPCPathPoint p_75853_1_, NPCPathPoint p_75853_2_) + { + int i = 1; + NPCPathPoint pathpoint2; + + for (pathpoint2 = p_75853_2_; pathpoint2.previous != null; pathpoint2 = (NPCPathPoint) pathpoint2.previous) + { + ++i; + } + + NPCPathPoint[] apathpoint = new NPCPathPoint[i]; + pathpoint2 = p_75853_2_; + --i; + + for (apathpoint[i] = p_75853_2_; pathpoint2.previous != null; apathpoint[i] = pathpoint2) + { + pathpoint2 = (NPCPathPoint) pathpoint2.previous; + --i; + } + + return new PathEntity(apathpoint); + } +} diff --git a/src/main/java/noppes/npcs/ai/pathfinder/NPCPathPoint.java b/src/main/java/noppes/npcs/ai/pathfinder/NPCPathPoint.java new file mode 100644 index 000000000..3cbb824e9 --- /dev/null +++ b/src/main/java/noppes/npcs/ai/pathfinder/NPCPathPoint.java @@ -0,0 +1,23 @@ +package noppes.npcs.ai.pathfinder; + +import net.minecraft.pathfinding.PathPoint; +import net.minecraft.util.MathHelper; + +public class NPCPathPoint extends PathPoint +{ + /** The index of this point in its assigned path */ + public int index = -1; + /** The distance along the path to this point */ + public float totalPathDistance; + /** The linear distance to the next point */ + public float distanceToNext; + /** The distance to the target */ + public float distanceToTarget; + public PathPoint previous; + + public NPCPathPoint(int p_i2135_1_, int p_i2135_2_, int p_i2135_3_) + { + super(p_i2135_1_, p_i2135_2_,p_i2135_3_); + } + +} diff --git a/src/main/java/noppes/npcs/ai/pathfinder/NodeProcessor.java b/src/main/java/noppes/npcs/ai/pathfinder/NodeProcessor.java new file mode 100644 index 000000000..5ef60e03a --- /dev/null +++ b/src/main/java/noppes/npcs/ai/pathfinder/NodeProcessor.java @@ -0,0 +1,50 @@ +package noppes.npcs.ai.pathfinder; + +import net.minecraft.entity.Entity; +import net.minecraft.pathfinding.PathPoint; +import net.minecraft.util.IntHashMap; +import net.minecraft.util.MathHelper; +import net.minecraft.world.IBlockAccess; + +public abstract class NodeProcessor +{ + public IBlockAccess blockaccess; + public IntHashMap pointMap = new IntHashMap(); + public int entitySizeX; + public int entitySizeY; + public int entitySizeZ; + + + public void initProcessor(IBlockAccess iblockaccessIn, Entity entityIn) + { + this.blockaccess = iblockaccessIn; + this.pointMap.clearMap(); + this.entitySizeX = MathHelper.floor_float(entityIn.width + 1.0F); + this.entitySizeY = MathHelper.floor_float(entityIn.height + 1.0F); + this.entitySizeZ = MathHelper.floor_float(entityIn.width + 1.0F); + } + + public void postProcess() + { + } + + public PathPoint openPoint(int x, int y, int z) + { + int i = NPCPathPoint.makeHash(x, y, z); + NPCPathPoint pathpoint = (NPCPathPoint)this.pointMap.lookup(i); + + if (pathpoint == null) + { + pathpoint = new NPCPathPoint(x, y, z); + this.pointMap.addKey(i, pathpoint); + } + + return pathpoint; + } + + public abstract PathPoint getPathPointTo(Entity entityIn); + + public abstract PathPoint getPathPointToCoords(Entity entityIn, double x, double y, double target); + + public abstract int findPathOptions(PathPoint[] pathOptions, Entity entityIn, PathPoint currentPoint, PathPoint targetPoint, float maxDistance); +} diff --git a/src/main/java/noppes/npcs/ai/pathfinder/PathNavigateFlying.java b/src/main/java/noppes/npcs/ai/pathfinder/PathNavigateFlying.java new file mode 100644 index 000000000..9a3ab7207 --- /dev/null +++ b/src/main/java/noppes/npcs/ai/pathfinder/PathNavigateFlying.java @@ -0,0 +1,25 @@ +package noppes.npcs.ai.pathfinder; + +import net.minecraft.entity.EntityLiving; +import net.minecraft.pathfinding.PathFinder; +import net.minecraft.world.World; + +public class PathNavigateFlying extends PathNavigateSwimmer { + + public PathNavigateFlying(EntityLiving p_i45873_1_, World worldIn) { + super(p_i45873_1_, worldIn); + } + + protected PathFinder func_179679_a() + { + return new NPCPathFinder(new FlyNodeProcessor()); + } + + /** + * If on ground or swimming and can swim + */ + protected boolean canNavigate() + { + return true; + } +} diff --git a/src/main/java/noppes/npcs/ai/pathfinder/PathNavigateGround.java b/src/main/java/noppes/npcs/ai/pathfinder/PathNavigateGround.java new file mode 100644 index 000000000..e920def57 --- /dev/null +++ b/src/main/java/noppes/npcs/ai/pathfinder/PathNavigateGround.java @@ -0,0 +1,299 @@ +package noppes.npcs.ai.pathfinder; + +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.monster.EntityZombie; +import net.minecraft.entity.passive.EntityChicken; +import net.minecraft.init.Blocks; +import net.minecraft.pathfinding.PathFinder; +import net.minecraft.pathfinding.PathNavigate; +import net.minecraft.pathfinding.PathPoint; +import net.minecraft.util.MathHelper; +import net.minecraft.util.Vec3; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import noppes.npcs.util.Vec3NPC; + +public class PathNavigateGround extends PathNavigateNPC +{ + protected WalkNodeProcessor nodeProcessor; + private boolean shouldAvoidSun; + + public PathNavigateGround(EntityLiving entitylivingIn, World worldIn) + { + super(entitylivingIn, worldIn); + } + + protected PathFinder getPathFinder() + { + this.nodeProcessor = new WalkNodeProcessor(); + this.nodeProcessor.setEnterDoors(true); + return new NPCPathFinder(this.nodeProcessor); + } + + /** + * If on ground or swimming and can swim + */ + protected boolean canNavigate() + { + return this.theEntity.onGround || this.getCanSwim() && this.isInLiquid() || this.theEntity.isRiding() && this.theEntity instanceof EntityZombie && this.theEntity.ridingEntity instanceof EntityChicken; + } + + protected Vec3 getEntityPosition() + { + return new Vec3NPC(this.theEntity.posX, (double)this.getPathablePosY(), this.theEntity.posZ); + } + + /** + * Gets the safe pathing Y position for the entity depending on if it can path swim or not + */ + private int getPathablePosY() + { + if (this.theEntity.isInWater() && this.getCanSwim()) + { + int i = (int)this.theEntity.boundingBox.minY; + Block block = this.worldObj.getBlock(MathHelper.floor_double(this.theEntity.posX), i, MathHelper.floor_double(this.theEntity.posZ)); + int j = 0; + + while (block == Blocks.flowing_water || block == Blocks.water) + { + ++i; + block = this.worldObj.getBlock(MathHelper.floor_double(this.theEntity.posX), i, MathHelper.floor_double(this.theEntity.posZ)); + ++j; + + if (j > 16) + { + return (int)this.theEntity.boundingBox.minY; + } + } + + return i; + } + else + { + return (int)(this.theEntity.boundingBox.minY + 0.5D); + } + } + + /** + * Trims path data from the end to the first sun covered block + */ + protected void removeSunnyPath() + { + super.removeSunnyPath(); + + if (this.shouldAvoidSun) + { + if (this.worldObj.canBlockSeeTheSky(MathHelper.floor_double(this.theEntity.posX), (int)(this.theEntity.boundingBox.minY + 0.5D), MathHelper.floor_double(this.theEntity.posZ))) + { + return; + } + + for (int i = 0; i < this.currentPath.getCurrentPathLength(); ++i) + { + PathPoint pathpoint = this.currentPath.getPathPointFromIndex(i); + + if (this.worldObj.canBlockSeeTheSky(pathpoint.xCoord, pathpoint.yCoord, pathpoint.zCoord)) + { + this.currentPath.setCurrentPathLength(i - 1); + return; + } + } + } + } + + /** + * Returns true when an entity of specified size could safely walk in a straight line between the two points. Args: + * pos1, pos2, entityXSize, entityYSize, entityZSize + */ + protected boolean isDirectPathBetweenPoints(Vec3 posVec31, Vec3 posVec32, int sizeX, int sizeY, int sizeZ) + { + int i = MathHelper.floor_double(posVec31.xCoord); + int j = MathHelper.floor_double(posVec31.zCoord); + double d0 = posVec32.xCoord - posVec31.xCoord; + double d1 = posVec32.zCoord - posVec31.zCoord; + double d2 = d0 * d0 + d1 * d1; + + if (d2 < 1.0E-8D) + { + return false; + } + else + { + double d3 = 1.0D / Math.sqrt(d2); + d0 = d0 * d3; + d1 = d1 * d3; + sizeX = sizeX + 2; + sizeZ = sizeZ + 2; + + if (!this.isSafeToStandAt(i, (int)posVec31.yCoord, j, sizeX, sizeY, sizeZ, posVec31, d0, d1)) + { + return false; + } + else + { + sizeX = sizeX - 2; + sizeZ = sizeZ - 2; + double d4 = 1.0D / Math.abs(d0); + double d5 = 1.0D / Math.abs(d1); + double d6 = (double)(i * 1) - posVec31.xCoord; + double d7 = (double)(j * 1) - posVec31.zCoord; + + if (d0 >= 0.0D) + { + ++d6; + } + + if (d1 >= 0.0D) + { + ++d7; + } + + d6 = d6 / d0; + d7 = d7 / d1; + int k = d0 < 0.0D ? -1 : 1; + int l = d1 < 0.0D ? -1 : 1; + int i1 = MathHelper.floor_double(posVec32.xCoord); + int j1 = MathHelper.floor_double(posVec32.zCoord); + int k1 = i1 - i; + int l1 = j1 - j; + + while (k1 * k > 0 || l1 * l > 0) + { + if (d6 < d7) + { + d6 += d4; + i += k; + k1 = i1 - i; + } + else + { + d7 += d5; + j += l; + l1 = j1 - j; + } + + if (!this.isSafeToStandAt(i, (int)posVec31.yCoord, j, sizeX, sizeY, sizeZ, posVec31, d0, d1)) + { + return false; + } + } + + return true; + } + } + } + + /** + * Returns true when an entity could stand at a position, including solid blocks under the entire entity. + */ + private boolean isSafeToStandAt(int x, int y, int z, int sizeX, int sizeY, int sizeZ, Vec3 vec31, double p_179683_8_, double p_179683_10_) + { + int i = x - sizeX / 2; + int j = z - sizeZ / 2; + + if (!this.isPositionClear(i, y, j, sizeX, sizeY, sizeZ, vec31, p_179683_8_, p_179683_10_)) + { + return false; + } + else + { + for (int k = i; k < i + sizeX; ++k) + { + for (int l = j; l < j + sizeZ; ++l) + { + double d0 = (double)k + 0.5D - vec31.xCoord; + double d1 = (double)l + 0.5D - vec31.zCoord; + + if (d0 * p_179683_8_ + d1 * p_179683_10_ >= 0.0D) + { + Block block = this.worldObj.getBlock(k, y - 1, l); + Material material = block.getMaterial(); + + if (material == Material.air) + { + return false; + } + + if (material == Material.water && !this.theEntity.isInWater()) + { + return false; + } + + if (material == Material.lava) + { + return false; + } + } + } + } + + return true; + } + } + + /** + * Returns true if an entity does not collide with any solid blocks at the position. + */ + private boolean isPositionClear(int p_179692_1_, int p_179692_2_, int p_179692_3_, int p_179692_4_, int p_179692_5_, int p_179692_6_, Vec3 p_179692_7_, double p_179692_8_, double p_179692_10_) + { + for (BlockPos blockpos : BlockPos.getAllInBox(new BlockPos(p_179692_1_, p_179692_2_, p_179692_3_), new BlockPos(p_179692_1_ + p_179692_4_ - 1, p_179692_2_ + p_179692_5_ - 1, p_179692_3_ + p_179692_6_ - 1))) + { + double d0 = (double)blockpos.getX() + 0.5D - p_179692_7_.xCoord; + double d1 = (double)blockpos.getZ() + 0.5D - p_179692_7_.zCoord; + + if (d0 * p_179692_8_ + d1 * p_179692_10_ >= 0.0D) + { + Block block = this.worldObj.getBlock(blockpos.getX(), blockpos.getY(), blockpos.getZ()); + + if (!block.getBlocksMovement(this.worldObj, blockpos.getX(), blockpos.getY(), blockpos.getZ())) + { + return false; + } + } + } + + return true; + } + + public void setAvoidsWater(boolean avoidsWater) + { + this.nodeProcessor.setAvoidsWater(avoidsWater); + } + + public boolean getAvoidsWater() + { + return this.nodeProcessor.getAvoidsWater(); + } + + public void setBreakDoors(boolean canBreakDoors) + { + this.nodeProcessor.setBreakDoors(canBreakDoors); + } + + public void setEnterDoors(boolean par1) + { + this.nodeProcessor.setEnterDoors(par1); + } + + public boolean getEnterDoors() + { + return this.nodeProcessor.getEnterDoors(); + } + + public void setCanSwim(boolean canSwim) + { + this.nodeProcessor.setCanSwim(canSwim); + } + + public boolean getCanSwim() + { + return this.nodeProcessor.getCanSwim(); + } + + public void setAvoidSun(boolean par1) + { + this.shouldAvoidSun = par1; + } +} \ No newline at end of file diff --git a/src/main/java/noppes/npcs/ai/pathfinder/PathNavigateNPC.java b/src/main/java/noppes/npcs/ai/pathfinder/PathNavigateNPC.java new file mode 100644 index 000000000..41b781a73 --- /dev/null +++ b/src/main/java/noppes/npcs/ai/pathfinder/PathNavigateNPC.java @@ -0,0 +1,88 @@ +package noppes.npcs.ai.pathfinder; + +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.attributes.IAttributeInstance; +import net.minecraft.entity.monster.EntityZombie; +import net.minecraft.entity.passive.EntityChicken; +import net.minecraft.init.Blocks; +import net.minecraft.pathfinding.PathEntity; +import net.minecraft.pathfinding.PathNavigate; +import net.minecraft.pathfinding.PathPoint; +import net.minecraft.util.MathHelper; +import net.minecraft.util.Vec3; +import net.minecraft.world.World; + +public class PathNavigateNPC extends PathNavigate +{ + protected EntityLiving theEntity; + protected World worldObj; + /** The PathEntity being followed. */ + protected PathEntity currentPath; + + /** Time, in number of ticks, following the current path */ + protected int totalTicks; + /** The time when the last position check was done (to detect successful movement) */ + protected int ticksAtLastPos; + /** Coordinates of the entity's position last time a check was done (part of monitoring getting 'stuck') */ + protected Vec3 lastPosCheck = Vec3.createVectorHelper(0.0D, 0.0D, 0.0D); + + public PathNavigateNPC(EntityLiving p_i1671_1_, World p_i1671_2_) + { + super(p_i1671_1_, p_i1671_2_); + this.theEntity = p_i1671_1_; + this.worldObj = p_i1671_2_; + } + + /** Gets Current Path of NPC **/ + public PathEntity getPath() + { + return this.currentPath; + } + + + /** Returns true if the entity is in water or lava, false otherwise **/ + protected boolean isInLiquid() + { + return this.theEntity.isInWater() || this.theEntity.handleLavaMovement(); + } + + /** Trims path data from the end to the first sun covered block **/ + protected void removeSunnyPath() + { + if (!this.worldObj.canBlockSeeTheSky(MathHelper.floor_double(this.theEntity.posX), (int)(this.theEntity.boundingBox.minY + 0.5D), MathHelper.floor_double(this.theEntity.posZ))) + { + for (int i = 0; i < this.currentPath.getCurrentPathLength(); ++i) + { + PathPoint pathpoint = this.currentPath.getPathPointFromIndex(i); + + if (this.worldObj.canBlockSeeTheSky(pathpoint.xCoord, pathpoint.yCoord, pathpoint.zCoord)) + { + this.currentPath.setCurrentPathLength(i - 1); + return; + } + } + } + } + + /** + * Checks if entity haven't been moved when last checked and if so, clears current {@link + * net.minecraft.pathfinding.PathEntity} + */ + protected void checkForStuck(Vec3 positionVec3) + { + if (this.totalTicks - this.ticksAtLastPos > 100) + { + if (positionVec3.squareDistanceTo(this.lastPosCheck) < 2.25D) + { + this.clearPathEntity(); + } + + this.ticksAtLastPos = this.totalTicks; + this.lastPosCheck = positionVec3; + } + } +} diff --git a/src/main/java/noppes/npcs/ai/pathfinder/PathNavigateSwimmer.java b/src/main/java/noppes/npcs/ai/pathfinder/PathNavigateSwimmer.java new file mode 100644 index 000000000..39493ba36 --- /dev/null +++ b/src/main/java/noppes/npcs/ai/pathfinder/PathNavigateSwimmer.java @@ -0,0 +1,80 @@ +package noppes.npcs.ai.pathfinder; + +import net.minecraft.entity.EntityLiving; +import net.minecraft.pathfinding.PathFinder; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.util.Vec3; +import net.minecraft.world.World; +import noppes.npcs.ai.pathfinder.NPCPathFinder; +import noppes.npcs.ai.pathfinder.PathNavigateNPC; +import noppes.npcs.ai.pathfinder.SwimNodeProcessor; +import noppes.npcs.util.Vec3NPC; + +public class PathNavigateSwimmer extends PathNavigateNPC +{ + public PathNavigateSwimmer(EntityLiving entitylivingIn, World worldIn) + { + super(entitylivingIn, worldIn); + } + + protected PathFinder getPathFinder() + { + return new NPCPathFinder(new SwimNodeProcessor()); + } + + /** + * If on ground or swimming and can swim + */ + protected boolean canNavigate() + { + return this.isInLiquid(); + } + + protected Vec3 getEntityPosition() + { + return new Vec3NPC(this.theEntity.posX, this.theEntity.posY + (double)this.theEntity.height * 0.5D, this.theEntity.posZ); + } + + protected void pathFollow() + { + Vec3 vec3 = this.getEntityPosition(); + float f = this.theEntity.width * this.theEntity.width; + int i = 6; + + if (vec3.squareDistanceTo(this.currentPath.getVectorFromIndex(this.theEntity, this.currentPath.getCurrentPathIndex())) < (double)f) + { + this.currentPath.incrementPathIndex(); + } + + for (int j = Math.min(this.currentPath.getCurrentPathIndex() + i, this.currentPath.getCurrentPathLength() - 1); j > this.currentPath.getCurrentPathIndex(); --j) + { + Vec3 vec31 = this.currentPath.getVectorFromIndex(this.theEntity, j); + + if (vec31.squareDistanceTo(vec3) <= 36.0D && this.isDirectPathBetweenPoints(vec3, vec31, 0, 0, 0)) + { + this.currentPath.setCurrentPathIndex(j); + break; + } + } + + this.checkForStuck(vec3); + } + + /** + * Trims path data from the end to the first sun covered block + */ + protected void removeSunnyPath() + { + super.removeSunnyPath(); + } + + /** + * Returns true when an entity of specified size could safely walk in a straight line between the two points. Args: + * pos1, pos2, entityXSize, entityYSize, entityZSize + */ + protected boolean isDirectPathBetweenPoints(Vec3 posVec31, Vec3 posVec32, int sizeX, int sizeY, int sizeZ) + { + MovingObjectPosition movingobjectposition = this.worldObj.func_147447_a(posVec31, new Vec3NPC(posVec32.xCoord, posVec32.yCoord + (double)this.theEntity.height * 0.5D, posVec32.zCoord), false, true, false); + return movingobjectposition == null || movingobjectposition.typeOfHit == MovingObjectPosition.MovingObjectType.MISS; + } +} diff --git a/src/main/java/noppes/npcs/ai/pathfinder/SwimNodeProcessor.java b/src/main/java/noppes/npcs/ai/pathfinder/SwimNodeProcessor.java new file mode 100644 index 000000000..2fb31c70d --- /dev/null +++ b/src/main/java/noppes/npcs/ai/pathfinder/SwimNodeProcessor.java @@ -0,0 +1,93 @@ +package noppes.npcs.ai.pathfinder; + +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; +import net.minecraft.entity.Entity; +import net.minecraft.pathfinding.PathPoint; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.MathHelper; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IBlockAccess; + +public class SwimNodeProcessor extends NodeProcessor +{ + public void initProcessor(IBlockAccess iblockaccessIn, Entity entityIn) + { + super.initProcessor(iblockaccessIn, entityIn); + } + + /** + * This method is called when all nodes have been processed and PathEntity is created. + * {@link net.minecraft.world.pathfinder.WalkNodeProcessor WalkNodeProcessor} uses this to change its field {@link + * net.minecraft.world.pathfinder.WalkNodeProcessor#avoidsWater avoidsWater} + */ + public void postProcess() + { + super.postProcess(); + } + + /** + * Returns given entity's position as PathPoint + */ + public PathPoint getPathPointTo(Entity entityIn) + { + return this.openPoint(MathHelper.floor_double(entityIn.boundingBox.minX), MathHelper.floor_double(entityIn.boundingBox.minY + 0.5D), MathHelper.floor_double(entityIn.boundingBox.minZ)); + } + + /** + * Returns PathPoint for given coordinates + */ + public PathPoint getPathPointToCoords(Entity entityIn, double x, double y, double target) + { + return this.openPoint(MathHelper.floor_double(x - (double)(entityIn.width / 2.0F)), MathHelper.floor_double(y + 0.5D), MathHelper.floor_double(target - (double)(entityIn.width / 2.0F))); + } + + public int findPathOptions(PathPoint[] pathOptions, Entity entityIn, PathPoint currentPoint, PathPoint targetPoint, float maxDistance) + { + int i = 0; + + for (EnumFacing enumfacing : EnumFacing.values()) + { + PathPoint pathpoint = this.getSafePoint(entityIn, currentPoint.xCoord + enumfacing.getFrontOffsetX(), currentPoint.yCoord + enumfacing.getFrontOffsetY(), currentPoint.zCoord + enumfacing.getFrontOffsetZ()); + + if (pathpoint != null && !pathpoint.isFirst && pathpoint.distanceTo(targetPoint) < maxDistance) + { + pathOptions[i++] = pathpoint; + } + } + + return i; + } + + /** + * Returns a point that the entity can safely move to + */ + private PathPoint getSafePoint(Entity entityIn, int x, int y, int z) + { + int i = this.func_176186_b(entityIn, x, y, z); + return i == -1 ? this.openPoint(x, y, z) : null; + } + + private int func_176186_b(Entity entityIn, int x, int y, int z) + { + BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos(); + + for (int i = x; i < x + this.entitySizeX; ++i) + { + for (int j = y; j < y + this.entitySizeY; ++j) + { + for (int k = z; k < z + this.entitySizeZ; ++k) + { + Block block = this.blockaccess.getBlock(i, j, k); + + if (block.getMaterial() != Material.water) + { + return 0; + } + } + } + } + + return -1; + } +} diff --git a/src/main/java/noppes/npcs/ai/pathfinder/WalkNodeProcessor.java b/src/main/java/noppes/npcs/ai/pathfinder/WalkNodeProcessor.java new file mode 100644 index 000000000..48ceeaf82 --- /dev/null +++ b/src/main/java/noppes/npcs/ai/pathfinder/WalkNodeProcessor.java @@ -0,0 +1,303 @@ +package noppes.npcs.ai.pathfinder; + +import net.minecraft.block.*; +import net.minecraft.block.material.Material; +import net.minecraft.entity.Entity; +import net.minecraft.init.Blocks; +import net.minecraft.pathfinding.PathPoint; +import net.minecraft.util.MathHelper; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IBlockAccess; + +public class WalkNodeProcessor extends NodeProcessor +{ + private boolean canEnterDoors; + private boolean canBreakDoors; + private boolean avoidsWater; + private boolean canSwim; + private boolean shouldAvoidWater; + + public void initProcessor(IBlockAccess iblockaccessIn, Entity entityIn) + { + super.initProcessor(iblockaccessIn, entityIn); + this.shouldAvoidWater = this.avoidsWater; + } + + /** + * This method is called when all nodes have been processed and PathEntity is created. + * {@link noppes.npcs.ai.pathfinder.WalkNodeProcessor WalkNodeProcessor} uses this to change its field {@link + * noppes.npcs.ai.pathfinder.WalkNodeProcessor#avoidsWater avoidsWater} + */ + public void postProcess() + { + super.postProcess(); + this.avoidsWater = this.shouldAvoidWater; + } + + /** + * Returns given entity's position as PathPoint + */ + public PathPoint getPathPointTo(Entity entityIn) + { + int i; + + if (this.canSwim && entityIn.isInWater()) + { + i = (int)entityIn.boundingBox.minY; + BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos(MathHelper.floor_double(entityIn.posX), i, MathHelper.floor_double(entityIn.posZ)); + + for (Block block = this.blockaccess.getBlock(blockpos$mutableblockpos.getX(), blockpos$mutableblockpos.getY(), blockpos$mutableblockpos.getZ()); block == Blocks.flowing_water || block == Blocks.water; block = this.blockaccess.getBlock(blockpos$mutableblockpos.getX(), blockpos$mutableblockpos.getY(), blockpos$mutableblockpos.getZ())) + { + ++i; + blockpos$mutableblockpos.set(MathHelper.floor_double(entityIn.posX), i, MathHelper.floor_double(entityIn.posZ)); + } + + this.avoidsWater = false; + } + else + { + i = MathHelper.floor_double(entityIn.boundingBox.minY + 0.5D); + } + + return this.openPoint(MathHelper.floor_double(entityIn.boundingBox.minX), i, MathHelper.floor_double(entityIn.boundingBox.minZ)); + } + + /** + * Returns PathPoint for given coordinates + */ + public PathPoint getPathPointToCoords(Entity entityIn, double x, double y, double target) + { + return this.openPoint(MathHelper.floor_double(x - (double)(entityIn.width / 2.0F)), MathHelper.floor_double(y), MathHelper.floor_double(target - (double)(entityIn.width / 2.0F))); + } + + public int findPathOptions(PathPoint[] pathOptions, Entity entityIn, PathPoint currentPoint, PathPoint targetPoint, float maxDistance) + { + int i = 0; + int j = 0; + + if (this.getVerticalOffset(entityIn, currentPoint.xCoord, currentPoint.yCoord + 1, currentPoint.zCoord) == 1) + { + j = 1; + } + + PathPoint pathpoint = this.getSafePoint(entityIn, currentPoint.xCoord, currentPoint.yCoord, currentPoint.zCoord + 1, j); + PathPoint pathpoint1 = this.getSafePoint(entityIn, currentPoint.xCoord - 1, currentPoint.yCoord, currentPoint.zCoord, j); + PathPoint pathpoint2 = this.getSafePoint(entityIn, currentPoint.xCoord + 1, currentPoint.yCoord, currentPoint.zCoord, j); + PathPoint pathpoint3 = this.getSafePoint(entityIn, currentPoint.xCoord, currentPoint.yCoord, currentPoint.zCoord - 1, j); + + if (pathpoint != null && !pathpoint.isFirst && pathpoint.distanceTo(targetPoint) < maxDistance) + { + pathOptions[i++] = pathpoint; + } + + if (pathpoint1 != null && !pathpoint1.isFirst && pathpoint1.distanceTo(targetPoint) < maxDistance) + { + pathOptions[i++] = pathpoint1; + } + + if (pathpoint2 != null && !pathpoint2.isFirst && pathpoint2.distanceTo(targetPoint) < maxDistance) + { + pathOptions[i++] = pathpoint2; + } + + if (pathpoint3 != null && !pathpoint3.isFirst && pathpoint3.distanceTo(targetPoint) < maxDistance) + { + pathOptions[i++] = pathpoint3; + } + + return i; + } + + /** + * Returns a point that the entity can safely move to + */ + private PathPoint getSafePoint(Entity entityIn, int x, int y, int z, int p_176171_5_) + { + PathPoint pathpoint = null; + int i = this.getVerticalOffset(entityIn, x, y, z); + + if (i == 2) + { + return this.openPoint(x, y, z); + } + else + { + if (i == 1) + { + pathpoint = this.openPoint(x, y, z); + } + + if (pathpoint == null && p_176171_5_ > 0 && i != -3 && i != -4 && this.getVerticalOffset(entityIn, x, y + p_176171_5_, z) == 1) + { + pathpoint = this.openPoint(x, y + p_176171_5_, z); + y += p_176171_5_; + } + + if (pathpoint != null) + { + int j = 0; + int k; + + for (k = 0; y > 0; pathpoint = this.openPoint(x, y, z)) + { + k = this.getVerticalOffset(entityIn, x, y - 1, z); + + if (this.avoidsWater && k == -1) + { + return null; + } + + if (k != 1) + { + break; + } + + if (j++ >= entityIn.getMaxSafePointTries()) + { + return null; + } + + --y; + + if (y <= 0) + { + return null; + } + } + + if (k == -2) + { + return null; + } + } + + return pathpoint; + } + } + + /** + * Checks if an entity collides with blocks at a position. + * Returns 1 if clear, 0 for colliding with any solid block, -1 for water(if avoids water), + * -2 for lava, -3 for fence and wall, -4 for closed trapdoor, 2 if otherwise clear except for open trapdoor or + * water(if not avoiding) + */ + private int getVerticalOffset(Entity entityIn, int x, int y, int z) + { + return func_176170_a(this.blockaccess, entityIn, x, y, z, this.entitySizeX, this.entitySizeY, this.entitySizeZ, this.avoidsWater, this.canBreakDoors, this.canEnterDoors); + } + + public static int func_176170_a(IBlockAccess blockaccessIn, Entity entityIn, int x, int y, int z, int sizeX, int sizeY, int sizeZ, boolean avoidWater, boolean breakDoors, boolean enterDoors) + { + boolean flag = false; + BlockPos blockpos = new BlockPos(entityIn); + BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos(); + + for (int i = x; i < x + sizeX; ++i) + { + for (int j = y; j < y + sizeY; ++j) + { + for (int k = z; k < z + sizeZ; ++k) + { + blockpos$mutableblockpos.set(i, j, k); + Block block = blockaccessIn.getBlock(blockpos$mutableblockpos.getX(), blockpos$mutableblockpos.getY(), blockpos$mutableblockpos.getZ()); + + if (block.getMaterial() != Material.air) + { + if (block != Blocks.trapdoor) + { + if (block != Blocks.flowing_water && block != Blocks.water) + { + if (!enterDoors && block instanceof BlockDoor && block.getMaterial() == Material.wood) + { + return 0; + } + } + else + { + if (avoidWater) + { + return -1; + } + + flag = true; + } + } + else + { + flag = true; + } + + if (entityIn.worldObj.getBlock(blockpos$mutableblockpos.getX(), blockpos$mutableblockpos.getY(), blockpos$mutableblockpos.getZ()) instanceof BlockRailBase) + { + if (!(entityIn.worldObj.getBlock(blockpos.getX(), blockpos.getY(), blockpos.getZ()) instanceof BlockRailBase) && !(entityIn.worldObj.getBlock(blockpos.down().getX(), blockpos.down().getY(), blockpos.down().getZ()) instanceof BlockRailBase)) + { + return -3; + } + } + else if (!block.getBlocksMovement(blockaccessIn, blockpos$mutableblockpos.getX(), blockpos$mutableblockpos.getY(), blockpos$mutableblockpos.getZ()) && (!breakDoors || !(block instanceof BlockDoor) || block.getMaterial() != Material.wood)) + { + if (block instanceof BlockFence || block instanceof BlockFenceGate || block instanceof BlockWall) + { + return -3; + } + + if (block == Blocks.trapdoor) + { + return -4; + } + + Material material = block.getMaterial(); + + if (material != Material.lava) + { + return 0; + } + + if (!entityIn.handleLavaMovement()) + { + return -2; + } + } + } + } + } + } + + return flag ? 2 : 1; + } + + public void setEnterDoors(boolean canEnterDoorsIn) + { + this.canEnterDoors = canEnterDoorsIn; + } + + public void setBreakDoors(boolean canBreakDoorsIn) + { + this.canBreakDoors = canBreakDoorsIn; + } + + public void setAvoidsWater(boolean avoidsWaterIn) + { + this.avoidsWater = avoidsWaterIn; + } + + public void setCanSwim(boolean canSwimIn) + { + this.canSwim = canSwimIn; + } + + public boolean getEnterDoors() + { + return this.canEnterDoors; + } + + public boolean getCanSwim() + { + return this.canSwim; + } + + public boolean getAvoidsWater() + { + return this.avoidsWater; + } +} \ No newline at end of file diff --git a/src/main/java/noppes/npcs/client/gui/SubGuiNpcMovement.java b/src/main/java/noppes/npcs/client/gui/SubGuiNpcMovement.java index 76e6d1d13..c9f63ddf6 100644 --- a/src/main/java/noppes/npcs/client/gui/SubGuiNpcMovement.java +++ b/src/main/java/noppes/npcs/client/gui/SubGuiNpcMovement.java @@ -28,7 +28,10 @@ public class SubGuiNpcMovement extends SubGuiInterface implements ITextfieldList int y = guiTop + 4; this.addLabel(new GuiNpcLabel(0, "movement.type", guiLeft + 4, y + 5)); this.addButton(new GuiNpcButton(0, guiLeft + 80, y, 100, 20, EnumMovingType.names(), ai.movingType.ordinal())); - + + // Fly Change + // this.addButton(new GuiNpcButton(15, guiLeft + 80, y += 22, 100, 20, new String[]{"movement.ground","movement.flying"}, ai.movementType)); + if(ai.movingType == EnumMovingType.Wandering){ addTextField(new GuiNpcTextField(4,this, guiLeft + 100, y += 22, 40, 20, ai.walkingRange + "")); getTextField(4).numbersOnly = true; @@ -141,6 +144,9 @@ public class SubGuiNpcMovement extends SubGuiInterface implements ITextfieldList else if (button.id == 13) { ai.stopAndInteract = button.getValue() == 1; } + else if (button.id == 15) { + ai.movementType = button.getValue(); + } else if(button.id == 66){ close(); } diff --git a/src/main/java/noppes/npcs/entity/EntityCustomNpc.java b/src/main/java/noppes/npcs/entity/EntityCustomNpc.java index b6c4316ca..52dbcf775 100644 --- a/src/main/java/noppes/npcs/entity/EntityCustomNpc.java +++ b/src/main/java/noppes/npcs/entity/EntityCustomNpc.java @@ -1,6 +1,7 @@ package noppes.npcs.entity; import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityFlying; import net.minecraft.entity.EntityLivingBase; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; @@ -9,9 +10,12 @@ import noppes.npcs.ModelData; import noppes.npcs.ModelPartData; import noppes.npcs.client.EntityUtil; -public class EntityCustomNpc extends EntityNPCInterface{ +// FLY CHANGE +// extends EntityNPCInterface +// extends EntityNPCFlying +public class EntityCustomNpc extends EntityNPCFlying { public ModelData modelData = new ModelData(); - + public EntityCustomNpc(World world) { super(world); } diff --git a/src/main/java/noppes/npcs/entity/EntityNPCFlying.java b/src/main/java/noppes/npcs/entity/EntityNPCFlying.java index 8db2a4418..3fd6ca295 100644 --- a/src/main/java/noppes/npcs/entity/EntityNPCFlying.java +++ b/src/main/java/noppes/npcs/entity/EntityNPCFlying.java @@ -18,82 +18,82 @@ public abstract class EntityNPCFlying extends EntityNPCInterface { // FLY CHANGE [WIP] -// @Override -// public boolean canFly(){ -// return ai.movementType == 1; -// } -// -// @Override -// public void fall(float distance) { -// if(!canFly()) -// super.fall(distance); -// } -// -// @Override -// protected void updateFallState(double p_180433_1_, boolean p_180433_3_) { -// if(!canFly()) -// super.updateFallState(p_180433_1_, p_180433_3_); -// } -// -// @Override -// public void moveEntityWithHeading(float p_70612_1_, float p_70612_2_){ -// if(!canFly()){ -// super.moveEntityWithHeading(p_70612_1_, p_70612_2_); -// return; -// } -// -// if (this.isInWater()){ -// this.moveFlying(p_70612_1_, p_70612_2_, 0.02F); -// this.moveEntity(this.motionX, this.motionY, this.motionZ); -// this.motionX *= 0.800000011920929D; -// this.motionY *= 0.800000011920929D; -// this.motionZ *= 0.800000011920929D; -// } -// else if (this.isInsideOfMaterial(Material.lava)){ -// this.moveFlying(p_70612_1_, p_70612_2_, 0.02F); -// this.moveEntity(this.motionX, this.motionY, this.motionZ); -// this.motionX *= 0.5D; -// this.motionY *= 0.5D; -// this.motionZ *= 0.5D; -// } -// else{ -// float f2 = 0.91F; -// -// if (this.onGround){ -// f2 = this.worldObj.getBlock((int)this.posX, (int)this.boundingBox.minY - 1, (int)this.posZ).slipperiness * 0.91F; -// } -// -// float f3 = 0.16277136F / (f2 * f2 * f2); -// this.moveFlying(p_70612_1_, p_70612_2_, this.onGround ? 0.1F * f3 : 0.02F); -// f2 = 0.91F; -// -// if (this.onGround){ -// f2 = this.worldObj.getBlock((int)this.posX, (int)this.boundingBox.minY - 1, (int)this.posZ).slipperiness * 0.91F; -// } -// -// this.moveEntity(this.motionX, this.motionY, this.motionZ); -// this.motionX *= (double)f2; -// this.motionY *= (double)f2; -// this.motionZ *= (double)f2; -// } -// -// this.prevLimbSwingAmount = this.limbSwingAmount; -// double d1 = this.posX - this.prevPosX; -// double d0 = this.posZ - this.prevPosZ; -// float f4 = MathHelper.sqrt_double(d1 * d1 + d0 * d0) * 4.0F; -// -// if (f4 > 1.0F){ -// f4 = 1.0F; -// } -// -// this.limbSwingAmount += (f4 - this.limbSwingAmount) * 0.4F; -// this.limbSwing += this.limbSwingAmount; -// } -// -// @Override -// public boolean isOnLadder(){ -// return false; -// } + @Override + public boolean canFly(){ + return ai.movementType == 1; + } + + @Override + public void fall(float distance) { + if(!canFly()) + super.fall(distance); + } + + @Override + protected void updateFallState(double p_180433_1_, boolean p_180433_3_) { + if(!canFly()) + super.updateFallState(p_180433_1_, p_180433_3_); + } + + @Override + public void moveEntityWithHeading(float p_70612_1_, float p_70612_2_){ + if(!canFly()){ + super.moveEntityWithHeading(p_70612_1_, p_70612_2_); + return; + } + + if (this.isInWater()){ + this.moveFlying(p_70612_1_, p_70612_2_, 0.02F); + this.moveEntity(this.motionX, this.motionY, this.motionZ); + this.motionX *= 0.800000011920929D; + this.motionY *= 0.800000011920929D; + this.motionZ *= 0.800000011920929D; + } + else if (this.isInsideOfMaterial(Material.lava)){ + this.moveFlying(p_70612_1_, p_70612_2_, 0.02F); + this.moveEntity(this.motionX, this.motionY, this.motionZ); + this.motionX *= 0.5D; + this.motionY *= 0.5D; + this.motionZ *= 0.5D; + } + else{ + float f2 = 0.91F; + + if (this.onGround){ + f2 = this.worldObj.getBlock((int)this.posX, (int)this.boundingBox.minY - 1, (int)this.posZ).slipperiness * 0.91F; + } + + float f3 = 0.16277136F / (f2 * f2 * f2); + this.moveFlying(p_70612_1_, p_70612_2_, this.onGround ? 0.1F * f3 : 0.02F); + f2 = 0.91F; + + if (this.onGround){ + f2 = this.worldObj.getBlock((int)this.posX, (int)this.boundingBox.minY - 1, (int)this.posZ).slipperiness * 0.91F; + } + + this.moveEntity(this.motionX, this.motionY, this.motionZ); + this.motionX *= (double)f2; + this.motionY *= (double)f2; + this.motionZ *= (double)f2; + } + + this.prevLimbSwingAmount = this.limbSwingAmount; + double d1 = this.posX - this.prevPosX; + double d0 = this.posZ - this.prevPosZ; + float f4 = MathHelper.sqrt_double(d1 * d1 + d0 * d0) * 4.0F; + + if (f4 > 1.0F){ + f4 = 1.0F; + } + + this.limbSwingAmount += (f4 - this.limbSwingAmount) * 0.4F; + this.limbSwing += this.limbSwingAmount; + } + + @Override + public boolean isOnLadder(){ + return false; + } diff --git a/src/main/java/noppes/npcs/entity/EntityNPCInterface.java b/src/main/java/noppes/npcs/entity/EntityNPCInterface.java index d77094d87..c8e4731d2 100644 --- a/src/main/java/noppes/npcs/entity/EntityNPCInterface.java +++ b/src/main/java/noppes/npcs/entity/EntityNPCInterface.java @@ -3,30 +3,20 @@ package noppes.npcs.entity; import io.netty.buffer.ByteBuf; import java.io.IOException; +import java.lang.reflect.Field; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; -import com.mojang.authlib.GameProfile; - import net.minecraft.block.Block; import net.minecraft.command.ICommandSender; import net.minecraft.command.IEntitySelector; -import net.minecraft.entity.DataWatcher; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityCreature; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.EnumCreatureAttribute; -import net.minecraft.entity.IRangedAttackMob; -import net.minecraft.entity.NPCEntityHelper; -import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.*; import net.minecraft.entity.ai.*; import net.minecraft.entity.ai.EntityAITasks.EntityAITaskEntry; -import net.minecraft.entity.ai.attributes.AttributeModifier; import net.minecraft.entity.boss.IBossDisplayData; import net.minecraft.entity.item.EntityItem; -import net.minecraft.entity.monster.EntityBlaze; import net.minecraft.entity.monster.EntityMob; import net.minecraft.entity.monster.EntityZombie; import net.minecraft.entity.passive.EntityBat; @@ -51,7 +41,6 @@ import net.minecraft.util.MathHelper; import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import net.minecraft.world.WorldServer; -import net.minecraftforge.common.ForgeHooks; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.util.FakePlayer; import net.minecraftforge.event.ServerChatEvent; @@ -65,7 +54,6 @@ import noppes.npcs.DataScript; import noppes.npcs.DataStats; import noppes.npcs.IChatMessages; import noppes.npcs.NBTTags; -import noppes.npcs.NoppesStringUtils; import noppes.npcs.NoppesUtilServer; import noppes.npcs.NpcDamageSource; import noppes.npcs.Server; @@ -75,6 +63,9 @@ import noppes.npcs.ai.EntityAIMoveIndoors; import noppes.npcs.ai.EntityAIPanic; import noppes.npcs.ai.EntityAIWander; import noppes.npcs.ai.EntityAIWatchClosest; +import noppes.npcs.ai.pathfinder.FlyingMoveHelper; +import noppes.npcs.ai.pathfinder.PathNavigateFlying; +import noppes.npcs.ai.pathfinder.PathNavigateGround; import noppes.npcs.ai.selector.NPCAttackSelector; import noppes.npcs.ai.target.EntityAIClearTarget; import noppes.npcs.ai.target.EntityAIClosestTarget; @@ -100,7 +91,6 @@ import noppes.npcs.controllers.LinkedNpcController.LinkedData; import noppes.npcs.controllers.PlayerDataController; import noppes.npcs.controllers.PlayerQuestData; import noppes.npcs.controllers.QuestData; -import noppes.npcs.controllers.ScriptController; import noppes.npcs.controllers.TransformData; import noppes.npcs.roles.JobBard; import noppes.npcs.roles.JobFollower; @@ -162,9 +152,9 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti public boolean updateClient = false; public boolean updateAI = false; - // Fly Change -// protected EntityMoveHelper moveHelper; -// protected PathNavigate navigator; +// Fly Change +// public EntityMoveHelper moveHelper; +// public PathNavigate navigator; public EntityNPCInterface(World world) { super(world); @@ -602,6 +592,7 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti this.targetTasks.addTask(3, new EntityAIOwnerHurtByTarget(this)); this.targetTasks.addTask(4, new EntityAIOwnerHurtTarget(this)); + this.tasks.addTask(0, new EntityAIWaterNav(this)); // if(canFly()){ // this.moveHelper = new FlyingMoveHelper(this); @@ -610,9 +601,9 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti // else{ // this.moveHelper = new EntityMoveHelper(this); // this.navigator = new PathNavigateGround(this, worldObj); - this.tasks.addTask(0, new EntityAIWaterNav(this)); +// this.tasks.addTask(0, new EntityAIWaterNav(this)); // } - // this.tasks.addTask(0, new EntityAIWaterNav(this)); + this.taskCount = 1; this.doorInteractType(); this.seekShelter(); diff --git a/src/main/java/noppes/npcs/util/Vec3NPC.java b/src/main/java/noppes/npcs/util/Vec3NPC.java new file mode 100644 index 000000000..6c5705e75 --- /dev/null +++ b/src/main/java/noppes/npcs/util/Vec3NPC.java @@ -0,0 +1,11 @@ +package noppes.npcs.util; + +import net.minecraft.util.MathHelper; +import net.minecraft.util.Vec3; + +public class Vec3NPC extends Vec3 +{ + public Vec3NPC(double p_i1108_1_, double p_i1108_3_, double p_i1108_5_) { + super(p_i1108_1_, p_i1108_3_, p_i1108_5_); + } +}