2024-02-19 02:02:25 -08:00
|
|
|
package net.minecraft.pathfinding;
|
2024-02-14 20:52:11 -08:00
|
|
|
|
|
|
|
|
import java.util.List;
|
2024-02-19 02:02:25 -08:00
|
|
|
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.pathfinding.PathEntity;
|
|
|
|
|
import net.minecraft.pathfinding.PathFinder;
|
|
|
|
|
import net.minecraft.util.AxisAlignedBB;
|
|
|
|
|
import net.minecraft.util.BlockPos;
|
|
|
|
|
import net.minecraft.util.MathHelper;
|
|
|
|
|
import net.minecraft.util.Vec3;
|
|
|
|
|
import net.minecraft.world.ChunkCache;
|
|
|
|
|
import net.minecraft.world.World;
|
2024-02-14 20:52:11 -08:00
|
|
|
|
|
|
|
|
/**+
|
|
|
|
|
* This portion of EaglercraftX contains deobfuscated Minecraft 1.8 source code.
|
|
|
|
|
*
|
|
|
|
|
* Minecraft 1.8.8 bytecode is (c) 2015 Mojang AB. "Do not distribute!"
|
|
|
|
|
* Mod Coder Pack v9.18 deobfuscation configs are (c) Copyright by the MCP Team
|
|
|
|
|
*
|
|
|
|
|
* EaglercraftX 1.8 patch files (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved.
|
|
|
|
|
*
|
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
|
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
|
|
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
|
|
|
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
|
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
|
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
|
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
public abstract class PathNavigate {
|
|
|
|
|
|
|
|
|
|
protected EntityLiving theEntity;
|
|
|
|
|
protected World worldObj;
|
|
|
|
|
protected PathEntity currentPath;
|
|
|
|
|
protected double speed;
|
|
|
|
|
private final IAttributeInstance pathSearchRange;
|
|
|
|
|
private int totalTicks;
|
|
|
|
|
private int ticksAtLastPos;
|
|
|
|
|
/**+
|
|
|
|
|
* Coordinates of the entity's position last time a check was
|
|
|
|
|
* done (part of monitoring getting 'stuck')
|
|
|
|
|
*/
|
|
|
|
|
private Vec3 lastPosCheck = new Vec3(0.0D, 0.0D, 0.0D);
|
|
|
|
|
private float heightRequirement = 1.0F;
|
|
|
|
|
private final PathFinder pathFinder;
|
|
|
|
|
|
|
|
|
|
public PathNavigate(EntityLiving entitylivingIn, World worldIn) {
|
|
|
|
|
this.theEntity = entitylivingIn;
|
|
|
|
|
this.worldObj = worldIn;
|
|
|
|
|
this.pathSearchRange = entitylivingIn.getEntityAttribute(SharedMonsterAttributes.followRange);
|
|
|
|
|
this.pathFinder = this.getPathFinder();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected abstract PathFinder getPathFinder();
|
|
|
|
|
|
|
|
|
|
/**+
|
|
|
|
|
* Sets the speed
|
|
|
|
|
*/
|
|
|
|
|
public void setSpeed(double speedIn) {
|
|
|
|
|
this.speed = speedIn;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**+
|
|
|
|
|
* 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. Args : x, y, z
|
|
|
|
|
*/
|
|
|
|
|
public final PathEntity getPathToXYZ(double x, double y, double z) {
|
|
|
|
|
return this.getPathToPos(new BlockPos(MathHelper.floor_double(x), (int) y, MathHelper.floor_double(z)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**+
|
|
|
|
|
* Returns path to given BlockPos
|
|
|
|
|
*/
|
|
|
|
|
public PathEntity getPathToPos(BlockPos pos) {
|
|
|
|
|
if (!this.canNavigate()) {
|
|
|
|
|
return null;
|
|
|
|
|
} else {
|
|
|
|
|
float f = this.getPathSearchRange();
|
|
|
|
|
this.worldObj.theProfiler.startSection("pathfind");
|
|
|
|
|
BlockPos blockpos = new BlockPos(this.theEntity);
|
|
|
|
|
int i = (int) (f + 8.0F);
|
|
|
|
|
ChunkCache chunkcache = new ChunkCache(this.worldObj, blockpos.add(-i, -i, -i), blockpos.add(i, i, i), 0);
|
|
|
|
|
PathEntity pathentity = this.pathFinder.createEntityPathTo(chunkcache, this.theEntity, (BlockPos) pos, f);
|
|
|
|
|
this.worldObj.theProfiler.endSection();
|
|
|
|
|
return pathentity;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**+
|
|
|
|
|
* Try to find and set a path to XYZ. Returns true if
|
|
|
|
|
* successful. Args : x, y, z, speed
|
|
|
|
|
*/
|
|
|
|
|
public boolean tryMoveToXYZ(double x, double y, double z, double speedIn) {
|
|
|
|
|
PathEntity pathentity = this.getPathToXYZ((double) MathHelper.floor_double(x), (double) ((int) y),
|
|
|
|
|
(double) MathHelper.floor_double(z));
|
|
|
|
|
return this.setPath(pathentity, speedIn);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**+
|
|
|
|
|
* Sets vertical space requirement for path
|
|
|
|
|
*/
|
|
|
|
|
public void setHeightRequirement(float jumpHeight) {
|
|
|
|
|
this.heightRequirement = jumpHeight;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**+
|
|
|
|
|
* Returns the path to the given EntityLiving. Args : entity
|
|
|
|
|
*/
|
|
|
|
|
public PathEntity getPathToEntityLiving(Entity entityIn) {
|
|
|
|
|
if (!this.canNavigate()) {
|
|
|
|
|
return null;
|
|
|
|
|
} else {
|
|
|
|
|
float f = this.getPathSearchRange();
|
|
|
|
|
this.worldObj.theProfiler.startSection("pathfind");
|
|
|
|
|
BlockPos blockpos = (new BlockPos(this.theEntity)).up();
|
|
|
|
|
int i = (int) (f + 16.0F);
|
|
|
|
|
ChunkCache chunkcache = new ChunkCache(this.worldObj, blockpos.add(-i, -i, -i), blockpos.add(i, i, i), 0);
|
|
|
|
|
PathEntity pathentity = this.pathFinder.createEntityPathTo(chunkcache, this.theEntity, (Entity) entityIn,
|
|
|
|
|
f);
|
|
|
|
|
this.worldObj.theProfiler.endSection();
|
|
|
|
|
return pathentity;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**+
|
|
|
|
|
* Try to find and set a path to EntityLiving. Returns true if
|
|
|
|
|
* successful. Args : entity, speed
|
|
|
|
|
*/
|
|
|
|
|
public boolean tryMoveToEntityLiving(Entity entityIn, double speedIn) {
|
|
|
|
|
PathEntity pathentity = this.getPathToEntityLiving(entityIn);
|
|
|
|
|
return pathentity != null ? this.setPath(pathentity, speedIn) : false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**+
|
|
|
|
|
* Sets a new path. If it's diferent from the old path. Checks
|
|
|
|
|
* to adjust path for sun avoiding, and stores start coords.
|
|
|
|
|
* Args : path, speed
|
|
|
|
|
*/
|
|
|
|
|
public boolean setPath(PathEntity pathentityIn, double speedIn) {
|
|
|
|
|
if (pathentityIn == null) {
|
|
|
|
|
this.currentPath = null;
|
|
|
|
|
return false;
|
|
|
|
|
} else {
|
|
|
|
|
if (!pathentityIn.isSamePath(this.currentPath)) {
|
|
|
|
|
this.currentPath = pathentityIn;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.removeSunnyPath();
|
|
|
|
|
if (this.currentPath.getCurrentPathLength() == 0) {
|
|
|
|
|
return false;
|
|
|
|
|
} else {
|
|
|
|
|
this.speed = speedIn;
|
|
|
|
|
Vec3 vec3 = this.getEntityPosition();
|
|
|
|
|
this.ticksAtLastPos = this.totalTicks;
|
|
|
|
|
this.lastPosCheck = vec3;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**+
|
|
|
|
|
* gets the actively used PathEntity
|
|
|
|
|
*/
|
|
|
|
|
public PathEntity getPath() {
|
|
|
|
|
return this.currentPath;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void onUpdateNavigation() {
|
|
|
|
|
++this.totalTicks;
|
|
|
|
|
if (!this.noPath()) {
|
|
|
|
|
if (this.canNavigate()) {
|
|
|
|
|
this.pathFollow();
|
|
|
|
|
} else if (this.currentPath != null
|
|
|
|
|
&& this.currentPath.getCurrentPathIndex() < this.currentPath.getCurrentPathLength()) {
|
|
|
|
|
Vec3 vec3 = this.getEntityPosition();
|
|
|
|
|
Vec3 vec31 = this.currentPath.getVectorFromIndex(this.theEntity,
|
|
|
|
|
this.currentPath.getCurrentPathIndex());
|
|
|
|
|
if (vec3.yCoord > vec31.yCoord && !this.theEntity.onGround
|
|
|
|
|
&& MathHelper.floor_double(vec3.xCoord) == MathHelper.floor_double(vec31.xCoord)
|
|
|
|
|
&& MathHelper.floor_double(vec3.zCoord) == MathHelper.floor_double(vec31.zCoord)) {
|
|
|
|
|
this.currentPath.setCurrentPathIndex(this.currentPath.getCurrentPathIndex() + 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!this.noPath()) {
|
|
|
|
|
Vec3 vec32 = this.currentPath.getPosition(this.theEntity);
|
|
|
|
|
if (vec32 != null) {
|
|
|
|
|
AxisAlignedBB axisalignedbb1 = (new AxisAlignedBB(vec32.xCoord, vec32.yCoord, vec32.zCoord,
|
|
|
|
|
vec32.xCoord, vec32.yCoord, vec32.zCoord)).expand(0.5D, 0.5D, 0.5D);
|
|
|
|
|
List list = this.worldObj.getCollidingBoundingBoxes(this.theEntity,
|
|
|
|
|
axisalignedbb1.addCoord(0.0D, -1.0D, 0.0D));
|
|
|
|
|
double d0 = -1.0D;
|
|
|
|
|
axisalignedbb1 = axisalignedbb1.offset(0.0D, 1.0D, 0.0D);
|
|
|
|
|
|
|
|
|
|
for (AxisAlignedBB axisalignedbb : (List<AxisAlignedBB>) list) {
|
|
|
|
|
d0 = axisalignedbb.calculateYOffset(axisalignedbb1, d0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.theEntity.getMoveHelper().setMoveTo(vec32.xCoord, vec32.yCoord + d0, vec32.zCoord, this.speed);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected void pathFollow() {
|
|
|
|
|
Vec3 vec3 = this.getEntityPosition();
|
|
|
|
|
int i = this.currentPath.getCurrentPathLength();
|
|
|
|
|
|
|
|
|
|
for (int j = this.currentPath.getCurrentPathIndex(); j < this.currentPath.getCurrentPathLength(); ++j) {
|
|
|
|
|
if (this.currentPath.getPathPointFromIndex(j).yCoord != (int) vec3.yCoord) {
|
|
|
|
|
i = j;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float f = this.theEntity.width * this.theEntity.width * this.heightRequirement;
|
|
|
|
|
|
|
|
|
|
for (int k = this.currentPath.getCurrentPathIndex(); k < i; ++k) {
|
|
|
|
|
Vec3 vec31 = this.currentPath.getVectorFromIndex(this.theEntity, k);
|
|
|
|
|
if (vec3.squareDistanceTo(vec31) < (double) f) {
|
|
|
|
|
this.currentPath.setCurrentPathIndex(k + 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int j1 = MathHelper.ceiling_float_int(this.theEntity.width);
|
|
|
|
|
int k1 = (int) this.theEntity.height + 1;
|
|
|
|
|
int l = j1;
|
|
|
|
|
|
|
|
|
|
for (int i1 = i - 1; i1 >= this.currentPath.getCurrentPathIndex(); --i1) {
|
|
|
|
|
if (this.isDirectPathBetweenPoints(vec3, this.currentPath.getVectorFromIndex(this.theEntity, i1), j1, k1,
|
|
|
|
|
l)) {
|
|
|
|
|
this.currentPath.setCurrentPathIndex(i1);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.checkForStuck(vec3);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**+
|
|
|
|
|
* 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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**+
|
|
|
|
|
* If null path or reached the end
|
|
|
|
|
*/
|
|
|
|
|
public boolean noPath() {
|
|
|
|
|
return this.currentPath == null || this.currentPath.isFinished();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**+
|
|
|
|
|
* sets active PathEntity to null
|
|
|
|
|
*/
|
|
|
|
|
public void clearPathEntity() {
|
|
|
|
|
this.currentPath = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected abstract Vec3 getEntityPosition();
|
|
|
|
|
|
|
|
|
|
protected abstract boolean canNavigate();
|
|
|
|
|
|
|
|
|
|
/**+
|
|
|
|
|
* Returns true if the entity is in water or lava, false
|
|
|
|
|
* otherwise
|
|
|
|
|
*/
|
|
|
|
|
protected boolean isInLiquid() {
|
|
|
|
|
return this.theEntity.isInWater() || this.theEntity.isInLava();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**+
|
|
|
|
|
* Trims path data from the end to the first sun covered block
|
|
|
|
|
*/
|
|
|
|
|
protected void removeSunnyPath() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected abstract boolean isDirectPathBetweenPoints(Vec3 var1, Vec3 var2, int var3, int var4, int var5);
|
|
|
|
|
}
|