Skip to content

Commit bf047ca

Browse files
committed
fix(walker): streamline door and transport handoffs
1 parent e1d7c81 commit bf047ca

10 files changed

Lines changed: 552 additions & 264 deletions

File tree

docs/entity-guides/movement.md

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,8 +194,8 @@ if (bothEndpointTilesReachable
194194
continue;
195195
}
196196
if (doorOpenedButPlayerDidNotTraverse) {
197-
// Only count this as success if the nudge actually reaches/crosses the door edge.
198-
tryDoorEdgeCrossNudge(from, to, currentTarget);
197+
// Record the open edge, then let normal route selection choose the next click.
198+
markStationaryDoorOpened(doorTile);
199199
}
200200
if (hasPendingDoorLikeSceneObjectBeforeDirectClick(rawPath, path, playerLoc, DIRECT_CLICK_MAX_DISTANCE)
201201
|| handlePendingDoorBeforeRouteClick(rawPath, path, i, targetIdx, smoothedToRaw, timeoutMs,
@@ -295,3 +295,23 @@ Sticky interim targets should also clear when route-index progress goes stale. I
295295
When a route-following minimap click is outside the minimap clip, fallback clicks must stay on the raw path. A generic "reachable tile closer to target" fallback can select a tile far away from the route in open areas, especially near the final destination.
296296

297297
For adjacent same-plane shortcuts, do not treat any movement away from the origin as success. Some shortcuts, such as stepping stones, can fail and place the player on a fallback tile; once the player is settled away from the expected destination, stop the landing wait and replan from the actual tile.
298+
299+
## 14. Resume normal route selection after opening a door
300+
301+
Opening a door should only resolve the blocked route edge. Do not follow it with a special canvas click on the adjacent far-side tile. Once the open edge is stable, yield the pass and let the normal route selector click the furthest reachable raw-path tile toward the destination.
302+
303+
**Why this matters:** An explicit one-tile cross-door nudge produces a conspicuous `Open door -> Walk here on the next tile` sequence and can fail even though the newly opened route is already clear. The ordinary minimap route click both crosses the doorway and carries movement forward naturally.
304+
305+
**Pattern to follow:**
306+
307+
```java
308+
if (isDoorEdgeResolved(from, to)) {
309+
markStationaryDoorOpened(doorTile);
310+
markNearbyDoorFamilyOpened(door, doorTile, action, radius);
311+
}
312+
return true; // next pass selects the furthest reachable route tile
313+
```
314+
315+
**Where this applies:** `Rs2Walker` door interaction handlers, recent-door recovery, and any post-door continuation logic.
316+
317+
**Defensive check:** After an `Open` interaction, the next walk action should target a forward route checkpoint, not the door edge's adjacent destination tile.

runelite-client/src/main/java/net/runelite/client/plugins/microbot/GameChatAppender.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,11 @@ protected void append(ILoggingEvent event) {
6767
if (!Microbot.isLoggedIn()) return;
6868

6969
final String formatted = layout.doLayout(event);
70-
// use invoke so we don't stall the calling thread
71-
Microbot.getClientThread().invoke(() ->
70+
// AppenderBase holds its monitor while append runs. A synchronous client-thread invoke here
71+
// deadlocks when the client thread logs at the same time: the background logger owns the
72+
// appender monitor and waits for Client, while Client waits for the appender monitor.
73+
// Chat mirroring is fire-and-forget, so enqueue it without waiting.
74+
Microbot.getClientThread().invokeLater(() ->
7275
Microbot.getClient().addChatMessage(ChatMessageType.ENGINE, "", formatted, "", false)
7376
);
7477
}

runelite-client/src/main/java/net/runelite/client/plugins/microbot/agentserver/handler/WalkHandler.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ protected void handleRequest(HttpExchange exchange) throws IOException {
117117
if (walkFuture.isDone()) {
118118
state = walkFuture.get();
119119
timedOut = false;
120+
completeActiveWalk(walkFuture, "agent-server:walk-completed-" + state.name());
120121
break;
121122
}
122123

@@ -126,7 +127,7 @@ protected void handleRequest(HttpExchange exchange) throws IOException {
126127
arrivedByPosition = true;
127128
timedOut = false;
128129
walkFuture.cancel(true);
129-
clearActiveWalk(walkFuture);
130+
completeActiveWalk(walkFuture, "agent-server:arrived-by-position");
130131
break;
131132
}
132133

@@ -187,16 +188,23 @@ private static synchronized Future<WalkerState> submitWalk(WorldPoint destinatio
187188
}
188189
if (activeWalk != null && !activeWalk.isDone()) {
189190
activeWalk.cancel(true);
190-
Rs2Walker.setTarget(null);
191+
Rs2Walker.clearWalkingRoute("agent-server:walk-replaced");
191192
}
192193
activeWalkTarget = destination;
193194
activeWalkReachedDistance = reachedDistance;
194195
activeWalk = WALK_EXECUTOR.submit(() -> Rs2Walker.walkWithState(destination, reachedDistance));
195196
return activeWalk;
196197
}
197198

198-
private static synchronized void clearActiveWalk(Future<WalkerState> walkFuture) {
199+
/**
200+
* Clears both the request bookkeeping and the route rendered by Shortest Path.
201+
*
202+
* <p>The identity check matters when overlapping HTTP requests replace a walk: a late
203+
* completion from the cancelled request must not clear the newer request's route.</p>
204+
*/
205+
private static synchronized void completeActiveWalk(Future<WalkerState> walkFuture, String reason) {
199206
if (activeWalk == walkFuture) {
207+
Rs2Walker.clearWalkingRoute(reason);
200208
activeWalk = null;
201209
activeWalkTarget = null;
202210
activeWalkReachedDistance = DEFAULT_REACHED_DISTANCE;

0 commit comments

Comments
 (0)