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 @Mixin into MTR’s MinecraftClientData.sync() — a client class.
  • The route overlay is a @Mixin into Xaero’s GuiMap — a client screen.
  • The old server-side broadcast logic from the original project has been removed: MTRSimulatorMixin overrides Simulator.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:

InstanceWhen 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:

ElementColor indexApprox. color
Station9Blue
Depot6Gold
Platform3Light 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

MixinTargetPurpose
MinecraftClientDataMixinorg.mtr.mod.client.MinecraftClientDataCalls requestSync() at the tail of sync().
XaeroWorldMapMixinxaero.map.gui.GuiMapInjects the route-render call into the map’s render method, and the click handler for the toggle widget.
XaeroWorldMapAccessorxaero.map.gui.GuiMap@Accessor exposing camera X/Z and zoom scale to the renderer.
MTRSimulatorMixinorg.mtr.core.simulation.SimulatorEmpty override of sync() — suppresses the old server-broadcast behavior.
MTRAccessorMixin, MainAccessorMixinorg.mtr.mod.Init, org.mtr.core.MainLegacy 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.