package com.thebrokenrail.twine.entity; import com.thebrokenrail.twine.Twine; import net.minecraft.block.Blocks; import net.minecraft.entity.ai.TargetFinder; import net.minecraft.entity.ai.goal.Goal; import net.minecraft.entity.ai.pathing.Path; import net.minecraft.entity.mob.MobEntityWithAi; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.world.WorldView; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.ChunkStatus; public class FleeEndRodGoal extends Goal { private final MobEntityWithAi mob; private Vec3d targetPos; private Path fleePath; public FleeEndRodGoal(MobEntityWithAi mob) { super(); this.mob = mob; } boolean isTargetPos(WorldView world, BlockPos pos) { Chunk chunk = world.getChunk(pos.getX() >> 4, pos.getZ() >> 4, ChunkStatus.FULL, false); if (chunk == null) { return false; } else { return chunk.getBlockState(pos).isOf(Blocks.END_ROD); } } private boolean findTargetPos() { BlockPos blockPos = mob.getBlockPos(); BlockPos.Mutable mutable = new BlockPos.Mutable(); for (int k = 0; k <= Twine.AI_MAX_Y_DIFFERENCE; k = k > 0 ? -k : 1 - k) { for (int l = 0; l < Twine.AI_RANGE; ++l) { for (int m = 0; m <= l; m = m > 0 ? -m : 1 - m) { for (int n = m < l && m > -l ? l : 0; n <= l; n = n > 0 ? -n : 1 - n) { mutable.set(blockPos, m, k - 1, n); if (mob.isInWalkTargetRange(mutable) && isTargetPos(mob.world, mutable)) { targetPos = new Vec3d(mutable.getX() + 0.5d, mutable.getY(), mutable.getZ() + 0.5d); return true; } } } } } return false; } private double squaredDistanceTo(Vec3d vector) { double d = targetPos.x - vector.x; double e = targetPos.y - vector.y; double f = targetPos.z - vector.z; return d * d + e * e + f * f; } @Override public boolean canStart() { if (findTargetPos()) { Vec3d vec3d = TargetFinder.findTargetAwayFrom(mob, Twine.AI_RANGE * 2, Twine.AI_MAX_Y_DIFFERENCE * 2, targetPos); if (vec3d == null) { return false; } else if (squaredDistanceTo(vec3d) < mob.squaredDistanceTo(targetPos)) { return false; } else { fleePath = mob.getNavigation().findPathTo(vec3d.x, vec3d.y, vec3d.z, 0); return fleePath != null; } } else { return false; } } @Override public boolean shouldContinue() { return !mob.getNavigation().isIdle(); } @Override public void start() { mob.getNavigation().startMovingAlong(fleePath, SLOW_SPEED); } @Override public void stop() { targetPos = null; } private static final float SLOW_SPEED = 1.25f; private static final float FAST_SPEED = 1.5f; @Override public void tick() { if (squaredDistanceTo(mob.getPos()) < (Twine.AI_RANGE / 2d)) { mob.getNavigation().setSpeed(FAST_SPEED); } else { mob.getNavigation().setSpeed(SLOW_SPEED); } } }