Documentation
How it works
The architecture behind MTR Surveyor — client-side data access, mixins, and safe dependency loading.
MTR Surveyor is a small mod with a clear job: read MTR’s client data, write Xaero waypoints, and draw route lines on Xaero’s World Map. Here’s how the pieces fit.
Pure client-side
The mod is client-side only in practice:
- Commands are registered via
RegisterClientCommandsEvent, so they go into the client command dispatcher. - The sync trigger is a
@Mixininto MTR’sMinecraftClientData.sync()— a client class. - The route overlay is a
@Mixininto Xaero’sGuiMap— a client screen. - The old server-side broadcast logic from the original project has been removed:
MTRSimulatorMixinoverridesSimulator.sync()with an empty body, and the player-join hook is an empty stub.
This means you can install it on your client and use it on any server, including ones running MTR but not MTR Surveyor.
Data sources
MTR keeps two client-side data instances:
| Instance | When it’s populated |
|---|---|
MinecraftClientData.getInstance() | Continuously, as the server streams MTR data to your client. |
MinecraftClientData.getDashboardInstance() | When you open the in-game MTR dashboard. |
MTR Surveyor reads both and unions them when building waypoints and route lines. This is the key design decision that lets it work without server-side cooperation — if one source is missing a station, the other often has it.
Sync flow
MTR data changes
└─> MinecraftClientData.sync() (MTR class)
└─> [TAIL inject] requestSync() (our mixin)
└─> needsSync = true
└─> on next ClientTickEvent (END)
└─> throttled to once / 100 ticks (5s)
└─> doSync()
└─> XaeroSyncHelper.performSync()
└─> remove old [MTR] waypoints
└─> station mode OR platform mode
└─> add new Waypoints to Xaero's current waypoint set
The Xaero-coupled code lives in a deliberately isolated nested class (XaeroSyncHelper) so the outer class can load without triggering Xaero classloading. A try/catch(NoClassDefFoundError) wraps the sync, so a missing Xaero never crashes the game.
Waypoint colors
The mod reuses Xaero’s numeric color indices:
| Element | Color index | Approx. color |
|---|---|---|
| Station | 9 | Blue |
| Depot | 6 | Gold |
| Platform | 3 | Light blue |
All MTR waypoints are prefixed [MTR] so they can be found and replaced on every sync pass — this is how stale waypoints get cleaned up.
Mixins
| Mixin | Target | Purpose |
|---|---|---|
MinecraftClientDataMixin | org.mtr.mod.client.MinecraftClientData | Calls requestSync() at the tail of sync(). |
XaeroWorldMapMixin | xaero.map.gui.GuiMap | Injects the route-render call into the map’s render method, and the click handler for the toggle widget. |
XaeroWorldMapAccessor | xaero.map.gui.GuiMap | @Accessor exposing camera X/Z and zoom scale to the renderer. |
MTRSimulatorMixin | org.mtr.core.simulation.Simulator | Empty override of sync() — suppresses the old server-broadcast behavior. |
MTRAccessorMixin, MainAccessorMixin | org.mtr.mod.Init, org.mtr.core.Main | Legacy accessors from the original project; currently unused by active code paths. |
Safe dependency loading — XaeroMixinPlugin
This is the bit that keeps the mod from crashing when Xaero’s World Map isn’t installed.
XaeroMixinPlugin implements SpongePowered’s IMixinConfigPlugin. At load time it checks the classloader for xaero/map/gui/GuiMap.class and remembers whether it was found. Then, for every mixin, shouldApplyMixin decides:
- If the mixin’s class name contains
.xaero.and Xaero’s World Map is not present → skip it. - Otherwise → apply it.
So with only Xaero’s Minimap installed, the world-map mixins are never applied, the GuiMap class is never referenced, and the mod loads cleanly. Waypoint sync still works; only the route overlay is unavailable.
The wrapper layer (legacy)
The wrapper/ package (MTRRoute, MTRRoutePlatform and their impls) plus MTRDataSummary are an abstraction over MTR’s two route types (Route and SimplifiedRoute). They’re inherited from the original AmberFrost project and currently aren’t exercised by the active sync paths — the sync code reads MTR data directly. They’re retained for future use and as a documentation of MTR’s route model.