RuneHive-Game
Loading...
Searching...
No Matches
Movement.java
Go to the documentation of this file.
1package com.runehive.game.world.entity.mob.movement;
2
3import com.runehive.game.world.Interactable;
4import com.runehive.game.world.entity.mob.Direction;
5import com.runehive.game.world.entity.mob.Mob;
6import com.runehive.game.world.entity.mob.data.PacketType;
7import com.runehive.game.world.pathfinding.distance.Manhattan;
8import com.runehive.game.world.pathfinding.path.Path;
9import com.runehive.game.world.pathfinding.path.impl.AStarPathFinder;
10import com.runehive.game.world.pathfinding.path.impl.DijkstraPathFinder;
11import com.runehive.game.world.pathfinding.path.impl.SimplePathFinder;
12import com.runehive.game.world.position.Position;
13import com.runehive.net.packet.out.SendConfig;
14import com.runehive.net.packet.out.HintArrowTile;
15import com.runehive.net.packet.out.HintArrowClear;
16
17import java.util.ArrayDeque;
18import java.util.Deque;
19
20/**
21 * Handles the movement for the player.
22 *
23 * @author Graham Edgecombe
24 */
25public class Movement {
26 /** The maximum size of the queue. If there are more points than this size, they are discarded. */
27 private static final int MAXIMUM_SIZE = 50;
28
29 /** The smart path finder. */
31
32 /** The smart path finder. */
34
35 /** The smart path finder. */
37
38 /** The mob. */
39 private Mob mob;
40
41 /** The queue of waypoints. */
42 private Deque<Point> waypoints = new ArrayDeque<>();
43
44 /** The last direction the mob walked in. Default to south */
46
47 /** Mob is moving. */
48 private boolean isMoving;
49
50 /** Run toggle (button in client). */
51 private boolean runToggled = false;
52
53 /** Run for this queue (CTRL-CLICK) toggle. */
54 private boolean runQueue = false;
55
56 private int walkingDirection = -1;
57 private int runningDirection = -1;
58
59 /** Destination hint-arrow state */
62
63 /** Creates the <code>WalkingQueue</code> for the specified */
64 public Movement(Mob mob) {
65 this.mob = mob;
66 this.smartPathFinder = new AStarPathFinder(mob, new Manhattan());
67 }
68
69 /** Walks to a certain position. */
70 public void walk(Position position) {
71 reset();
72 addStep(position.getX(), position.getY());
73 finish();
74 }
75
76 /** Handles mob walking to certain coordinates. */
77 public void walkTo(int x, int y) {
78 final int newX = mob.getX() + x;
79 final int newY = mob.getY() + y;
80 reset();
81 addStepInternal(newX, newY);
82 finish();
83 }
84
85 /** Handles mob walking to a certain position. */
86 public void walkTo(Position position) {
87 reset();
88 addStepInternal(position.getX(), position.getY());
89 finish();
90 }
91
92 /** Sets the run toggled flag. */
93 public void setRunningToggled(boolean runToggled) {
94 this.runToggled = runToggled;
95 if (mob.isPlayer()) {
96 mob.getPlayer().send(new SendConfig(152, runToggled ? 1 : 0));
97 }
98 }
99
100 /** Resets the walking queue so it contains no more steps. */
101 public void reset() {
102 runQueue = false;
103 waypoints.clear();
104 waypoints.add(new Point(mob.getX(), mob.getY(), -1));
105
106 // Clear any active hint
107 if (mob.isPlayer() && destinationHint != null) {
108 new HintArrowClear().execute(mob.getPlayer());
109 destinationHint = null;
110 lastSentHint = null;
111 }
112 }
113
114 /** Removes the first waypoint which is only used for calculating directions. This means walking begins at the correct time. */
115 public void finish() {
116 waypoints.removeFirst();
117 }
118
119 /** Adds a single step to the walking queue, filling in the points to the previous point in the queue if necessary. */
120 public void addStep(int x, int y) {
121// if (mob.locked()) return;
122 if (waypoints.size() == 0)
123 reset();
124 Point last = waypoints.peekLast();
125 int diffX = x - last.x;
126 int diffY = y - last.y;
127 int max = Math.max(Math.abs(diffX), Math.abs(diffY));
128 for (int i = 0; i < max; i++) {
129 if (diffX < 0) {
130 diffX++;
131 } else if (diffX > 0) {
132 diffX--;
133 }
134 if (diffY < 0) {
135 diffY++;
136 } else if (diffY > 0) {
137 diffY--;
138 }
139 addStepInternal(x - diffX, y - diffY);
140 }
141 }
142
143 /**
144 * Adds a single step to the queue internally without counting gaps. This
145 * method is unsafe if used incorrectly so it is private to protect the
146 * queue.
147 */
148 private void addStepInternal(int x, int y) {
149 if (waypoints.size() >= MAXIMUM_SIZE)
150 return;
151 Point last = waypoints.peekLast();
152 int diffX = x - last.x;
153 int diffY = y - last.y;
154 int dir = Direction.direction(diffX, diffY);
155 if (dir > -1)
156 waypoints.add(new Point(x, y, dir));
157 }
158
159 /** Processes the next player's movement. */
160 public void processNextMovement() {
161 boolean teleporting = mob.teleportTarget != null;
162 if (teleporting) {
163 reset();
164 mob.positionChange = true;
165 mob.setPosition(mob.teleportTarget);
166 mob.clearTeleportTarget();
167 } else {
168 Point walkPoint, runPoint = null;
169 walkPoint = getNextPoint();
170
171 if (runToggled || runQueue) {
172 runPoint = getNextPoint();
173 }
174
175 int walkDir = walkPoint == null ? -1 : walkPoint.dir;
176 int runDir = runPoint == null ? -1 : runPoint.dir;
177 if (runDir != -1) lastDirection = Direction.DIRECTIONS.get(runDir);
178 else if (walkDir != -1) lastDirection = Direction.DIRECTIONS.get(walkDir);
179 this.walkingDirection = walkDir;
180 this.runningDirection = runDir;
181 }
182 int diffX = mob.getPosition().getLocalX(mob.lastPosition);
183 int diffY = mob.getPosition().getLocalY(mob.lastPosition);
184 boolean changed = false;
185 if (diffX < 16) {
186 changed = true;
187 } else if (diffX >= 88) {
188 changed = true;
189 }
190 if (diffY < 16) {
191 changed = true;
192 } else if (diffY >= 88) {
193 changed = true;
194 }
195 if (changed)
196 mob.regionChange = true;
197
198// if (mob.attributes.has("mob-following")) {
199// Waypoint waypoint = mob.attributes.get("mob-following");
200// waypoint.onChange();
201// }
202 }
203
204 /** Gets the next point of movement. */
205 private Point getNextPoint() {
206 Point p = waypoints.poll();
207 if (p == null || p.dir == -1) {
208 if (isMoving)
209 isMoving = false;
210 return null;
211 } else {
212 int diffX = Direction.DELTA_X[p.dir];
213 int diffY = Direction.DELTA_Y[p.dir];
214 mob.setPosition(mob.getPosition().transform(diffX, diffY));
215 if (!isMoving)
216 isMoving = true;
217 mob.onStep();
218
219 // Clear the arrow once we arrive at the destination or no steps remain
220 if (mob.isPlayer() && destinationHint != null) {
221 boolean arrived = mob.getPosition().equals(destinationHint);
222 boolean noMoreSteps = waypoints.isEmpty();
223 if (arrived || noMoreSteps) {
224 new HintArrowClear().execute(mob.getPlayer());
225 destinationHint = null;
226 lastSentHint = null;
227 }
228 }
229 return p;
230 }
231 }
232
233 /** Finds a smart path to the target. */
234 public boolean simplePath(Position destination) {
235 return !mob.locking.locked(PacketType.MOVEMENT) && addPath(SIMPLE_PATH_FINDER.find(mob, destination));
236 }
237
238 /** Finds a medium path to the target. */
239 public boolean dijkstraPath(Position destination) {
240 return !mob.locking.locked(PacketType.MOVEMENT) && addPath(DIJKSTRA_PATH_FINDER.find(mob, destination));
241 }
242
243 /** Finds a smart path to the target. */
244 public boolean aStarPath(Position destination) {
245 return !mob.locking.locked(PacketType.MOVEMENT) && addPath(smartPathFinder.find(mob, destination));
246 }
247
248 /** Finds a smart path to the target. */
249 public boolean simplePath(Interactable interactable) {
250 return !mob.locking.locked(PacketType.MOVEMENT) && addPath(SIMPLE_PATH_FINDER.find(mob, interactable));
251 }
252
253 /** Finds a medium path to the target. */
254 public boolean dijkstraPath(Interactable interactable) {
255 return !mob.locking.locked(PacketType.MOVEMENT) && addPath(DIJKSTRA_PATH_FINDER.find(mob, interactable));
256 }
257
258 /** Finds a smart path to the target. */
259 public boolean aStarPath(Interactable interactable) {
260 return !mob.locking.locked(PacketType.MOVEMENT) && addPath(smartPathFinder.find(mob, interactable));
261 }
262
263 /** Finds a smart path to the target. */
264 public boolean addPath(Path path) {
265 if (!path.isPossible() || mob.locking.locked(PacketType.MOVEMENT))
266 return false;
267 path.addSteps(this);
268
269 // Set/update the destination hint after steps are enqueued
270 if (mob.isPlayer() && !waypoints.isEmpty()) {
271 Point last = waypoints.peekLast();
272 Position dest = new Position(last.x, last.y, mob.getHeight());
273 destinationHint = dest;
274 if (lastSentHint == null || !lastSentHint.equals(dest)) {
275 new HintArrowTile(dest).execute(mob.getPlayer());
276 lastSentHint = dest;
277 }
278 }
279 return true;
280 }
281
282 /** Sets the run queue flag. */
283 public void setRunningQueue(boolean runQueue) {
284 this.runQueue = runQueue;
285 }
286
287 /** Gets the run toggled flag. */
288 public boolean isRunningToggled() {
289 return runToggled;
290 }
291
292 /** Gets the running queue flag. */
293 public boolean isRunningQueue() {
294 return runQueue;
295 }
296
297 /** Checks if any running flag is set. */
298 public boolean isRunning() {
299 return runToggled || runQueue;
300 }
301
302 public boolean isMoving() {
303 return isMoving;
304 }
305
306 public boolean isMovementDone() {
307 return waypoints.size() == 0;
308 }
309
310 public boolean hasSteps() {
311 return !waypoints.isEmpty();
312 }
313
314 public boolean needsPlacement() {
315 return isMoving || hasSteps();
316 }
317
321
322 public int getWalkingDirection() {
323 return walkingDirection;
324 }
325
326 public int getRunningDirection() {
327 return runningDirection;
328 }
329
330 /** Re-emit hint arrow on region change */
331 public void onRegionChange() {
332 if (mob.isPlayer() && destinationHint != null) {
333 new HintArrowTile(destinationHint).execute(mob.getPlayer());
335 }
336 }
337
339 final Point last = waypoints.peekLast();
340 if (last == null) return null;
341 if (waypoints.size() == 1 && last.x == mob.getX() && last.y == mob.getY())
342 return null;
343 return new Position(last.x, last.y, mob.getHeight());
344 }
345
346}
Handles the mob class.
Definition Mob.java:66
boolean dijkstraPath(Position destination)
Finds a medium path to the target.
void walkTo(Position position)
Handles mob walking to a certain position.
Definition Movement.java:86
void walk(Position position)
Walks to a certain position.
Definition Movement.java:70
Deque< Point > waypoints
The queue of waypoints.
Definition Movement.java:42
void addStepInternal(int x, int y)
Adds a single step to the queue internally without counting gaps.
void finish()
Removes the first waypoint which is only used for calculating directions.
Direction lastDirection
The last direction the mob walked in.
Definition Movement.java:45
boolean runQueue
Run for this queue (CTRL-CLICK) toggle.
Definition Movement.java:54
boolean aStarPath(Position destination)
Finds a smart path to the target.
Position destinationHint
Destination hint-arrow state.
Definition Movement.java:60
boolean simplePath(Position destination)
Finds a smart path to the target.
boolean isRunning()
Checks if any running flag is set.
void setRunningToggled(boolean runToggled)
Sets the run toggled flag.
Definition Movement.java:93
boolean runToggled
Run toggle (button in client).
Definition Movement.java:51
static final SimplePathFinder SIMPLE_PATH_FINDER
The smart path finder.
Definition Movement.java:33
void onRegionChange()
Re-emit hint arrow on region change.
Point getNextPoint()
Gets the next point of movement.
boolean addPath(Path path)
Finds a smart path to the target.
void walkTo(int x, int y)
Handles mob walking to certain coordinates.
Definition Movement.java:77
static final DijkstraPathFinder DIJKSTRA_PATH_FINDER
The smart path finder.
Definition Movement.java:36
boolean dijkstraPath(Interactable interactable)
Finds a medium path to the target.
boolean aStarPath(Interactable interactable)
Finds a smart path to the target.
void setRunningQueue(boolean runQueue)
Sets the run queue flag.
void processNextMovement()
Processes the next player's movement.
boolean isRunningToggled()
Gets the run toggled flag.
void reset()
Resets the walking queue so it contains no more steps.
Movement(Mob mob)
Creates the WalkingQueue for the specified.
Definition Movement.java:64
void addStep(int x, int y)
Adds a single step to the walking queue, filling in the points to the previous point in the queue if ...
final AStarPathFinder smartPathFinder
The smart path finder.
Definition Movement.java:30
boolean simplePath(Interactable interactable)
Finds a smart path to the target.
static final int MAXIMUM_SIZE
The maximum size of the queue.
Definition Movement.java:27
boolean isRunningQueue()
Gets the running queue flag.
Represents a single point in the queue.
Definition Point.java:8
final int dir
The direction to walk to this point.
Definition Point.java:17
The Manhattan Distance is the distance between two points measured along axes at right angles.
Represents a single path in the path finding system.
Definition Path.java:13
void addSteps(final Movement movement)
Definition Path.java:72
boolean isPossible()
Gets the condition if the path is possible.
Definition Path.java:50
Represents a PathFinder which uses the A* search algorithm(by passingobstacles).
Represents a simple path finder which determines a straight path to the first blocked tile or it's de...
Represents a single tile on the game world.
Definition Position.java:14
Clears any active hint arrow (317 opcode 254, type=0).
Shows the flashing yellow hint arrow pointing at a world tile (317 opcode 254, type=2).
The OutgoingPacket responsible for changing settings on a client.
Represents the enumerated directions an entity can walk or face.
static final byte[] DELTA_Y
Difference in Y coordinates for directions array.
static final ImmutableList< Direction > DIRECTIONS
static final byte[] DELTA_X
Difference in X coordinates for directions array.
An object implementing Interactable has uses.