Skip to content

PML compatibility ​

TSPML intends to run PolyModLoader (PML) format mods eventually, either natively or through an adapter mod. That is a stated direction, not a shipped feature. Nothing in TSPML loads a PML mod today.

This page exists so the intent is written down honestly: what is already reserved for it, what an adapter could realistically carry, and the one part that is not translatable in general and never will be.

Status

Not implemented. A PML mod URL imported into the portal today is refused by name, with the reason stated, rather than half-parsed into something that looks installed and then does nothing.

Why bother ​

PML, by polytrackmods, was the first PolyTrack mod loader and it pioneered modding for the game. The mods that exist, exist for it. A player who already has a PML mod they like should not have to wait for someone to rewrite it before TSPML is useful to them, and a modder should not have to pick a side to reach both audiences.

The two loaders made different architectural bets (see What is TSPML?), and those bets are exactly why compatibility is partial rather than total. The differences below are trade-offs, not defects.

What is reserved today ​

Two seams exist now so that adding the feature later is not a schema migration:

  • A format discriminator. Every stored mod record and every registry entry carries format: "tspml" | "pml", defaulting to tspml when absent. This is what would tell the loader how to execute the code: TSPML expects a default-export factory that receives api, while PML exports a named polyMod binding and talks to a pml global. Storage schemas are much harder to retrofit than code, so the field was reserved from day one.
  • A format dispatch step in the importer. URL import runs host and size policy first, then picks a format handler, then delegates. The handler interface takes a base URL and may fetch more than once, because a PML mod is a directory tree (manifest.json, then a per-version file, then the mod's main JavaScript) rather than a single manifest with relative siblings. An interface that assumed one fetch would have to be rewritten to support PML at all.

The PML handler currently contains one thing: a refusal that names its reason.

What an adapter could carry ​

These map onto things TSPML already has, so a translation is a matter of work rather than a matter of luck:

PML surfaceTSPML equivalentOutlook
preInit / init / postInit / onGameLoadThe mod entrypoint plus track.afterLoad and friendsPlausible. Ordering differs, so a mod that depends on subtle interleaving may still misbehave.
registerSetting / getSettingNo direct equivalent yet; a settings registry would be new workPlausible, and useful independently of PML.
registerKeybindapi.keybindsPlausible.
pmlapi audioapi.audioPlausible.
editorExtras.registerModel and custom blocksPartly covered; block registration is not builtPlausible, with real work behind it.
Semver dependency resolutionThe loader's own depends / provides topo-sortAlready equivalent in shape.

What cannot be translated ​

PML mixins are not translatable in general. This is the load-bearing limit and it is worth being precise about why.

PML patches a function by reading originalFunc.toString(), finding a literal substring of the minified source with indexOf, splicing text in at that offset, and writing the result back with eval. The token being searched for is minified game source: mangled identifier names, exact spacing, whatever the mangler emitted for that build. The injected code then runs in game scope, not the mod's.

TSPML patches structurally. A mod names a stable symbol such as Car.controlCar, the mappings file resolves that to a concrete AST target for the running build, and the patch is applied to the parsed tree. If the symbol does not resolve, the patch fails closed and reports why.

There is no mechanical route from the first to the second. A substring of minified text does not carry enough information to say where in the syntax tree it sits, or which stable concept it belongs to. Recovering that would mean re-deriving the mapping by hand for every token in every PML mod, for every game build. That is the work TSPML does once per build for the whole game; doing it per mod per build is the cost the mappings layer exists to avoid.

So an adapter's honest behaviour for mixins is:

  • Refuse or degrade per call, never abort boot. PML itself throws and stops loading when a token is not found. TSPML's failure model is the opposite: a failing patch fails that mod's row and nothing else. An adapter must keep that property, which means a registerClassMixin it cannot honour is one refused call with a named reason, not a dead mod and certainly not a dead loader.
  • Say so in the report. A mod that loaded with three of its five mixin calls refused is not "working". The per-mod report has to name what was dropped, the same way mixin and physics reports do now.

The same applies to registerChunkMixin, registerSimWorkerMixin, and registerPhysicsLibMixin: all three are token-and-splice against build-specific text.

There is also a security floor an adapter does not get to lower. PML exposes getFromPolyTrackGlobal(path), which is eval over the game's whole module graph. TSPML will not reproduce an arbitrary eval sink into game internals as an API, so a PML mod built on it is out of scope regardless of how the rest of the translation goes.

The realistic target ​

Partial compatibility, honestly labelled. A PML mod whose behaviour lives in lifecycle hooks, settings, keybinds, audio, and model registration is a reasonable candidate. A PML mod whose behaviour is its mixins is not, and the right outcome there is a clear refusal naming the calls that could not be carried, so an author knows what to port rather than guessing why their mod does nothing.

Anything that ships will follow the rule the rest of the loader follows: a surface that cannot be provided correctly degrades to vanilla with a reason, and never silently patches the wrong thing.

Following along ​

Tracked in the TSPML repository at github.com/roowus/TSPML/issues. The reserved seams described above are the only part that is currently code.

TSPML is a fan-made tool. It never redistributes PolyTrack; the portal transforms your own live copy of the game.