mirror of
https://github.com/SK8-ENGINE/skate-3-rust-engine.git
synced 2026-10-27 19:54:40 +00:00
Load ZIP mod packages and publish agent authoring guides and packaging tools
This commit is contained in:
1 parent
3611047d32
commit
b262dfdcfe
33 files changed
+668
-171
No files matched your search
@@ -0,0 +1,134 @@
|
||||
# ZIP mod packages (SDK 1)
|
||||
|
||||
For agents, start at [sdk/AGENTS.md](../sdk/AGENTS.md). For function signatures, use
|
||||
[sdk/skate.lua](../sdk/skate.lua); for callbacks/settings use [Lua SDK](lua-modding.md).
|
||||
|
||||
## Installation and updates
|
||||
|
||||
Drop a `.zip` directly into top-level `mods/` and launch `PLAY-MARIO-KART.bat`.
|
||||
Open Escape → Mods, select it and enable it. New IDs start disabled. Open mods folder
|
||||
opens this same directory. SKATE3_MODS overrides discovery; a standalone executable
|
||||
defaults to its adjacent mods/. No manual extraction is needed.
|
||||
|
||||
The game scans approximately every 500 ms. Changed enabled packages reload after a
|
||||
750 ms debounce; Rescan forces discovery. Replace the ZIP to update; remove it to
|
||||
uninstall. Stable IDs preserve compatible settings, stored outside the ZIP. Reloading
|
||||
restarts Lua and removes/recreates owner objects. Removing a driving vehicle releases
|
||||
its rider. Disabling a mod keeps its package available for later use.
|
||||
|
||||
The loader supports editable folders too, but **never install a folder and ZIP with
|
||||
the same mod ID**. All copies of a duplicate ID are rejected. Hidden directories are
|
||||
not packages. The two editable examples are under sdk/examples; live mods/ contains
|
||||
native-trainer.zip and mario-kart.zip. Archives remain local and untracked.
|
||||
|
||||
## Exact archive structure
|
||||
|
||||
```text
|
||||
my-mod.zip
|
||||
mod.json REQUIRED: manifest at archive root
|
||||
main.lua REQUIRED if manifest.entry is main.lua
|
||||
README.md recommended controls and credits
|
||||
vehicle.json optional vehicle definition
|
||||
assets/
|
||||
kart.glb optional embedded vehicle model
|
||||
help.txt optional package text data
|
||||
animations/
|
||||
rider.json optional native vehicle clips
|
||||
```
|
||||
|
||||
Do not wrap this in a my-mod/ parent folder. `entry` may name a different relative
|
||||
Lua file. Optional directory names are conventions, not magic. Paths in vehicle.json
|
||||
are **package-root relative**, even if the definition itself lives in a subdirectory.
|
||||
For the above layout, model=`assets/kart.glb`, animations.file=`animations/rider.json`.
|
||||
Lua uses `sdk.vehicle.spawn('kart','vehicle.json',position,heading)` and
|
||||
`sdk.read_text('assets/help.txt')`. A ZIP's filename does not determine its mod ID.
|
||||
|
||||
Include only files your mod needs. Vehicle GLBs must embed geometry, buffers and textures.
|
||||
Rider JSON must match the installed native skeleton exactly; FBX and .blend are authoring
|
||||
inputs, not runtime animation files. Engine audio is currently synthesized through the
|
||||
vehicle definition; adding arbitrary WAV/MP3 files does not make them playable.
|
||||
No executable binaries or external Lua modules are loaded.
|
||||
|
||||
## Minimal complete mod
|
||||
|
||||
mod.json:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "yourname.hello", "api": 1, "name": "Hello Skater",
|
||||
"version": "1.0.0", "author": "Your name", "description": "Example HUD mod.",
|
||||
"entry": "main.lua",
|
||||
"settings": {
|
||||
"message": { "type": "string", "label": "Message",
|
||||
"description": "Text shown on screen.", "default": "Hello skater" }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
main.lua:
|
||||
|
||||
```lua
|
||||
local function draw()
|
||||
sdk.ui.text('hello', sdk.settings.message)
|
||||
end
|
||||
return {
|
||||
on_load = draw,
|
||||
on_settings = draw,
|
||||
on_event = function(event)
|
||||
if event.name == 'world_changed' then draw() end
|
||||
end,
|
||||
}
|
||||
```
|
||||
|
||||
The host removes owner visuals on disable/reload. Number settings require finite min,
|
||||
max, positive step and an in-range default. Choice settings require choices. Unknown
|
||||
manifest fields are rejected; there is no permissions or dependency declaration.
|
||||
Read the full setting and callback reference before extending this example.
|
||||
|
||||
## Package and check
|
||||
|
||||
From the repository:
|
||||
|
||||
```powershell
|
||||
python tools/package_mod.py sdk/examples/your-mod mods/your-mod.zip
|
||||
cargo run --locked -p skate-mods --example check_mod -- mods/your-mod.zip
|
||||
```
|
||||
|
||||
Requires Python 3.9+ and Rust/Cargo. The packer uses Python's standard ZIP library and
|
||||
runs the authoritative Rust checker on both the source and ZIP before replacing the
|
||||
output. It writes a temporary non-ZIP file first so discovery cannot see a half-written
|
||||
archive. Optional `--target-dir .local/vehicle-tests` selects the Cargo cache.
|
||||
The checker does not execute Lua callbacks. Passing it is not a gameplay test.
|
||||
|
||||
`Build-VehicleSDK.ps1` builds the host, packages both example sources and stages a
|
||||
standalone copy with docs. Older mod folders in its private staging directory are
|
||||
preserved under hidden .legacy-* names to avoid duplicate IDs. It does not delete
|
||||
personal mod edits. Example-specific model/rider files must exist locally to package
|
||||
an asset-complete Mario Kart; source checkout alone does not contain those assets.
|
||||
|
||||
## Limits and extraction rules
|
||||
|
||||
- At most 128 immediate packages; 512 ZIP entries and 512 extracted files/directories.
|
||||
- At most 64 MiB compressed and 64 MiB expanded per ZIP/package.
|
||||
- ZIP Store or Deflate compression. No encryption, links or special file entries.
|
||||
- Relative forward-slash paths only, at most 240 bytes for ZIP paths. No traversal,
|
||||
absolute/drive paths, Windows device names, forbidden characters or trailing dots/spaces.
|
||||
- Duplicate paths, including case collisions, are rejected. No overwrite extraction.
|
||||
- mod.json ≤64 KiB; Lua entry ≤256 KiB of UTF-8 source, no bytecode.
|
||||
- Vehicle definition ≤128 KiB; model ≤32 MiB; vehicle clips ≤16 MiB.
|
||||
- Text reads ≤256 KiB; authored vanilla body replacements ≤4 MiB. Other Lua quotas
|
||||
and native validation rules are described in lua-modding.md and vehicle-sdk.md.
|
||||
|
||||
The loader checks/decompresses within bounds, then writes to a new session directory
|
||||
under mods/.cache. Assets use this private directory transparently. Never edit or package
|
||||
.cache. Changed ZIPs get new cache paths, so assets cannot silently reuse the old model.
|
||||
Session caches are removed on normal shutdown; a crash may leave cache directories,
|
||||
which may be deleted with the game closed. Do not delete live session caches.
|
||||
A rejected ZIP shows diagnostics in the Mods UI/log and does not continue running an
|
||||
outdated copy indefinitely. Cache contents do not become independent installed mods.
|
||||
|
||||
## Further examples
|
||||
|
||||
- [Native Trainer](../sdk/examples/native-trainer/README.md): tuning, HUD, markers, timers.
|
||||
- [Vehicle SDK](vehicle-sdk.md): physics, controller input, ramp tuning and engine audio.
|
||||
- [Mixamo workflow](mixamo-vehicle-workflow.md): calibrated native-rig animation authoring.
|
||||
Reference in new issue
Block a user