RuneHive-Tarnish
Neural OSRS Enhancement Framework
Loading...
Searching...
No Matches
AStarPathFinder.java
1package com.osroyale.game.world.pathfinding.path.impl;
2
3import com.osroyale.game.world.Interactable;
4import com.osroyale.game.world.entity.mob.Direction;
5import com.osroyale.game.world.entity.mob.Mob;
6import com.osroyale.game.world.pathfinding.distance.Distance;
7import com.osroyale.game.world.pathfinding.path.Path;
8import com.osroyale.game.world.pathfinding.path.PathFinder;
9import com.osroyale.game.world.position.Position;
10import com.osroyale.game.world.region.Region;
11
12import java.util.*;
13
59
60public final class AStarPathFinder extends PathFinder {
61
63 private final Distance heuristic;
64 private final Mob character;
65 private final Map<Position, Node> nodes = new HashMap<>(Region.SIZE * Region.SIZE);
66 private final Set<Node> open = new HashSet<>(Region.SIZE * Region.SIZE);
67 private final Queue<Node> sorted = new PriorityQueue<>(Region.SIZE * Region.SIZE);
68 private final Deque<Position> shortest = new ArrayDeque<>(100);
69
74 public AStarPathFinder(Mob character, Distance heuristic) {
75 this.character = character;
76 this.heuristic = heuristic;
77 }
78
86 public Path find(Position destination) {
87 Position origin = character.getPosition();
88 if (origin.getHeight() != destination.getHeight())
89 return new Path(null);
90 return find(character, destination);
91 }
92
100 public Path find(Interactable destination) {
101 Position origin = character.getPosition();
102 if (origin.getHeight() != destination.getHeight())
103 return new Path(null);
104 return find(character, destination);
105 }
106
116 @Override
117 public Path find(Mob source, Position target, int targetWidth, int targetLength) {
118 if (source.getHeight() != target.getHeight())
119 return new Path(null);
120
121 Node start = new Node(source.getPosition()), end = new Node(target);
122
123 open.clear();
124 nodes.clear();
125 sorted.clear();
126 shortest.clear();
127
128 nodes.put(source.getPosition(), start);
129 nodes.put(target, end);
130
131 open.add(start);
132 sorted.add(start);
133
134 Node active;
135 Position next;
136 boolean found = false;
137 int distance = (int) (source.getPosition().getDistance(target) * Region.SIZE);
138
139 do {
140 active = getCheapest(sorted);
141 Position position = active.getPosition();
142
143 if (position.equals(target)) {
144 found = true;
145 break;
146 }
147
148 open.remove(active);
149 active.close();
150
151 for (Direction direction : Direction.valid()) {
152 next = position.transform(direction.getFaceLocation());
153 if (traversable(position, source.width(), direction) && traversable(next, source.width(), Direction.getOppositeDirection(direction))) {
154 Node node = nodes.computeIfAbsent(next, Node::new);
155 compare(active, node);
156 }
157 }
158 } while (!open.isEmpty() && sorted.size() < distance);
159
160 if (found) {
161
162 if (end.hasParent()) {
163 active = end;
164 }
165
166 if (active.hasParent()) {
167 Position position = active.getPosition();
168
169 while (!source.getPosition().equals(position)) {
170 shortest.addFirst(position);
171 active = active.getParent();
172 position = active.getPosition();
173
174 if (shortest.size() >= 100) {
175 break;
176 }
177 }
178 }
179
180 return new Path(shortest);
181 }
182 return new Path(null);
183 }
184
185 private void compare(Node active, Node other) {
186 int cost = active.getCost() + heuristic.calculate(active.getPosition(), other.getPosition());
187 if (other.getCost() > cost) {
188 open.remove(other);
189 other.close();
190 } else if (other.isOpen() && !open.contains(other)) {
191 other.setCost(cost);
192 other.setParent(active);
193 open.add(other);
194 sorted.add(other);
195 }
196 }
197
204 private Node getCheapest(Queue<Node> nodes) {
205 Node node = nodes.peek();
206 while (!node.isOpen()) {
207 nodes.poll();
208 node = nodes.peek();
209 }
210 return node;
211 }
212
213}
214
223final class Node implements Comparable<Node> {
224
226 private int cost;
227
229 private boolean open = true;
230
232 private Node parent;
233
235 private final Position position;
236
242 Node(Position position) {
243 this(position, 0);
244 }
245
252 private Node(Position position, int cost) {
253 this.position = position;
254 this.cost = cost;
255 }
256
262 void setCost(int cost) {
263 this.cost = cost;
264 }
265
271 int getCost() {
272 return cost;
273 }
274
278 public void close() {
279 open = false;
280 }
281
287 public boolean isOpen() {
288 return open;
289 }
290
296 void setParent(Node parent) {
297 this.parent = parent;
298 }
299
306 Node getParent() {
307 return parent;
308 }
309
316 boolean hasParent() {
317 return parent != null;
318 }
319
325 public Position getPosition() {
326 return position;
327 }
328
335 @Override
336 public int compareTo(Node other) {
337 return Integer.compare(cost, other.cost);
338 }
339
347 @Override
348 public final boolean equals(Object obj) {
349 if (this == obj) return true;
350 if (!(obj instanceof Node)) return false;
351 Node other = (Node) obj;
352 return getPosition().getX() == other.getPosition().getX()
353 && getPosition().getY() == other.getPosition().getY()
354 && getPosition().getHeight() == other.getPosition().getHeight()
355 && getCost() == other.getCost()
356 && getParent().getCost() == other.getParent().getCost()
357 && getParent().getPosition().getX() == other.getParent().getPosition().getX()
358 && getParent().getPosition().getY() == other.getParent().getPosition().getY()
359 && getParent().getPosition().getHeight() == other.getPosition().getHeight();
360 }
361
367 @Override
368 public final int hashCode() {
369 final int prime = 31;
370 int result = 1;
371 result = prime * result + position.getX();
372 result = prime * result + position.getY();
373 result = prime * result + position.getHeight();
374 if (hasParent()) {
375 Position p = parent.getPosition();
376 result = prime * result + p.getX();
377 result = prime * result + p.getY();
378 result = prime * result + p.getHeight();
379 }
380 result = prime * result + cost;
381 return result;
382 }
383
384}
385
boolean traversable(Position current, int size, Direction... directions)
Path find(Mob source, Position target, int targetWidth, int targetLength)
Position transform(int diffX, int diffY, int diffZ)