This is a tool to create mods for and to edit functions within Polytrack 0.6.0
Also in this folder is a decompiled copy of Polytrack 0.6.0
It covers:
- how the packaged mod loader works
- how to create and install folder-based mods
- what the built-in mod API exposes [more API points to come]
- optional advanced workflows for editing tracks or repacking the app bundle
After installation, the important files live inside the PolyTrack install folder:
<PolyTrack>
PolyTrack.exe
mods\
ctrl-boost\
_template\
README_MODS.md
resources\
app.asar
app.asar.original (created automatically the first time the app is repacked)
Runtime requirements for this mod system are:
resources\app.asar- the
modsfolder
Nothing outside the PolyTrack folder is required for normal use.
When PolyTrack starts, the mod loader appears before the main menu.
Behavior:
Vanillastarts the game without loading an external gameplay mod.- Any non-vanilla mod starts the game in modded mode.
- Vanilla uses the normal blue PolyTrack branding.
- Non-vanilla mods use the red/gold branding by default so modded builds are visually obvious.
The recommended way to make mods for this package is to create folder-based mods inside:
<PolyTrack>\mods
This is safer than editing app.asar directly, easier to share, and what the boot selector is designed to load.
Each playable mod needs its own folder with:
<PolyTrack>\mods\<your-mod>\
manifest.json
mod.js
The loader ignores folders that start with _, so _template is provided as a safe starting point that will not appear in the selector until copied and renamed.
- Copy
_templateto a new folder, for examplemy-first-mod. - Edit
manifest.json. - Change the
idin bothmanifest.jsonandmod.js. - Add your mod logic to
mod.js. - Launch PolyTrack and select your mod in the boot menu.
Example:
{
"id": "my_first_mod",
"name": "My First Mod",
"version": "1.0.0",
"author": "Your Name",
"gameVersion": "0.6.0",
"entry": "mod.js",
"description": "What this mod does."
}Field reference:
id: required. Lowercase letters, numbers, underscores, and hyphens only.name: required. Displayed in the boot selector.version: optional but recommended.author: optional but recommended.gameVersion: optional. Good for documentation and compatibility tracking.entry: required. Usuallymod.js.description: optional but recommended. Displayed in the selector.
Rules:
- The
idinmanifest.jsonmust match theidused inwindow.PolyTrackMods.register(...). - Duplicate mod IDs are rejected.
- If the manifest is invalid or the script fails to load, the selector will show that mod as disabled.
Each mod entry file should call:
window.PolyTrackMods.register({
id: "my_first_mod",
activate(api) {
api.log("Activated");
},
deactivate(api) {
api.log("Deactivated");
}
});Lifecycle:
activate(api)runs when the user chooses that mod and the game is about to start.deactivate(api)runs if the loader switches away from that mod before another one is activated.
For normal startup use, activate is the main place to put your logic.
The loader exposes:
window.PolyTrackMods.register({ id, activate(api), deactivate(api) })Inside activate(api) and deactivate(api), the following helpers are available:
The parsed manifest for the current mod.
Writes a namespaced log message through the Electron bridge.
Example:
api.log("Hello from my mod");Enables a built-in loader feature flag.
Currently supported built-in feature:
ctrl_boost
Example:
api.enableFeature("ctrl_boost");Disables a built-in loader feature flag.
Checks whether a built-in feature is currently enabled.
Injects a <style> tag into the page and automatically removes it when the mod is cleaned up.
Example:
api.injectStyle(`
body::after {
content: "My Mod";
position: fixed;
right: 12px;
top: 12px;
z-index: 999999;
color: white;
}
`);Waits until an element matching selector exists, then runs callback(element).
If callback returns a function, that return value is treated as cleanup and will be called automatically later.
Example:
api.waitForElement("#ui", element => {
api.log("UI is ready");
});Resolves a file inside your mod folder to a usable file:// URL.
Example:
const imageUrl = api.assetUrl("assets/banner.png");Reads JSON-backed local storage for the current mod namespace.
Writes JSON-backed local storage for the current mod namespace.
Deletes a stored value for the current mod namespace.
Registers a cleanup callback that will run when the mod is unloaded or replaced.
Example:
const onResize = () => api.log("resize");
window.addEventListener("resize", onResize);
api.addCleanup(() => window.removeEventListener("resize", onResize));window.PolyTrackMods.register({
id: "hello_mod",
activate(api) {
api.log("Hello Mod is active");
}
});window.PolyTrackMods.register({
id: "ctrl_boost",
activate(api) {
api.enableFeature("ctrl_boost");
},
deactivate(api) {
api.disableFeature("ctrl_boost");
}
});window.PolyTrackMods.register({
id: "label_mod",
activate(api) {
api.injectStyle(`
body::after {
content: "LABEL MOD";
position: fixed;
right: 16px;
bottom: 16px;
z-index: 1000000;
padding: 8px 10px;
background: rgba(0, 0, 0, 0.65);
color: #fff;
font: 12px/1.2 sans-serif;
}
`);
}
});If a mod does not appear:
- Make sure the folder name does not start with
_. - Make sure the folder contains both
manifest.jsonandmod.js. - Make sure the manifest
idmatches theregister(...)id.
If a mod appears as disabled:
- Read the error text shown in the boot selector.
- Check for JSON mistakes in
manifest.json. - Check for JS syntax errors or registration errors in
mod.js.
If you only see vanilla:
- Confirm the mod files are in
<PolyTrack>\mods. - Confirm the package was extracted into the actual PolyTrack install folder.
- Confirm
resources\app.asarfrom this package has replaced the original one.
Folder-based mods are the supported path for this package. If you need deeper changes, the included tools can help with advanced workflows.
track_tool.js can decode and encode PolyTrack track strings.
Usage:
node "<PolyTrack_mod_tools>\track_tool.js" decode "<input.track>" "<output.json>"
node "<PolyTrack_mod_tools>\track_tool.js" encode "<input.json>" "<output.track>"Notes:
decodeautodetects PolyTrack export strings and save strings.encodewrites an export string unless the JSON containskind: "save".
Useful decoded fields:
environmentId:0=Summer,1=Winter,2=DesertsunAngleRepresentation: stored in 2-degree stepsrotationAxis:0=YPositive,1=YNegative,2=XPositive,3=XNegative,4=ZPositive,5=ZNegative
If you are maintaining the loader itself or changing the packaged game files, the extracted app bundle is the advanced workspace.
Important files in an extracted bundle:
main.bundle.js: main gameplay and UI codesimulation_worker.bundle.js: simulation worker logicelectron\main.js: Electron main processelectron\preload.js: browser bridgeimages\,audio\,models\: direct asset replacement targets
repack_app.ps1 repacks an extracted app folder into app.asar.
Recommended usage is to always pass explicit paths:
powershell -ExecutionPolicy Bypass -File "<PolyTrack_mod_tools>\repack_app.ps1" `
-SourceDir "<Extracted app folder>" `
-GameDir "<PolyTrack folder>"Behavior:
- Writes the output to
<PolyTrack>\resources\app.asar - Creates
<PolyTrack>\resources\app.asar.originalthe first time it overwrites the app
enable_devtools.ps1 modifies the extracted Electron main.js so Chromium DevTools can be opened.
Recommended usage:
powershell -ExecutionPolicy Bypass -File "<PolyTrack_mod_tools>\enable_devtools.ps1" `
-SourceDir "<Extracted app folder>"This is only for advanced debugging of an extracted workspace. Normal folder-based mods do not need it.
For most users:
- Extract the mod pack into the PolyTrack install folder.
- Put mods in
<PolyTrack>\mods. - Launch PolyTrack.
- Pick a mod in the boot selector.
For mod authors:
- Copy
_template. - Edit
manifest.json. - Write
mod.js. - Test by launching the game through the packaged boot selector.
For advanced maintainers:
- Work from an extracted app bundle.
- Edit the bundle files directly.
- Repack with
repack_app.ps1. - Rebuild the release package if you are distributing the result.