Skip to content

Support junction routing for reversing train consists - #57

Merged
ryanbarlow97 merged 2 commits into
mainfrom
fix/reverse-junction-routing
Oct 3, 2026
Merged

ryanbarlow97 merged 2 commits into
mainfrom
fix/reverse-junction-routing

Conversation

@ryanbarlow97

Copy link
Copy Markdown
Contributor

Trains can now choose and traverse junctions while reversing. A/D acts ahead of the leading wheels; once those wheels enter, every carriage follows the same route until the whole consist clears. Reversing midway retraces that route, and adjacent occupied switches remain locked independently.

Track body orientation separately from movement direction, preserve route decisions across partial chunk loading and reloads, and convert recorded throttle samples into the current orientation. Existing saves and tapes remain readable. Downgrading after writing opposite-facing saves requires restoring matching vehicle-data backups.

Validation: Java 21 mvn clean verify passes all 675 tests. Coverage includes an engine with three carriages, both turnout directions, reverse entry/exit, changing direction midway, adjacent switches, asymmetric axles, partial loading, route recovery, legacy saves, and throttle tape frames. Opus 5.5 high and Astra reviewed the changes; their premature-lock and partial-load findings have regression coverage and fixes in ba99244.

@coderabbitai

coderabbitai Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: d55c788a-16a5-417b-b1cc-c313b397cf73
📥 Commits

Reviewing files that changed from the base of the PR and between 5ae81c0 and ba99244.

📒 Files selected for processing (11)
  • README.md
  • src/main/java/net/tfminecraft/vehicleframework/VehicleFramework.java
  • src/main/java/net/tfminecraft/vehicleframework/database/ConsistData.java
  • src/main/java/net/tfminecraft/vehicleframework/tracks/ThrottleTape.java
  • src/main/java/net/tfminecraft/vehicleframework/tracks/TrackRegistry.java
  • src/main/java/net/tfminecraft/vehicleframework/tracks/TrainRoute.java
  • src/main/java/net/tfminecraft/vehicleframework/vehicles/handlers/TrainHandler.java
  • src/test/java/net/tfminecraft/vehicleframework/database/ConsistDataTest.java
  • src/test/java/net/tfminecraft/vehicleframework/tracks/ThrottleTapeTest.java
  • src/test/java/net/tfminecraft/vehicleframework/tracks/TrainRouteTest.java
  • src/test/java/net/tfminecraft/vehicleframework/vehicles/handlers/TrainReversePlacementTest.java

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Summary

Summary by CodeRabbit

  • New Features
    • Trains can now travel through junctions in either facing direction. Turnout choices persist while the train is stopped or reversing, and remain locked until the entire train has cleared the junction.
    • Closely spaced junctions retain independent choices, and branch exits follow the connected track.
    • Train direction and junction choices are preserved when saving and loading. Existing saves remain readable.
  • Bug Fixes
    • Turnouts can no longer be changed while occupied by a train.

Walkthrough

Train movement now tracks body orientation and independent turnout choices while planning and moving consists across connected rails. Saved consist data and throttle tapes include orientation and junction choices. TrackRegistry rejects turnout changes while a junction is occupied. Tests and README cover reverse movement, persistence, relinking and turnout occupancy.

Changes

Train routing and persistence

Layer / File(s) Summary
Persist orientation and junction choices
src/main/java/net/tfminecraft/vehicleframework/database/ConsistData.java, src/main/java/net/tfminecraft/vehicleframework/tracks/ThrottleTape.java, src/test/java/net/tfminecraft/vehicleframework/database/ConsistDataTest.java, src/test/java/net/tfminecraft/vehicleframework/tracks/ThrottleTapeTest.java, README.md
Consist data and throttle tape samples now store orientation and junction choices. Missing orientation fields default to positive orientation. Tests cover round-trips and orientation-aware throttle targets.
Walk connected tracks and guard occupied turnouts
src/main/java/net/tfminecraft/vehicleframework/tracks/TrackRegistry.java, src/main/java/net/tfminecraft/vehicleframework/tracks/TrainRoute.java, src/test/java/net/tfminecraft/vehicleframework/tracks/TrainRouteTest.java
TrainRoute walks connected tracks in body direction and records junction choices. TrackRegistry checks junction occupancy before changing a turnout. Tests cover orientation, branch ends and retained choices.
Integrate orientation and route state into train handlers
src/main/java/net/tfminecraft/vehicleframework/VehicleFramework.java, src/main/java/net/tfminecraft/vehicleframework/vehicles/handlers/TrainHandler.java
TrainHandler restores and saves orientation and junction choices. Turnout selection uses train movement and leading-wheel position. Throttle recording and playback include orientation. VehicleFramework registers the handler's occupancy query.
Plan and move consists across turnouts
src/main/java/net/tfminecraft/vehicleframework/vehicles/handlers/TrainHandler.java, src/test/java/net/tfminecraft/vehicleframework/vehicles/handlers/TrainReversePlacementTest.java, README.md
TrainHandler plans car positions across connected tracks and retains route choices while cars occupy junctions. Blocked movement restores route state. Tests cover reverse travel, turnout occupancy, saving and relinking. README describes route selection and persistence.

Priority: ➖ Normal

Estimated code review effort: 4 (Complex) | ~60 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant TrainHandler
  participant TrainRoute
  participant TrackRegistry
  TrainHandler->>TrainRoute: Plan consist positions and walk the route
  TrainRoute->>TrackRegistry: Read connected tracks and junction choices
  TrackRegistry-->>TrainRoute: Return track and turnout route data
  TrainRoute-->>TrainHandler: Return positions and traversed junction choices
  TrackRegistry->>TrainHandler: Query junction occupancy before changing turnout
  TrainHandler-->>TrackRegistry: Return whether the train occupies the junction
Loading

Merge Risk: ⚪ Minimal · up to ba992

This change adds reverse junction routing, turnout locking while a train occupies a junction, and persistence of train facing and route choices. Existing saves and throttle tapes remain readable. No concrete defects were identified, and the reported tests cover the main traversal and persistence scenarios.

Security Architecture Review

Security architecture risk: 🔵 Low · up to ba992

The inspected steering path retains its mounted-captain restriction and adds occupied-switch checks. Legacy save handling is deliberate, but downgrade requires matching data backups, and some loading and recovery transitions remain unconfirmed.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The demonstrated player-controlled effect is mutation of a shared turnout selected ahead of a consist, potentially affecting other trains using that junction. The inspected path does not demonstrate control over arbitrary files, credentials, services, or server execution; broader public-API exposure remains incompletely assessed.

Security Findings and Attack Paths

  • observed — Directional player input reaches turnout selection only after mounted-captain checks. Selection checks retained and shared occupancy, and the mutation sink rechecks occupancy. This inspected path does not establish an authorization or occupied-switch bypass.

Trust Boundaries and Controls

  • observed — Persisted junction choices pass through type filtering and UUID parsing before entering runtime route state. Malformed UUID entries are ignored without preventing restoration of the remaining consist. Occupancy enforcement subsequently derives from active, bound root handlers.

Resilience and Maintainability Implications

  • observed — Unload refuses removal when saving fails. Successful removal unregisters the vehicle and performs model and entity cleanup through finally blocks. Therefore, a fully unloaded snapshot is not by itself evidence of a still-present physical train requiring a turnout lock.

Hardening Proposals

  • proposed — Make the reservation contract explicit for fully unloaded snapshots, partially loaded consists, and registry replacement. Define when ownership transfers or terminates so future lifecycle changes cannot silently weaken occupied-switch enforcement.
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@ryanbarlow97

Copy link
Copy Markdown
Contributor Author

Opus 5.5 high and Astra completed two review passes through ba992443657da89ef32a583a8f2031744ca9aaa7; both report no remaining blocking findings.

  • Fixed premature through-route locking with asymmetric axle offsets. New locks use signed support bounds; coupler clearance extends only an existing lock.
  • Fixed route loss during partial consist loading. Every carriage saves its route snapshot, unresolved links preserve it, and relinking merges snapshots before placement. Resolved consists release the locks normally.
  • Removed the duplicate carriage-placement pass identified by Opus.

The initial review regressions reproduced four failures before the fixes. Final Java 21 mvn clean verify: 675 tests, zero failures/errors/skips. Both reviewers also checked the companion documentation: TF-Minecraft/Docs#84.

Opus noted a non-blocking follow-up: a train moving with an unresolved link retains newly crossed route decisions until that link resolves. This release keeps those decisions rather than expiring a route that a missing carriage may still need when the consist is reconstructed. Bounding that history requires proving the missing cars no longer need it.

@ryanbarlow97
ryanbarlow97 merged commit 373a81b into main Oct 3, 2026
2 checks passed
@ryanbarlow97
ryanbarlow97 deleted the fix/reverse-junction-routing branch October 3, 2026 15:40
@ryanbarlow97

Copy link
Copy Markdown
Contributor Author

Released and deployed as v2.9.0.

  • CodeRabbit approved the final head with no actionable comments; Opus 5.5 high and Astra findings were addressed before merge.
  • The release build passed all 675 tests. The release artifact identifies merge commit 373a81be7b7c1db67618b2cd2cae3381b2977981; its JAR checksum and embedded version were verified.
  • Dev: installed the release JAR and restarted. VehicleFramework enabled successfully, completed setup, and the console confirmed version 2.9.0.
  • Main: installed the identical JAR on disk without restart or reload. Its existing server process and startup time remained unchanged; 2.9.0 will activate at its next restart.
  • Previous JARs, consistent SQLite snapshots, and config/data archives were backed up and verified for both environments.

JAR SHA-256: e4c0a8bc544a8b66bcdd50bd2dec4dfc8f2333c06b46948909cd899df272a7b7.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant