Package files and the content browser
BUILD.md step 4.6. Code: crates/fusion-core/src/content.rs (format, sources, resolution, install), crates/fusion-godot/src/content.rs (FusionContent), godot/scripts/content_browser.gd.
A package file¶
A package file is one file ending in .fusion. It's a plain zip, so anyone can open it and look inside. It holds package.toml and any mix of these:
| Path inside | What it is | Installed to (while developing) |
|---|---|---|
routers/<id>/... | a router folder (router.toml + its Lua files) | routers/<id>/ |
scenarios/<file>.toml | a scenario (or an Experience) | scenarios/ |
scenarios/<file>.png | that scenario's cover picture | scenarios/, next to it |
addons/<name>/... | a Lua addon (needs init.lua) | godot/addons_dev/<name>/ |
devices/<type>.lua | a Device template | godot/devices/ |
thumbnail.png | its picture in the browser | (not installed) |
signature.toml | who signed it (trust.md) | (not installed) |
Anything else is refused, and so are paths with .. or a drive letter. A package unpacks to at most 512 MB.
# package.toml
[package]
id = "zombie-arena" # lowercase, digits, - and _; the same id replaces the old copy
name = "Zombie Arena"
version = "1.0.0"
author = "Ali" # optional
description = "..." # optional
requires = ["vein"] # optional: routers it needs beyond what its scenarios use
Routers inside must load (router.toml checks, its id matches its folder), scenarios must parse.
What it needs¶
A package's needs come from what's inside it, never from a list of games:
- every router whose blocks its scenarios use;
- every Device type its scenarios place;
- every addon its scenarios list (
addons = [...]); - the routers in
requires.
Each need is met by what's installed, by the package itself, or by another package file a source offers. That one is installed first, after its own needs. A need nobody has blocks the install and says so in plain words.
The ownership check uses My Games: for every router the package needs (except Fusion's own), is its game on this PC? "You own 1 of the 2 games this needs (not Farm Game)". Routers in the package count too, so a friend learns which of the games they have before installing anything. Not owning a game doesn't block installing: the scenario just shows as unplayable until they get it.
Installing¶
For each piece:
- already installed (same files): nothing is written;
- installed before by this same package: replaced (reinstall or update);
- a different one with the same name: a scenario gets a free name (
arena-2.toml); a router, addon or Device template that's already there is kept (yours wins), and the browser says so.
Every file written is recorded with its sha256 in %LOCALAPPDATA%/Fusion/packages/installed.toml. If a write fails halfway, what was written is taken back.
Uninstall removes what the package installed, except:
- files changed since (for example a scenario edited in the builder): kept, and named;
- pieces another installed package needs: that package keeps them.
Sources¶
Content comes from sources behind one interface (content::Source: list, fetch):
- Files on this PC (
FileSource): every*.fusionin the Downloads folder, plus files the player opens or drops on Fusion's window. The first source, always available. - Content hubs (
hub::HubSource, step 6.3, ADR 0005): each hub in Settings is a static folder (index.tomlsigned by Fusion,packages/). Fusion checks the index's signature, downloads each package into%LOCALAPPDATA%/Fusion/cache/hubs/<hub>/, and checks its sha256, size and signer against the index. The newest version of each package is listed. Hub operators publish withfusion-cli hub add HUB PACKAGE --key OFFICIAL.key. A router goes on a hub only with a passing conformance report for its current files (conformance.toml, saved byfusion-cli router conform; any change to the router means running the tests again). Sharing a scenario as a file with friends doesn't need one. - The Steam Workshop (8.3) comes later, as one more source.
Versions¶
Every version installed is kept in %LOCALAPPDATA%/Fusion/packages/archive/<id>/. Roll back (in Content, under Installed) reinstalls the version before the current one and keeps the package at it (Keep this version / Allow updates): a kept package isn't offered newer versions. Versions compare as numbers (1.10 is newer than 1.9).
Sharing a scenario¶
Main menu → Share next to a scenario (or on an Experience's cover) saves it as one package file with every router it uses (except Fusion's own), the Device templates it places and the addons it lists, so it installs on a PC that has none of them. An Experience's cover picture goes with it and is also the package's picture; otherwise the package's picture is the one Fusion took the last time the scenario was played (5 s after every game showed; user://thumbnails/<scenario>.png). The browser calls a scenario with an [experience] table an "Experience". If it's installed under a free name (arena-2.toml), its cover follows (arena-2.png).
Not yet¶
- Signatures, tiers and the publish check are in
trust.md(step 6.1): packages carrysignature.toml, Share signs with the player's own key and refuses game files. - Double-clicking a
.fusionfile doesn't open Fusion (needs the installer, 6.4). - Kits (native files) can't travel in a package; a router's setup recipe still uses Fusion's own.
- No version ranges: a router that's installed meets a need whatever its version.