name: fusion-router description: Make, fix or extend a Fusion router (routers/<id>/router.toml, router.lua, or a game plugin on Fusion's guest SDK) for any game, or bring a passthrough mod (a SkyCraft port, "Minecraft in <game>") into Fusion. Use for "add <game> to Fusion", "port my mod to Fusion", "fix <game>'s router after an update", "add a block to <game>'s router".
Fusion routers
A router puts one game into Fusion as blocks (its World, its NPCs, a character) that players combine with other games' blocks. Fusion runs every game hidden, draws them together from its own camera, and passes collision, entities and input between them. A router is a folder routers/<id>/:
router.toml: the blocks, how the game starts, how it's set up. Most of a router is this file.router.lua(kits only): what data can't say, e.g. a menu to click through.MODLOG.md(what changed, why) andnotes.md(gotchas for the next person).
Pick the path (run fusion-cli router recon <game folder> first)¶
| The game | Path | Read |
|---|---|---|
| Unreal 4/5 | Unreal kit: data + a little Lua | unreal.md |
Unity IL2CPP (GameAssembly.dll) | Unity kit: data + a little Lua | unity.md |
| Unity Mono, Bethesda, Source, anything with your own plugin/DLL, open source | your plugin or program speaks Fusion through the guest SDK (C# FusionGuest.cs, C/C++ fusion_guest.h, Rust) | sdk.md |
| Minecraft | already in Fusion (minecraft.player, minecraft.mobs) |
Porting a passthrough mod (SkyCraft port, a ReShade or WebSocket bridge): the game becomes a World guest that draws from Fusion's camera; Minecraft is Fusion's minecraft.player. Keep the mod's knowledge of the game; delete its link, its Minecraft fork, its compositing, its frame sync and its installer. Part-by-part table: sdk.md, "Porting".
The loop¶
- Look first.
fusion-cli router recon <game folder>: engine, path, anti-cheat, the build's hash, and whether a router exists. If one exists, improve it, never make a second:fusion-cli router get <id> --out work/<id>, thenfusion-cli router propose work/<id> --message "...". After a game update:fusion-cli game diff <old dump> <new dump> --router routers/<id>. - Start.
fusion-cli router new <id> --name "<Name>" --kit unreal|unity|sdk (--steam-app N | --exe <path>). - Ask the game, don't grep dumps. Game running (kit installed), Fusion closed:
fusion-cli game find <text> --game-id <id>,... classes [text],... objects <Class>,... inspect <object>; Unity also... lua "<code>". A test or simulated game:<Game>.exe --help. - Write the data, then Lua or plugin code only for what data can't do.
- Check.
fusion-cli router check routers/<id>: a few lines, each failure with its fix; exit code 0 = pass.--live: the running game's kit tries the router. - Measure.
fusion-cli router conform routers/<id> --start: starts the game, checks every port it gives (picture frames and lag behind Fusion's camera, collision, entities), requests it can't do, and sleep/wake. Publishing needs a pass. - Play it with a scenario (below):
fusion-cli check-scenario scenarios/<file>.toml. - Write it down. A line in
MODLOG.md; gotchas innotes.md(what you saw → cause → fix), with the game build that worked.
fusion-cli where prints where Fusion's docs, kits, SDK files and routers are.
router.toml essentials¶
Every field: Fusion's docs/block-manifest.md. What's easy to get wrong:
- Ids are lowercase (
a-z0-9_-); block ids start with the router id:mygame.world. units: Unreal{ length = "cm", up_axis = "z", handedness = "left" }; Unity{ length = "m", up_axis = "y", handedness = "left" }; SDK programs send Fusion's space already:{ length = "m", up_axis = "y" }.- Launch:
steam_app = N, orexe+args. Paths start with a placeholder:{game}(the game's folder),{fusion},{tools}(Fusion's programs),{router},%ENV%. No relative paths, no... A game outside Steam needs[router.detect] paths = [...]. - SDK programs find Fusion by their discovery id: the router id, or
[router.link] game_id. - Blocks:
kind(world,character,npc_group,items,system),gives(layer:color+depth,collision,entities,pose),needs(collision,input),actions,cost. One World per scenario; a block that isn't a World plays in Fusion's playground. Kits do a block's work only if the block gives that port. [router.setup]: requirement checks and copy steps players run with one click (examples inunreal.md,sdk.md).[router.anticheat]: only for a game's own official anti-cheat-off mode.
A scenario (what players press Play on)¶
[scenario]
name = "Minecraft in My Game"
description = "Play as the Minecraft player in My Game's world."
[[block]]
use = "mygame.world"
[[block]]
use = "minecraft.player"
Rules¶
- Data before Lua before code. Something every game on an engine needs belongs in the kit, not a router: say so in
notes.md. - Try against a test or simulated game first, the real game last (it takes minutes to start).
- After 3 identical failures, stop: write what you know in
MODLOG.mdand change approach. - Never focus a game window or send it input while a person is using the PC. Stop processes by id, never by name.
- Single-player and offline only. Never touch anti-cheat, online modes or copy protection.
- Never put game files, extracted assets, decompiled code or memory addresses in a router: the publish check refuses them. Reading the player's own install at runtime for names and lists is fine (
[[block.content]]). - No Nintendo or Take-Two games.
Reference (read only what you need)¶
unreal.md,unity.md,sdk.md: one per path, with the data, the Lua or SDK calls, an example.example-unreal.router.toml+example-unreal.router.lua: a complete Unreal router.example-unity.router.toml: a Unity router.example-sdk.router.toml: a router for a plugin on the guest SDK, with its one-click setup. (The examples are made-up games: they passrouter check, but there's no game to run them.)- Fusion's
docs/(fusion-cli where):making-routers.md(overview),porting.md,router-api.md,block-manifest.md,guest-sdk.md,protocol.md.