mirror of
https://github.com/KAMKEEL/CustomNPC-Plus.git
synced 2026-11-12 18:57:32 +00:00
665 lines
26 KiB
Java
665 lines
26 KiB
Java
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.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.MovingObjectPosition;
|
|
import net.minecraft.util.Vec3;
|
|
import net.minecraft.util.math.BlockPos;
|
|
import net.minecraft.world.ChunkCache;
|
|
import net.minecraft.world.World;
|
|
import noppes.npcs.entity.EntityNPCInterface;
|
|
|
|
import javax.annotation.Nullable;
|
|
|
|
public class PathNavigateFlying extends PathNavigate {
|
|
|
|
private EntityNPCInterface theEntity;
|
|
private World worldObj;
|
|
/**
|
|
* The PathEntity being followed.
|
|
*/
|
|
protected NPCPath currentPath;
|
|
private double speed;
|
|
/**
|
|
* The number of blocks (extra) +/- in each axis that get pulled out as cache for the pathfinder's search space
|
|
*/
|
|
private IAttributeInstance pathSearchRange;
|
|
protected float maxDistanceToWaypoint = 0.5F;
|
|
private boolean noSunPathfind;
|
|
/**
|
|
* Time, in number of ticks, following the current path
|
|
*/
|
|
private int totalTicks;
|
|
/**
|
|
* The time when the last position check was done (to detect successful movement)
|
|
*/
|
|
private int ticksAtLastPos;
|
|
/**
|
|
* Coordinates of the entity's position last time a check was done (part of monitoring getting 'stuck')
|
|
*/
|
|
private Vec3 lastPosCheck = Vec3.createVectorHelper(0.0D, 0.0D, 0.0D);
|
|
private Vec3 timeoutCachedNode = Vec3.createVectorHelper(0.0D, 0.0D, 0.0D);
|
|
private long timeoutTimer;
|
|
private long lastTimeoutCheck;
|
|
private double timeoutLimit;
|
|
/**
|
|
* Specifically, if a wooden door block is even considered to be passable by the pathfinder
|
|
*/
|
|
private boolean canPassOpenWoodenDoors = true;
|
|
/**
|
|
* If door blocks are considered passable even when closed
|
|
*/
|
|
private boolean canPassClosedWoodenDoors;
|
|
/**
|
|
* If water blocks are avoided (at least by the pathfinder)
|
|
*/
|
|
private boolean avoidsWater;
|
|
/**
|
|
* If the entity can swim. Swimming AI enables this and the pathfinder will also cause the entity to swim straight
|
|
* upwards when underwater
|
|
*/
|
|
private boolean canSwim;
|
|
|
|
public BlockPos targetPos;
|
|
protected boolean tryUpdatePath;
|
|
protected long lastTimeUpdated;
|
|
|
|
public FlyPathFinder pathFinder;
|
|
|
|
public PathNavigateFlying(EntityLiving entityIN, World worldIn) {
|
|
super(entityIN, worldIn);
|
|
this.theEntity = (EntityNPCInterface) entityIN;
|
|
this.worldObj = worldIn;
|
|
this.pathSearchRange = entityIN.getEntityAttribute(SharedMonsterAttributes.followRange);
|
|
}
|
|
|
|
public void updatePath() {
|
|
if (this.worldObj.getTotalWorldTime() - this.lastTimeUpdated > 20L) {
|
|
if (this.targetPos != null) {
|
|
this.currentPath = null;
|
|
this.currentPath = this.getPathToXYZ(this.targetPos.getX(), this.targetPos.getY(), this.targetPos.getZ());
|
|
this.lastTimeUpdated = this.worldObj.getTotalWorldTime();
|
|
this.tryUpdatePath = false;
|
|
}
|
|
} else {
|
|
this.tryUpdatePath = true;
|
|
}
|
|
}
|
|
|
|
public void setAvoidsWater(boolean p_75491_1_) {
|
|
this.avoidsWater = p_75491_1_;
|
|
}
|
|
|
|
public boolean getAvoidsWater() {
|
|
return this.avoidsWater;
|
|
}
|
|
|
|
public void setBreakDoors(boolean p_75498_1_) {
|
|
this.canPassClosedWoodenDoors = p_75498_1_;
|
|
}
|
|
|
|
/**
|
|
* Sets if the entity can enter open doors
|
|
*/
|
|
public void setEnterDoors(boolean p_75490_1_) {
|
|
this.canPassOpenWoodenDoors = p_75490_1_;
|
|
}
|
|
|
|
/**
|
|
* Returns true if the entity can break doors, false otherwise
|
|
*/
|
|
public boolean getCanBreakDoors() {
|
|
return this.canPassClosedWoodenDoors;
|
|
}
|
|
|
|
/**
|
|
* Sets if the path should avoid sunlight
|
|
*/
|
|
public void setAvoidSun(boolean p_75504_1_) {
|
|
this.noSunPathfind = p_75504_1_;
|
|
}
|
|
|
|
/**
|
|
* Sets the speed
|
|
*/
|
|
public void setSpeed(double p_75489_1_) {
|
|
this.speed = p_75489_1_;
|
|
}
|
|
|
|
/**
|
|
* Sets if the entity can swim
|
|
*/
|
|
public void setCanSwim(boolean p_75495_1_) {
|
|
this.canSwim = p_75495_1_;
|
|
}
|
|
|
|
/**
|
|
* Gets the maximum distance that the path finding will search in.
|
|
*/
|
|
public float getPathSearchRange() {
|
|
return (float) this.pathSearchRange.getAttributeValue();
|
|
}
|
|
|
|
/**
|
|
* Returns the path to the given coordinates
|
|
*/
|
|
public NPCPath getPathToXYZ(double x, double y, double z) {
|
|
BlockPos pos = new BlockPos(x, y, z);
|
|
if (!this.canNavigate()) {
|
|
return null;
|
|
} else if (this.currentPath != null && !this.currentPath.isFinished() && pos.equals(this.targetPos)) {
|
|
return this.currentPath;
|
|
} else {
|
|
this.targetPos = pos;
|
|
return this.getEntityPathToXYZ(this.theEntity, MathHelper.floor_double(x), (int) y, MathHelper.floor_double(z), this.getPathSearchRange(), this.canPassOpenWoodenDoors, this.canPassClosedWoodenDoors, this.avoidsWater, this.canSwim);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Try to find and set a path to XYZ. Returns true if successful.
|
|
*/
|
|
public boolean tryMoveToXYZ(double p_75492_1_, double p_75492_3_, double p_75492_5_, double p_75492_7_) {
|
|
NPCPath pathentity = this.getPathToXYZ((double) MathHelper.floor_double(p_75492_1_), (double) ((int) p_75492_3_), (double) MathHelper.floor_double(p_75492_5_));
|
|
return this.setPath(pathentity, p_75492_7_);
|
|
}
|
|
|
|
/**
|
|
* Returns the path to the given EntityLiving
|
|
*/
|
|
public NPCPath getPathToEntityLiving(Entity entity) {
|
|
if (!this.canNavigate()) {
|
|
return null;
|
|
} else {
|
|
BlockPos blockpos = new BlockPos(entity);
|
|
if (this.currentPath != null && !this.currentPath.isFinished() && blockpos.equals(this.targetPos)) {
|
|
return this.currentPath;
|
|
} else {
|
|
this.targetPos = blockpos;
|
|
return this.getPathEntityToEntity(this.theEntity, entity, this.getPathSearchRange(), this.canPassOpenWoodenDoors, this.canPassClosedWoodenDoors, this.avoidsWater, this.canSwim);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Try to find and set a path to EntityLiving. Returns true if successful.
|
|
*/
|
|
public boolean tryMoveToEntityLiving(Entity p_75497_1_, double p_75497_2_) {
|
|
NPCPath pathentity = this.getPathToEntityLiving(p_75497_1_);
|
|
return pathentity != null && this.setPath(pathentity, p_75497_2_);
|
|
}
|
|
|
|
/**
|
|
* sets the active path data if path is 100% unique compared to old path, checks to adjust path for sun avoiding
|
|
* ents and stores end coords
|
|
*/
|
|
public boolean setPath(@Nullable PathEntity pathEntity, double speed) {
|
|
NPCPath NPCPath = (NPCPath) pathEntity;
|
|
if (NPCPath == null) {
|
|
this.currentPath = null;
|
|
return false;
|
|
} else {
|
|
if (!NPCPath.isSamePath(this.currentPath)) {
|
|
this.currentPath = NPCPath;
|
|
}
|
|
|
|
if (this.noSunPathfind) {
|
|
this.removeSunnyPath();
|
|
}
|
|
|
|
if (this.currentPath.getCurrentPathLength() == 0) {
|
|
return false;
|
|
} else {
|
|
this.speed = speed;
|
|
Vec3 vec3 = this.getEntityPosition();
|
|
this.ticksAtLastPos = this.totalTicks;
|
|
this.lastPosCheck = vec3;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* gets the actively used PathEntity
|
|
*/
|
|
public PathEntity getPath() {
|
|
return this.currentPath;
|
|
}
|
|
|
|
private boolean isInLiquid() {
|
|
return this.theEntity.isInWater() || this.theEntity.handleLavaMovement();
|
|
}
|
|
|
|
private boolean canNavigate() {
|
|
return !this.isInLiquid() || (this.canSwim && this.isInLiquid());
|
|
}
|
|
|
|
public void onUpdateNavigation() {
|
|
|
|
++this.totalTicks;
|
|
|
|
if (this.tryUpdatePath) {
|
|
this.updatePath();
|
|
}
|
|
|
|
if (!this.noPath()) {
|
|
if (this.canNavigate()) {
|
|
if (((EntityNPCInterface) this.theEntity).display.modelSize >= 5)
|
|
this.pathFollowBig();
|
|
else
|
|
this.pathFollowSmall();
|
|
} else if (this.currentPath != null && this.currentPath.getCurrentPathIndex() < this.currentPath.getCurrentPathLength()) {
|
|
if (!this.noPath()) {
|
|
Vec3 vec3d = this.currentPath.getVectorFromIndex(this.theEntity, this.currentPath.getCurrentPathIndex());
|
|
Vec3 vec3 = this.currentPath.getPosition(this.theEntity);
|
|
|
|
if (MathHelper.floor_double(this.theEntity.posX) == MathHelper.floor_double(vec3d.xCoord) && MathHelper.floor_double(this.theEntity.posY) == MathHelper.floor_double(vec3d.yCoord) && MathHelper.floor_double(this.theEntity.posZ) == MathHelper.floor_double(vec3d.zCoord))
|
|
if (vec3 != null) {
|
|
this.currentPath.setCurrentPathIndex(this.currentPath.getCurrentPathIndex() + 1);
|
|
this.theEntity.getMoveHelper().setMoveTo(vec3.xCoord, vec3.yCoord, vec3.zCoord, this.speed);
|
|
}
|
|
}
|
|
}
|
|
if (!this.noPath()) {
|
|
Vec3 vec3 = this.currentPath.getPosition(this.theEntity);
|
|
if (vec3 != null) {
|
|
this.theEntity.getMoveHelper().setMoveTo(vec3.xCoord, vec3.yCoord, vec3.zCoord, this.speed);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void pathFollowBig() {
|
|
Vec3 vec3 = this.getEntityPosition();
|
|
int i = this.currentPath.getCurrentPathLength();
|
|
|
|
float f = this.theEntity.width * this.theEntity.width;
|
|
int k;
|
|
|
|
for (k = this.currentPath.getCurrentPathIndex(); k < i; ++k) {
|
|
if (vec3.squareDistanceTo(this.currentPath.getVectorFromIndex(this.theEntity, k)) < (double) f) {
|
|
this.currentPath.setCurrentPathIndex(k + 1);
|
|
}
|
|
}
|
|
|
|
k = MathHelper.floor_double(this.theEntity.width + 1.0F);
|
|
int l = MathHelper.floor_double(this.theEntity.height + 1.0F);
|
|
this.trimPath(vec3, i, k, l);
|
|
|
|
this.checkForStuck(vec3);
|
|
}
|
|
|
|
private void pathFollowSmall() {
|
|
Vec3 vec3 = this.getEntityPosition();
|
|
int i = this.currentPath.getCurrentPathLength();
|
|
for (int j = this.currentPath.getCurrentPathIndex(); j < this.currentPath.getCurrentPathLength(); ++j) {
|
|
if ((double) this.currentPath.getPathPointFromIndex(j).yCoord != Math.floor(vec3.yCoord)) {
|
|
i = j;
|
|
break;
|
|
}
|
|
}
|
|
|
|
this.maxDistanceToWaypoint = this.theEntity.width > 0.75F ? this.theEntity.width / 2.0F : 0.75F - this.theEntity.width / 2.0F;
|
|
Vec3 vec3d1 = this.currentPath.getCurrentPos();
|
|
|
|
if (MathHelper.abs((float) (this.theEntity.posX - (vec3d1.xCoord + 0.5D))) < this.maxDistanceToWaypoint && MathHelper.abs((float) (this.theEntity.posZ - (vec3d1.zCoord + 0.5D))) < this.maxDistanceToWaypoint && Math.abs(this.theEntity.posY - vec3d1.yCoord) < 1.0D) {
|
|
this.currentPath.setCurrentPathIndex(this.currentPath.getCurrentPathIndex() + 1);
|
|
}
|
|
|
|
int k = MathHelper.ceiling_double_int(this.theEntity.width);
|
|
int l = MathHelper.ceiling_double_int(this.theEntity.height + 1.0F);
|
|
this.trimPath(vec3, i, k, l);
|
|
|
|
this.checkForStuck(vec3);
|
|
}
|
|
|
|
public void trimPath(Vec3 position, int pathLength, int width, int height) {
|
|
for (int j1 = pathLength - 1; j1 >= this.currentPath.getCurrentPathIndex(); --j1) {
|
|
Vec3 pathPoint = this.currentPath.getVectorFromIndex(this.theEntity, j1);
|
|
if (position.distanceTo(pathPoint) > 6)
|
|
continue;
|
|
|
|
if (this.isDirectPathBetweenPoints(position, pathPoint, width, height)) {
|
|
this.currentPath.setCurrentPathIndex(j1);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* If null path or reached the end
|
|
*/
|
|
public boolean noPath() {
|
|
return this.currentPath == null || this.currentPath.isFinished();
|
|
}
|
|
|
|
/**
|
|
* sets active PathEntity to null
|
|
*/
|
|
@Override
|
|
public void clearPathEntity() {
|
|
this.currentPath = null;
|
|
}
|
|
|
|
private Vec3 getEntityPosition() {
|
|
return Vec3.createVectorHelper(this.theEntity.posX, this.getPathableYPos(), this.theEntity.posZ);
|
|
}
|
|
|
|
/**
|
|
* Gets the safe pathing Y position for the entity depending on if it can path swim or not
|
|
*/
|
|
private double getPathableYPos() {
|
|
return this.theEntity.boundingBox.minY + 0.05D;
|
|
}
|
|
|
|
/**
|
|
* Trims path data from the end to the first sun covered block
|
|
*/
|
|
private 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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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
|
|
*/
|
|
private boolean isDirectPathBetweenPoints(Vec3 startPos, Vec3 endPos, int width, int height) {
|
|
Vec3 pos17 = Vec3.createVectorHelper(startPos.xCoord, startPos.yCoord, startPos.zCoord);
|
|
Vec3 pos18 = Vec3.createVectorHelper(endPos.xCoord, endPos.yCoord, endPos.zCoord);
|
|
if (this.rayTraceBlocks(pos17, pos18, true, false, false, width, height))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
public boolean rayTraceBlocks(Vec3 p_147447_1_, Vec3 p_147447_2_, boolean p_147447_3_, boolean p_147447_4_, boolean p_147447_5_, int width, int height) {
|
|
if (!Double.isNaN(p_147447_1_.xCoord) && !Double.isNaN(p_147447_1_.yCoord) && !Double.isNaN(p_147447_1_.zCoord)) {
|
|
if (!Double.isNaN(p_147447_2_.xCoord) && !Double.isNaN(p_147447_2_.yCoord) && !Double.isNaN(p_147447_2_.zCoord)) {
|
|
int i = MathHelper.floor_double(p_147447_2_.xCoord);
|
|
int j = MathHelper.floor_double(p_147447_2_.yCoord);
|
|
int k = MathHelper.floor_double(p_147447_2_.zCoord);
|
|
int l = MathHelper.floor_double(p_147447_1_.xCoord);
|
|
int i1 = MathHelper.floor_double(p_147447_1_.yCoord);
|
|
int j1 = MathHelper.floor_double(p_147447_1_.zCoord);
|
|
Block block = this.worldObj.getBlock(l, i1, j1);
|
|
int k1 = this.worldObj.getBlockMetadata(l, i1, j1);
|
|
|
|
if ((!p_147447_4_ || block.getCollisionBoundingBoxFromPool(this.worldObj, l, i1, j1) != null) && block.canCollideCheck(k1, p_147447_3_)) {
|
|
MovingObjectPosition movingobjectposition = block.collisionRayTrace(this.worldObj, l, i1, j1, p_147447_1_, p_147447_2_);
|
|
|
|
if (movingobjectposition != null && movingobjectposition.typeOfHit != MovingObjectPosition.MovingObjectType.MISS) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
MovingObjectPosition movingobjectposition2 = null;
|
|
k1 = 200;
|
|
|
|
while (k1-- >= 0) {
|
|
if (Double.isNaN(p_147447_1_.xCoord) || Double.isNaN(p_147447_1_.yCoord) || Double.isNaN(p_147447_1_.zCoord)) {
|
|
return false;
|
|
}
|
|
|
|
if (l == i && i1 == j && j1 == k) {
|
|
if (p_147447_5_) {
|
|
return movingobjectposition2 != null && movingobjectposition2.typeOfHit != MovingObjectPosition.MovingObjectType.MISS;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
boolean flag6 = true;
|
|
boolean flag3 = true;
|
|
boolean flag4 = true;
|
|
double d0 = 999.0D;
|
|
double d1 = 999.0D;
|
|
double d2 = 999.0D;
|
|
|
|
if (i > l) {
|
|
d0 = (double) l + 1.0D;
|
|
} else if (i < l) {
|
|
d0 = (double) l + 0.0D;
|
|
} else {
|
|
flag6 = false;
|
|
}
|
|
|
|
if (j > i1) {
|
|
d1 = (double) i1 + 1.0D;
|
|
} else if (j < i1) {
|
|
d1 = (double) i1 + 0.0D;
|
|
} else {
|
|
flag3 = false;
|
|
}
|
|
|
|
if (k > j1) {
|
|
d2 = (double) j1 + 1.0D;
|
|
} else if (k < j1) {
|
|
d2 = (double) j1 + 0.0D;
|
|
} else {
|
|
flag4 = false;
|
|
}
|
|
|
|
double d3 = 999.0D;
|
|
double d4 = 999.0D;
|
|
double d5 = 999.0D;
|
|
double d6 = p_147447_2_.xCoord - p_147447_1_.xCoord;
|
|
double d7 = p_147447_2_.yCoord - p_147447_1_.yCoord;
|
|
double d8 = p_147447_2_.zCoord - p_147447_1_.zCoord;
|
|
|
|
if (flag6) {
|
|
d3 = (d0 - p_147447_1_.xCoord) / d6;
|
|
}
|
|
|
|
if (flag3) {
|
|
d4 = (d1 - p_147447_1_.yCoord) / d7;
|
|
}
|
|
|
|
if (flag4) {
|
|
d5 = (d2 - p_147447_1_.zCoord) / d8;
|
|
}
|
|
|
|
boolean flag5 = false;
|
|
byte b0;
|
|
|
|
if (d3 < d4 && d3 < d5) {
|
|
if (i > l) {
|
|
b0 = 4;
|
|
} else {
|
|
b0 = 5;
|
|
}
|
|
|
|
p_147447_1_.xCoord = d0;
|
|
p_147447_1_.yCoord += d7 * d3;
|
|
p_147447_1_.zCoord += d8 * d3;
|
|
} else if (d4 < d5) {
|
|
if (j > i1) {
|
|
b0 = 0;
|
|
} else {
|
|
b0 = 1;
|
|
}
|
|
|
|
p_147447_1_.xCoord += d6 * d4;
|
|
p_147447_1_.yCoord = d1;
|
|
p_147447_1_.zCoord += d8 * d4;
|
|
} else {
|
|
if (k > j1) {
|
|
b0 = 2;
|
|
} else {
|
|
b0 = 3;
|
|
}
|
|
|
|
p_147447_1_.xCoord += d6 * d5;
|
|
p_147447_1_.yCoord += d7 * d5;
|
|
p_147447_1_.zCoord = d2;
|
|
}
|
|
|
|
Vec3 vec32 = Vec3.createVectorHelper(p_147447_1_.xCoord, p_147447_1_.yCoord, p_147447_1_.zCoord);
|
|
l = (int) (vec32.xCoord = (double) MathHelper.floor_double(p_147447_1_.xCoord));
|
|
|
|
if (b0 == 5) {
|
|
--l;
|
|
++vec32.xCoord;
|
|
}
|
|
|
|
i1 = (int) (vec32.yCoord = (double) MathHelper.floor_double(p_147447_1_.yCoord));
|
|
|
|
if (b0 == 1) {
|
|
--i1;
|
|
++vec32.yCoord;
|
|
}
|
|
|
|
j1 = (int) (vec32.zCoord = (double) MathHelper.floor_double(p_147447_1_.zCoord));
|
|
|
|
if (b0 == 3) {
|
|
--j1;
|
|
++vec32.zCoord;
|
|
}
|
|
|
|
boolean value = false;
|
|
for (int x = -width; x <= width; x++) {
|
|
if (value) {
|
|
break;
|
|
}
|
|
for (int y = 0; y <= height; y++) {
|
|
if (value) {
|
|
break;
|
|
}
|
|
for (int z = -width; z <= width; z++) {
|
|
if (Math.abs(x) == Math.abs(z)) {
|
|
continue;
|
|
}
|
|
|
|
l += x;
|
|
i1 += y;
|
|
j1 += z;
|
|
|
|
Block block2 = this.worldObj.getBlock(l, i1, j1);
|
|
int meta2 = this.worldObj.getBlockMetadata(l, i1, j1);
|
|
|
|
boolean collideCheck = (!p_147447_4_ || block2.getCollisionBoundingBoxFromPool(this.worldObj, l, i1, j1) != null) && block2.canCollideCheck(meta2, p_147447_3_);
|
|
boolean noCollisionBlock = block2 == Blocks.air || block2.getMaterial() == Material.lava && this.theEntity.isImmuneToFire() ||
|
|
block2.getMaterial() == Material.water && this.theEntity.stats.drowningType == 2;
|
|
|
|
if (collideCheck && !noCollisionBlock) {
|
|
if (!block2.getBlocksMovement(this.worldObj, l, i1, j1)) {
|
|
value = true;
|
|
l -= x;
|
|
i1 -= y;
|
|
j1 -= z;
|
|
break;
|
|
}
|
|
MovingObjectPosition movingobjectposition = block2.collisionRayTrace(this.worldObj, l, i1, j1, p_147447_1_, p_147447_2_);
|
|
if (movingobjectposition != null && movingobjectposition.typeOfHit != MovingObjectPosition.MovingObjectType.MISS) {
|
|
value = true;
|
|
l -= x;
|
|
i1 -= y;
|
|
j1 -= z;
|
|
break;
|
|
} else {
|
|
movingobjectposition2 = new MovingObjectPosition(l, i1, j1, b0, p_147447_1_, false);
|
|
}
|
|
}
|
|
|
|
l -= x;
|
|
i1 -= y;
|
|
j1 -= z;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (value) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if (p_147447_5_) {
|
|
return movingobjectposition2 != null && movingobjectposition2.typeOfHit != MovingObjectPosition.MovingObjectType.MISS;
|
|
}
|
|
return false;
|
|
} else {
|
|
return false;
|
|
}
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
if (this.currentPath != null && !this.currentPath.isFinished()) {
|
|
Vec3 vec3d = this.currentPath.getCurrentPos();
|
|
|
|
if (vec3d.equals(this.timeoutCachedNode)) {
|
|
this.timeoutTimer += System.currentTimeMillis() - this.lastTimeoutCheck;
|
|
} else {
|
|
this.timeoutCachedNode = vec3d;
|
|
double d0 = positionVec3.distanceTo(this.timeoutCachedNode);
|
|
this.timeoutLimit = this.theEntity.getAIMoveSpeed() > 0.0F ? d0 / (double) this.theEntity.getAIMoveSpeed() * 1000.0D : 0.0D;
|
|
}
|
|
|
|
if (this.timeoutLimit > 0.0D && (double) this.timeoutTimer > this.timeoutLimit * 3.0D) {
|
|
this.timeoutCachedNode = Vec3.createVectorHelper(0.0D, 0.0D, 0.0D);
|
|
;
|
|
this.timeoutTimer = 0L;
|
|
this.timeoutLimit = 0.0D;
|
|
this.clearPathEntity();
|
|
}
|
|
|
|
this.lastTimeoutCheck = System.currentTimeMillis();
|
|
}
|
|
}
|
|
|
|
public ChunkCache createChunkCache(World world, BlockPos blockFrom, BlockPos blockTo) {
|
|
return new ChunkCache(world, blockFrom.getX(), blockFrom.getY(), blockFrom.getZ(), blockTo.getX(), blockTo.getY(), blockTo.getZ(), 0);
|
|
}
|
|
|
|
public NPCPath getPathEntityToEntity(Entity entityFrom, Entity entityTo, float distance, boolean openDoors, boolean breakDoors, boolean pathWater, boolean canSwim) {
|
|
float f = this.getPathSearchRange();
|
|
this.theEntity.worldObj.theProfiler.startSection("pathfind");
|
|
BlockPos blockpos1 = (new BlockPos(this.theEntity)).up();
|
|
int i = (int) (f + 16.0F);
|
|
ChunkCache chunkcache = createChunkCache(this.worldObj, blockpos1.add(-i, -i, -i), blockpos1.add(i, i, i));
|
|
this.pathFinder = new FlyPathFinder(chunkcache, openDoors, breakDoors, pathWater, canSwim, this.theEntity);
|
|
NPCPath pathentity = this.pathFinder.createEntityPathTo(entityFrom, entityTo, distance);
|
|
this.theEntity.worldObj.theProfiler.endSection();
|
|
return pathentity;
|
|
}
|
|
|
|
public NPCPath getEntityPathToXYZ(Entity entityFrom, int x, int y, int z, float distance, boolean openDoors, boolean breakDoors, boolean pathWater, boolean canSwim) {
|
|
float f = this.getPathSearchRange();
|
|
this.theEntity.worldObj.theProfiler.startSection("pathfind");
|
|
BlockPos blockpos1 = (new BlockPos(this.theEntity)).up();
|
|
int i = (int) (f + 16.0F);
|
|
ChunkCache chunkcache = createChunkCache(this.worldObj, blockpos1.add(-i, -i, -i), blockpos1.add(i, i, i));
|
|
this.pathFinder = new FlyPathFinder(chunkcache, openDoors, breakDoors, pathWater, canSwim, this.theEntity);
|
|
NPCPath pathentity = this.pathFinder.createEntityPathTo(entityFrom, this.targetPos.getX(), this.targetPos.getY(), this.targetPos.getZ(), f);
|
|
this.theEntity.worldObj.theProfiler.endSection();
|
|
return pathentity;
|
|
}
|
|
}
|