SteonMod
View as Markdown

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 insideWhat it isInstalled to (while developing)
routers/<id>/...a router folder (router.toml + its Lua files)routers/<id>/
scenarios/<file>.tomla scenario (or an Experience)scenarios/
scenarios/<file>.pngthat scenario's cover picturescenarios/, next to it
addons/<name>/...a Lua addon (needs init.lua)godot/addons_dev/<name>/
devices/<type>.luaa Device templategodot/devices/
thumbnail.pngits picture in the browser(not installed)
signature.tomlwho 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 *.fusion in 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.toml signed 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 with fusion-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 by fusion-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 carry signature.toml, Share signs with the player's own key and refuses game files.
  • Double-clicking a .fusion file 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.