Citizens2/main/src/main/java/net/citizensnpcs/npc/ai/FlyingAStarNavigationStrate...

152 lines
5.4 KiB
Java
Raw Normal View History

2013-11-04 14:33:56 +01:00
package net.citizensnpcs.npc.ai;
2016-08-02 18:13:21 +02:00
import java.util.List;
import org.bukkit.Effect;
import org.bukkit.Location;
import org.bukkit.entity.EntityType;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import org.bukkit.util.Vector;
2016-08-02 18:13:21 +02:00
import com.google.common.collect.Lists;
2016-07-25 18:32:32 +02:00
import net.citizensnpcs.api.ai.AbstractPathStrategy;
2013-11-04 14:33:56 +01:00
import net.citizensnpcs.api.ai.NavigatorParameters;
import net.citizensnpcs.api.ai.TargetType;
import net.citizensnpcs.api.ai.event.CancelReason;
import net.citizensnpcs.api.astar.AStarMachine;
import net.citizensnpcs.api.astar.pathfinder.BlockExaminer;
2013-11-04 14:33:56 +01:00
import net.citizensnpcs.api.astar.pathfinder.ChunkBlockSource;
import net.citizensnpcs.api.astar.pathfinder.FlyingBlockExaminer;
2013-11-04 14:33:56 +01:00
import net.citizensnpcs.api.astar.pathfinder.Path;
import net.citizensnpcs.api.astar.pathfinder.VectorGoal;
import net.citizensnpcs.api.astar.pathfinder.VectorNode;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.util.NMS;
2013-11-04 14:33:56 +01:00
public class FlyingAStarNavigationStrategy extends AbstractPathStrategy {
private final NPC npc;
private final NavigatorParameters parameters;
private Path plan;
2016-09-05 13:22:23 +02:00
private boolean planned;
2013-11-04 14:33:56 +01:00
private final Location target;
private Vector vector;
2016-08-02 18:13:21 +02:00
public FlyingAStarNavigationStrategy(NPC npc, Iterable<Vector> path, NavigatorParameters params) {
super(TargetType.LOCATION);
List<Vector> list = Lists.newArrayList(path);
this.target = list.get(list.size() - 1).toLocation(npc.getStoredLocation().getWorld());
this.parameters = params;
this.npc = npc;
setPlan(new Path(list));
}
2013-11-04 14:33:56 +01:00
public FlyingAStarNavigationStrategy(final NPC npc, Location dest, NavigatorParameters params) {
super(TargetType.LOCATION);
this.target = dest;
this.parameters = params;
this.npc = npc;
}
2016-07-25 18:32:32 +02:00
@Override
public Iterable<Vector> getPath() {
return plan == null ? null : plan.getPath();
}
2013-11-04 14:33:56 +01:00
@Override
public Location getTargetAsLocation() {
return target;
}
2016-08-02 18:13:21 +02:00
public void setPlan(Path path) {
this.plan = path;
if (plan == null || plan.isComplete()) {
setCancelReason(CancelReason.STUCK);
} else {
vector = plan.getCurrentVector();
if (parameters.debug()) {
2016-08-02 18:13:21 +02:00
plan.debug();
}
}
2016-09-07 12:05:06 +02:00
planned = true;
2016-08-02 18:13:21 +02:00
}
2013-11-04 14:33:56 +01:00
@Override
public void stop() {
if (plan != null && parameters.debug()) {
2014-01-12 12:47:05 +01:00
plan.debugEnd();
}
2013-11-04 14:33:56 +01:00
plan = null;
}
@Override
public boolean update() {
2016-09-05 13:22:23 +02:00
if (!planned) {
Location location = npc.getEntity().getLocation();
VectorGoal goal = new VectorGoal(target, (float) parameters.pathDistanceMargin());
boolean found = false;
for (BlockExaminer examiner : parameters.examiners()) {
if (examiner instanceof FlyingBlockExaminer) {
found = true;
break;
}
}
if (!found) {
parameters.examiner(new FlyingBlockExaminer());
}
setPlan(ASTAR.runFully(goal, new VectorNode(goal, location,
new ChunkBlockSource(location, parameters.range()), parameters.examiners()), 50000));
}
2013-11-04 14:33:56 +01:00
if (getCancelReason() != null || plan == null || plan.isComplete()) {
return true;
}
2013-11-05 12:29:18 +01:00
Location current = npc.getEntity().getLocation(NPC_LOCATION);
2013-11-04 14:33:56 +01:00
if (current.toVector().distanceSquared(vector) <= parameters.distanceMargin()) {
plan.update(npc);
if (plan.isComplete()) {
return true;
}
vector = plan.getCurrentVector();
}
if (parameters.debug()) {
npc.getEntity().getWorld().playEffect(vector.toLocation(npc.getEntity().getWorld()), Effect.ENDER_SIGNAL,
0);
}
2013-11-04 14:33:56 +01:00
double d0 = vector.getX() + 0.5D - current.getX();
double d1 = vector.getY() + 0.1D - current.getY();
double d2 = vector.getZ() + 0.5D - current.getZ();
2013-11-05 12:29:18 +01:00
Vector velocity = npc.getEntity().getVelocity();
2013-11-04 14:33:56 +01:00
double motX = velocity.getX(), motY = velocity.getY(), motZ = velocity.getZ();
motX += (Math.signum(d0) * 0.5D - motX) * 0.1;
2017-06-09 14:31:43 +02:00
motY += (Math.signum(d1) - motY) * 0.1;
2013-11-04 14:33:56 +01:00
motZ += (Math.signum(d2) * 0.5D - motZ) * 0.1;
float targetYaw = (float) (Math.atan2(motZ, motX) * 180.0D / Math.PI) - 90.0F;
float normalisedTargetYaw = (targetYaw - current.getYaw()) % 360;
if (normalisedTargetYaw >= 180.0F) {
normalisedTargetYaw -= 360.0F;
}
if (normalisedTargetYaw < -180.0F) {
normalisedTargetYaw += 360.0F;
}
velocity.setX(motX).setY(motY).setZ(motZ).multiply(parameters.speed());
2013-11-05 12:29:18 +01:00
npc.getEntity().setVelocity(velocity);
2013-11-04 14:33:56 +01:00
if (npc.getEntity().getType() != EntityType.ENDER_DRAGON) {
2016-09-07 12:05:06 +02:00
NMS.setVerticalMovement(npc.getEntity(), 0.5);
float newYaw = current.getYaw() + normalisedTargetYaw;
current.setYaw(newYaw);
NMS.setHeadYaw(npc.getEntity(), newYaw);
npc.teleport(current, TeleportCause.PLUGIN);
}
2014-01-12 05:50:05 +01:00
parameters.run();
plan.run(npc);
2013-11-04 14:33:56 +01:00
return false;
}
private static final AStarMachine<VectorNode, Path> ASTAR = AStarMachine.createWithDefaultStorage();
private static final Location NPC_LOCATION = new Location(null, 0, 0, 0);
}