Global collision/hybrid live collision#9
Merged
infuse21 merged 7 commits intoJul 23, 2026
Merged
Conversation
Adds an immutable live-collision overlay on top of the static SplitFlagMap so pathfinding and smoothing can reflect the loaded scene, gated by a config flag that defaults OFF. Out-of-scene routing is unchanged — the static map still owns global routes. New pathfinder/live package: - LiveCollisionSnapshot: immutable, world-addressed, known/value per edge so the scene rim reads as unknown and falls back to the static map. - LiveCollisionOverlay: shared, atomically-swapped volatile holder read lock-free by every CollisionMap. - LiveCollisionCapture: client-thread builder mirroring Rs2Tile's CollisionDataFlag translation; instances return null (static fallback) pending dedicated chunk mapping. CollisionMap.get() consults a per-search pinned snapshot then the static map, so both neighbour expansion and PathSmoother pick it up from one place. PathfinderConfig owns the shared overlay behind its ThreadLocal<CollisionMap>; Pathfinder.run() pins the snapshot per search so a mid-search swap cannot mix two scenes. ShortestPathPlugin rebuilds the snapshot on scene-base change from the onGameTick client thread (no per-tick allocation). With the flag off a CollisionMap reads byte-for-byte as the static-only map, so the existing shortestpath suite is unchanged. New LiveCollisionTest covers the flag translation (walls, symmetry, full-block closing all four edges), rim/out-of-scene fallback, overlay-wins-in-scene, and no-overlay determinism. Guardrail stays green. Stage 2 (door/openable-edge preservation) and Stage 3 (debounced scene-change recalc) follow. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ge 2) A closed door blocks its doorway in RuneLite's live collision, so with the overlay on the pathfinder would route around an openable door instead of walking up and opening it — the static map treats the doorway as passable and the runtime door subsystem (Rs2Walker.handleDoors) opens the physical door as the path crosses it. LiveCollisionCapture now scans the loaded scene on the client thread for wall objects with a door action (open / go-through / walk-through / pass / pick-lock / pay-toll, incl. multiloc impostors) and leaves every edge touching such a tile UNKNOWN in the snapshot. Unknown edges already fall back to the static map in CollisionMap.get, so the existing door pipeline keeps owning doors unchanged — no CollisionMap change needed. Transports need no handling: getNeighbors adds transport edges independently of the collision traversability check, so a live-blocked walking edge never removes a transport edge. That, plus the door exemption, covers the false-"unreachable" cases without a blanket fallback that would defeat live blocking of genuine new obstacles. Tests: door-tile edges stay unknown even when live flags block all four sides; null door mask matches the no-door path. Full suite and guardrail green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
GET /live-collision[?x=&y=&plane=] reports whether the live-collision overlay is enabled and captured, the snapshot's scene base, and per-tile the overlay's own edge readings (overlayRaw: true/false/null=defer-to-static), the resolved edges the pathfinder uses, and the static-only edges. Where resolved differs from static, live collision is changing routing. The overlay and pathfinder are otherwise not observable over HTTP; this exists to verify the hybrid live-collision work against a running client. Logic lives in PathfinderConfig.liveCollisionDiagnostics (immutable reads, any thread); the handler is thin. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
RuneLite's collision for the outer ring of the loaded scene is incomplete while adjacent chunks are only partially loaded. Verified against a running client: the border produced a uniform band of ~1260 false walls out to about five tiles deep, while the deep interior matched reality. Stage 1's rim handling only exempted the outermost neighbour-out-of-scene edges, so those false walls leaked into the overlay and would fabricate obstacles near every scene boundary. LiveCollisionCapture now treats any tile within SCENE_BORDER_MARGIN (8) of the scene edge as unknown, deferring to the static map there. The scene always loads centred on the player (~tile 52 of 104), so the trusted ~88x88 interior still covers everything near the player, and the border recentres before the player reaches it. Eight gives headroom over the ~5 tiles of artifact observed (real live-vs-static differences began at ~24 tiles in, a clean gap). Re-verified live after the fix: border diffs 1260 -> 0, while the genuine interior corrections (incl. 3 stale-static unblocks) are preserved. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…stage 3) Stage 1 refreshed the overlay only on scene-base change, so a door closing or a temporary object appearing mid-scene was not picked up until the next reload, and the walker would walk into it and stall. Now object spawn/despawn (game + wall) mark the snapshot dirty, and refreshLiveCollision rebuilds it at most once per tick. After a mid-scene rebuild it validates the walker's remaining route against the fresh overlay via LiveRouteValidator and, if a walking step within a 15-tile look-ahead is now blocked, calls the walker's public recalculatePath() so it routes around before stalling. Cooldown-gated (3s) so churn cannot spam recalcs. Driven entirely from the plugin's onGameTick (client thread) using public walker API — the walker's internal loop is untouched. Openable doors and transports are skipped by LiveRouteValidator (door edges are unknown in the overlay, transport jumps are non-adjacent), so this never fights the runtime door handler. Scene reloads do not trigger a proactive recalc (they usually just recenter); the walker's own machinery picks up the fresh snapshot there. LiveRouteValidator is a pure helper with unit tests: nearest-index, detects a live-blocked walking step, skips transport/cross-plane jumps, respects the look-ahead bound. The four object subscribers only set a volatile flag (no client reads), so the guardrail is unaffected. Full suite green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.