Making routers: start here
For people who connect a game to Fusion, and for the AI agents they work with. Read this page first; it says which other page you need.
A router connects one game to Fusion. It splits the game into blocks (its world, its characters, its NPCs) that players snap together with blocks of other games, with no code: cards, press Play. One router per game; every fusion with that game reuses it.
Why make a router instead of a two-game mod¶
Today a fusion is a hand-built mod for one pair of games: copy SkyCraft, rename the host, write the link, the collision, the camera sync, the frame pacing, an installer, and publish a repo. The player then installs a mod loader, a launcher, Java, a modpack, and starts both games in order.
| A two-game mod | A Fusion router | |
|---|---|---|
| What you write | both halves: link, collision field, camera sync, compositing, input, pause, installer | only what's particular to your game: which object is the player, which are NPCs, how to get past the menu. Mostly data in router.toml |
| Size | SkyCraft is about 890 KB of code | VEIN's router is 25 lines of data and 36 lines of Lua; "Minecraft in VEIN" is a 15-line scenario |
| Which games it fuses with | one other game | every game that has a router, in any number, picked block by block |
| Minecraft's side | yours to fork and maintain | done: Fusion's Fabric kit is SkyCraft's mod, kept up to date |
| Players install | a loader, a launcher, Java, files in the right folders, both games started in order | Fusion, then Play: one-click setup installs the loaders and your router |
| Game updates | it breaks, and someone rediscovers the game | tested_builds disables it cleanly; fusion-cli game diff lists what the update renamed |
| Testing | look at the screen | router check and router conform measure it in numbers (picture lag in frames, collision, NPCs, sleep and wake) |
| The next person | starts again from the source | starts from your router (router get), its notes.md and MODLOG.md, and sends you improvements |
Your path¶
Run fusion-cli router recon <the game's folder> first. It reads only file names and says the engine, which path fits, whether there's anti-cheat, and whether the game already has a router.
| What you have | What you make | Read |
|---|---|---|
| An Unreal 4 or 5 game | data (and maybe a little Lua) on Fusion's Unreal kit | agent/unreal.md, router-api.md |
A Unity IL2CPP game (GameAssembly.dll in its folder) | data (and maybe Lua) on Fusion's Unity kit | agent/unity.md, router-api.md |
| Your own mod already in the game: a BepInEx or MelonLoader plugin (Unity Mono), an SKSE/F4SE/NVSE plugin, a Source server plugin, an injected DLL | keep your mod; replace its link with Fusion's guest SDK (C# FusionGuest.cs, C/C++ fusion_guest.h) | agent/sdk.md, porting.md, guest-sdk.md |
| An open-source game, a rewrite or a recomp | link the guest SDK into its source (Rust, Bevy, C, C#) | guest-sdk.md |
| Minecraft | nothing: its router is in Fusion; players pick their own modpack on its card | |
| A game with anti-cheat | only if its own launcher has an official anti-cheat-off mode ([router.anticheat]); otherwise it can't come in | block-manifest.md |
Already made a passthrough mod (a SkyCraft port, a ReShade bridge)? porting.md maps each part of it to Fusion: most of it is no longer yours to maintain.
Set up¶
- Install Fusion. Its developer tool is
fusion-cli.exein Fusion'sbinfolder (%LOCALAPPDATA%\Programs\Fusion\versions\<version>\bin; add it to your PATH).fusion-cli whereprints every folder you need (docs, the agent pack, the SDK files, routers). - Make a folder for your work, and in it run
fusion-cli agent install. Your AI agent then knows Fusion's commands and rules (a Claude Code skill, and a section ofAGENTS.mdfor Codex, Cursor, Copilot and Gemini CLI). Your own text inAGENTS.mdstays. - Your routers live in
routers/<id>/in that folder. Fusion's commands read them first, then the routers installed in Fusion.
The loop¶
- Look first.
fusion-cli router recon <game folder>. If the game has a router, improve it instead of making a second one:fusion-cli router get <id> --out work/<id>, change it,router checkit, thenfusion-cli router propose work/<id> --message "what and why"and send the file to its author. - Start.
fusion-cli router new <id> --name "<Name>" --kit unreal|unity|sdk (--steam-app N | --exe <path>)writesrouters/<id>/:router.toml(the blocks),router.lua(kits),MODLOG.md(what changed and why),notes.md(gotchas for the next person). - Ask the game, don't guess. With the game running and Fusion closed:
fusion-cli game find <text> --game-id <id>,game classes,game objects <Class>,game inspect <object>. Or open Fusion, play the router's blocks and press F4 (Router Studio): click "This is the player", "These are NPCs", and save. - Write the data, then Lua only where data can't say it (a menu to click through).
- Check.
fusion-cli router check routers/<id>: a few lines, each failure with its fix; exit code 0 = pass.--livehas the running game try the router. - Measure.
fusion-cli router conform routers/<id> --start: Fusion's side, in numbers. It starts the game, checks every port the router promises, the picture's lag behind Fusion's camera, requests it can't do, and sleep and wake. Publishing needs a pass. - Play it. Make a scenario (below) and play it in Fusion. F7 shows collision, F8 entities, F6 cost, F4 Router Studio.
- Write it down. A line in
MODLOG.md; anything surprising innotes.md(what you saw → why → the fix), with the game build that worked.
Stop after three identical failures: write what you know in MODLOG.md and change approach.
Blocks, and what your router must do for each¶
Players combine blocks; ports say what flows between them. Fusion wires matching ports by itself.
Block kind | What it is | It gives / needs | What your router does |
|---|---|---|---|
world | the place everyone stands in | gives layer:color+depth, collision | the game draws its world from Fusion's camera, and sends its ground and walls |
character | someone the player plays | needs input (and collision if it walks on another World), gives pose | moves its character from Fusion's controls; says where its feet and eyes are |
npc_group | enemies, animals, vehicles | gives entities, lists actions | lists them a few times a second (id, kind, position, health); does remove, set_health, move_to... |
items, system | things to hold; weather, money | gives state, events | (v0: few routers have these yet) |
One scenario has one World and at most one played Character; any number of the rest. A block that isn't a World plays in Fusion's own playground, so you can test an NPC group without a world.
Everything crosses in Fusion's space: meters, Y up, right-handed, -Z forward. Kits convert from the units your router declares; with the SDK you convert at your game's edge (agent/sdk.md).
A scenario¶
A scenario is the fusion players press Play on. It names blocks; Fusion does the wiring:
[scenario]
name = "Minecraft in VEIN's World"
description = "Play as the Minecraft player in VEIN Demo's world."
[[block]]
use = "vein.world"
[[block]]
use = "minecraft.player"
Put it in a scenarios/ folder and check it with fusion-cli check-scenario scenarios/<file>.toml. Players make the same thing with cards in Fusion's main menu (Scenario Builder).
Test without the game¶
router checkneeds no game at all;router conformneeds it running.- Fusion's test game (
fake-guest) and the SDK's example worlds behave like games: try a draft on them first. - Record what your game sends once (start Fusion with
-- --record=<folder>), thenfusion-cli replay <folder>/<router>.fusionrecplays it back with no game running, for testing addons, Devices and Experiences in seconds.
Publish¶
fusion-cli router conform routers/<id> --startmust pass (it writesconformance.toml).fusion-cli package router routers/<id> --out <id>.fusionchecks and signs it. The publish check refuses game files, extracted game data, decompiled code and memory addresses.- Share the
.fusionfile (players double-click it, or drop it on Fusion), or send it to a content hub.
Trust: a router of data and Lua can come from anyone. A router that carries program files (the DLL of an SDK plugin) is shared only from verified authors. Credit what you build on: contributors, based_on, and keep the licenses of code you reuse (SkyCraft is MIT).
Rules¶
- Single-player and offline only. Never touch anti-cheat, online modes or copy protection; the one exception is a game's own official anti-cheat-off mode.
- Never ship game files, extracted assets, decompiled code or encryption keys. Reading the player's own installed files at runtime for lists and names is fine (
[[block.content]]). - Never focus a game window or send it input while someone is using the PC. Stop processes by id, never by name.
- No Nintendo or Take-Two games (Fusion's blocklist).
Where to read more¶
| Page | |
|---|---|
porting.md | from your passthrough mod to a router, part by part |
router-api.md | the kits' data ([block.bind]) and Lua (Router.block, Game.*) |
block-manifest.md | every router.toml field, ports, placeholders, setup recipes |
guest-sdk.md | the guest SDK: Rust, Bevy, C/C++, C# |
protocol.md | the protocol under the SDK and kits, and the questions tools ask a game |
packages.md, trust.md | packages, signing, trust tiers |
lua-api.md, devices.md | addons, Devices and Experiences built on your blocks |
agent/ | the agent pack: SKILL.md and one page per path (fusion-cli where shows it) |