package net.minecraft.world.entity.ai.goal; import java.util.EnumSet; import java.util.List; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.animal.horse.Llama; import net.minecraft.world.entity.decoration.LeashFenceKnotEntity; import net.minecraft.world.phys.Vec3; public class LlamaFollowCaravanGoal extends Goal { public final Llama llama; private double speedModifier; private static final int CARAVAN_LIMIT = 8; private int distCheckCounter; public LlamaFollowCaravanGoal(Llama llama, double speedModifier) { this.llama = llama; this.speedModifier = speedModifier; this.setFlags(EnumSet.of(Goal.Flag.MOVE)); } @Override public boolean canUse() { if (!this.llama.isLeashed() && !this.llama.inCaravan()) { List list = this.llama.level().getEntities(this.llama, this.llama.getBoundingBox().inflate(9.0, 4.0, 9.0), entityx -> { EntityType entityType = entityx.getType(); return entityType == EntityType.LLAMA || entityType == EntityType.TRADER_LLAMA; }); Llama llama = null; double d = Double.MAX_VALUE; for (Entity entity : list) { Llama llama2 = (Llama)entity; if (llama2.inCaravan() && !llama2.hasCaravanTail()) { double e = this.llama.distanceToSqr(llama2); if (!(e > d)) { d = e; llama = llama2; } } } if (llama == null) { for (Entity entityx : list) { Llama llama2 = (Llama)entityx; if (llama2.isLeashed() && !llama2.hasCaravanTail()) { double e = this.llama.distanceToSqr(llama2); if (!(e > d)) { d = e; llama = llama2; } } } } if (llama == null) { return false; } else if (d < 4.0) { return false; } else if (!llama.isLeashed() && !this.firstIsLeashed(llama, 1)) { return false; } else { this.llama.joinCaravan(llama); return true; } } else { return false; } } @Override public boolean canContinueToUse() { if (this.llama.inCaravan() && this.llama.getCaravanHead().isAlive() && this.firstIsLeashed(this.llama, 0)) { double d = this.llama.distanceToSqr(this.llama.getCaravanHead()); if (d > 676.0) { if (this.speedModifier <= 3.0) { this.speedModifier *= 1.2; this.distCheckCounter = reducedTickDelay(40); return true; } if (this.distCheckCounter == 0) { return false; } } if (this.distCheckCounter > 0) { this.distCheckCounter--; } return true; } else { return false; } } @Override public void stop() { this.llama.leaveCaravan(); this.speedModifier = 2.1; } @Override public void tick() { if (this.llama.inCaravan()) { if (!(this.llama.getLeashHolder() instanceof LeashFenceKnotEntity)) { Llama llama = this.llama.getCaravanHead(); double d = this.llama.distanceTo(llama); float f = 2.0F; Vec3 vec3 = new Vec3(llama.getX() - this.llama.getX(), llama.getY() - this.llama.getY(), llama.getZ() - this.llama.getZ()) .normalize() .scale(Math.max(d - 2.0, 0.0)); this.llama.getNavigation().moveTo(this.llama.getX() + vec3.x, this.llama.getY() + vec3.y, this.llama.getZ() + vec3.z, this.speedModifier); } } } private boolean firstIsLeashed(Llama llama, int leashedQueuePosition) { if (leashedQueuePosition > 8) { return false; } else if (llama.inCaravan()) { return llama.getCaravanHead().isLeashed() ? true : this.firstIsLeashed(llama.getCaravanHead(), ++leashedQueuePosition); } else { return false; } } }