package com.owlmaddie.goals; import net.minecraft.entity.ai.FuzzyTargeting; import net.minecraft.entity.ai.pathing.Path; import net.minecraft.entity.mob.MobEntity; import net.minecraft.entity.mob.PathAwareEntity; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.math.Vec3d; import java.util.EnumSet; /** * The {@code FleePlayerGoal} class instructs a Mob Entity to flee from the current player * and only recalculates path when it has reached its destination and the player is close again. */ public class FleePlayerGoal extends PlayerBaseGoal { private final MobEntity entity; private final double speed; private final float fleeDistance; public FleePlayerGoal(ServerPlayerEntity player, MobEntity entity, double speed, float fleeDistance) { super(player); this.entity = entity; this.speed = speed; this.fleeDistance = fleeDistance; this.setControls(EnumSet.of(Control.MOVE)); } @Override public boolean canStart() { return super.canStart() && this.entity.squaredDistanceTo(this.targetEntity) < fleeDistance * fleeDistance; } @Override public boolean shouldContinue() { return super.canStart() && this.entity.squaredDistanceTo(this.targetEntity) < fleeDistance * fleeDistance; } @Override public void stop() { this.entity.getNavigation().stop(); } private void fleeFromPlayer() { int roundedFleeDistance = Math.round(fleeDistance); if (this.entity instanceof PathAwareEntity) { // Set random path away from player Vec3d fleeTarget = FuzzyTargeting.findFrom((PathAwareEntity) this.entity, roundedFleeDistance, roundedFleeDistance, this.targetEntity.getPos()); if (fleeTarget != null) { Path path = this.entity.getNavigation().findPathTo(fleeTarget.x, fleeTarget.y, fleeTarget.z, 0); if (path != null) { this.entity.getNavigation().startMovingAlong(path, this.speed); } } } else { // Move in the opposite direction from player (for non-path aware entities) Vec3d playerPos = this.targetEntity.getPos(); Vec3d entityPos = this.entity.getPos(); // Calculate the direction away from the player Vec3d fleeDirection = entityPos.subtract(playerPos).normalize(); // Apply movement with the entity's speed in the opposite direction this.entity.setVelocity(fleeDirection.x * this.speed, fleeDirection.y * this.speed, fleeDirection.z * this.speed); this.entity.velocityModified = true; } } @Override public void start() { fleeFromPlayer(); } @Override public void tick() { if (!this.entity.getNavigation().isFollowingPath()) { fleeFromPlayer(); } } }