-
-
Notifications
You must be signed in to change notification settings - Fork 294
/
AStarNavigationStrategy.java
133 lines (120 loc) · 5.01 KB
/
AStarNavigationStrategy.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package net.citizensnpcs.npc.ai;
import java.util.List;
import org.bukkit.Effect;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.material.Door;
import org.bukkit.util.Vector;
import com.google.common.collect.Lists;
import net.citizensnpcs.Settings.Setting;
import net.citizensnpcs.api.ai.AbstractPathStrategy;
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.ChunkBlockSource;
import net.citizensnpcs.api.astar.pathfinder.MinecraftBlockExaminer;
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;
public class AStarNavigationStrategy extends AbstractPathStrategy {
private final Location destination;
private final NPC npc;
private final NavigatorParameters params;
private Path plan;
private boolean planned = false;
private Vector vector;
public AStarNavigationStrategy(NPC npc, Iterable<Vector> path, NavigatorParameters params) {
super(TargetType.LOCATION);
List<Vector> list = Lists.newArrayList(path);
this.params = params;
this.destination = list.get(list.size() - 1).toLocation(npc.getStoredLocation().getWorld());
this.npc = npc;
setPlan(new Path(list));
}
public AStarNavigationStrategy(NPC npc, Location dest, NavigatorParameters params) {
super(TargetType.LOCATION);
this.params = params;
this.destination = dest;
this.npc = npc;
}
@Override
public Iterable<Vector> getPath() {
return plan == null ? null : plan.getPath();
}
@Override
public Location getTargetAsLocation() {
return destination;
}
public void setPlan(Path path) {
this.plan = path;
this.planned = true;
if (plan == null || plan.isComplete()) {
setCancelReason(CancelReason.STUCK);
} else {
vector = plan.getCurrentVector();
if (params.debug()) {
plan.debug();
}
}
}
@Override
public void stop() {
if (plan != null && params.debug()) {
plan.debugEnd();
}
plan = null;
}
@Override
public boolean update() {
if (!planned) {
Location location = npc.getEntity().getLocation();
VectorGoal goal = new VectorGoal(destination, (float) params.pathDistanceMargin());
setPlan(ASTAR.runFully(goal,
new VectorNode(goal, location, new ChunkBlockSource(location, params.range()), params.examiners()),
Setting.MAXIMUM_ASTAR_ITERATIONS.asInt()));
}
if (getCancelReason() != null || plan == null || plan.isComplete()) {
return true;
}
Location currLoc = npc.getEntity().getLocation(NPC_LOCATION);
Vector destVector = new Vector(vector.getX() + 0.5, vector.getY(), vector.getZ() + 0.5);
if (currLoc.toVector().distanceSquared(destVector) <= params.distanceMargin()) {
plan.update(npc);
if (plan.isComplete()) {
return true;
}
vector = plan.getCurrentVector();
}
double dX = vector.getBlockX() - currLoc.getX();
double dZ = vector.getBlockZ() - currLoc.getZ();
double dY = vector.getY() - currLoc.getY();
double xzDistance = dX * dX + dZ * dZ;
double distance = xzDistance + dY * dY;
if (params.debug()) {
npc.getEntity().getWorld().playEffect(vector.toLocation(npc.getEntity().getWorld()), Effect.ENDER_SIGNAL,
0);
}
if (distance > 0 && dY > NMS.getStepHeight(npc.getEntity()) && xzDistance <= 2.75) {
NMS.setShouldJump(npc.getEntity());
}
Block block = currLoc.getWorld().getBlockAt(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ());
if (MinecraftBlockExaminer.isDoor(block.getType())) {
Door door = (Door) block.getState().getData();
if (door.isOpen()) {
BlockFace targetFace = door.getFacing().getOppositeFace();
destVector.setX(vector.getX() + targetFace.getModX());
destVector.setZ(vector.getZ() + targetFace.getModZ());
}
}
NMS.setDestination(npc.getEntity(), destVector.getX(), destVector.getY(), destVector.getZ(), params.speed());
params.run();
plan.run(npc);
return false;
}
private static final AStarMachine<VectorNode, Path> ASTAR = AStarMachine.createWithDefaultStorage();
private static final Location NPC_LOCATION = new Location(null, 0, 0, 0);
}