-
Notifications
You must be signed in to change notification settings - Fork 0
Package Author Guide
This guide is the short public authoring contract for FUSE packages. The full schema is documented in ../schemas/FUSE_JSON_SCHEMA.md and schemas/fuse-mod.schema.json.
Use one or more *.fuse.json files inside a FUSE package folder. Each file should keep one clear concern where practical: graph, scenery, industries, progressions, audio, map tiles, or asset metadata.
Every file should include:
schemaVersionidnamemodVersion
author may be blank if the source package does not provide one.
- Package ids should be stable across releases.
- Object ids should be stable and human-readable.
- Do not reuse the same object id for different objects in one package.
- Do not rename an id just to change display text.
- Keep display names in
name; keep identity inid.
Use top-level settings plus featureRules when one package should offer
optional track, scenery, industries, loaders, or other authored sections. The
Tile Editor's Options workspace creates on/off, choice, and slider settings,
lets you select the exact objects controlled by each option, and writes both
dictionaries together.
Feature settings must be marked reloadRequired; the Editor does this
automatically. A false rule omits only the targets listed by that rule from the
runtime definition. It does not delete those objects from the package file.
Every target must be authored in the same definition, and an industry-component
target uses industryId/componentId. See the schema guide for the full target
list and JSON example.
RailLoader output has no equivalent contract. The Editor therefore disables this workspace in legacy mode instead of creating a lossy or misleading export.
Use package metadata for required package ordering and dependencies:
FuseLoadPriority-
FuseRequiresfor hard FUSE data-package dependencies FuseLoadAfterFuseLoadBefore-
FuseConflictsWithfor explicit package incompatibilities, with optionalNotBefore/NotAfterbounds - normal UMM
Requirements/LoadAfterwhen a UMM code mod requires FUSE or another UMM mod
Use mixinto when converting legacy conditional mixin files. Missing mixinto
requirements or matching mixinto.conflictsWith references skip only that
fragment, not the whole stack.
References that may not exist on every route should be treated as optional by schema/runtime design. Missing optional references should log an info-level skip, not fault an unrelated package.
Hard references should identify:
- package id
- source object id
- source field
- target kind
- target id
Track graph data is based on node, segment, and span ids. Spans must point at valid segment ids and valid segment ends. FUSE can reference base-game graph objects at runtime, but converted packages should not invent ids that cannot exist in the runtime graph.
Use /fuse.dumpgraph and /fuse.dumpruntimegraph to inspect graph state.
Supported industry component types include:
loaderunloaderformulaicrepairTrackteamTrackinterchangeinterchangedLoaderinterchangedUnloaderteleportLoadingprogressionpassengerStop- fully-qualified custom
IndustryComponenttypes from loaded assemblies
Custom components can use fields for reflection-bound values. The custom component assembly must be installed separately.
Use world.scenery for asset-pack objects. Use world.sceneClones for base-game scene objects. Use world.mapMasks for terrain flattening, tree cutting, height masks, and mask modifiers. Use world.splineys for roads, rivers, trestles, and related spline builders.
Packages with a map declaration are treated as complete replacement worlds:
map.suppressBaseWorld defaults to true. FUSE keeps Railroader's required
scene managers but removes the stock track graph and suppresses the stock
operations, scenery, map labels, signs, setups, progression, and CTC content
before applying the selected package. Set suppressBaseWorld to false only
for a map that intentionally overlays custom terrain on Bushnell/Whittier.
Asset pack objects should keep their real asset identifiers. Do not alias to unrelated assets if the correct pack exists.
Declare normal asset-pack roots with FuseAssetPacks. A runtime store is
identified by Catalog.json; Bundle is optional for a definitions-only
catalog whose assets are supplied by another store. FUSE reports an actual
missing bundle if an asset from that store is requested.
For the old AssetLoader pattern where a Definitions.json file replaces the
definitions of an existing store (rolling-stock and tender swaps), prefer an
explicit native manifest entry:
{
"Requirements": ["FUSE"],
"FuseDefinitionOverrides": [
{
"StoreIdentifier": "fm-flatcar03",
"Path": "DefinitionOverrides/fm-flatcar03/Definitions.json"
}
]
}The path must stay inside the package. An object entry names the exact existing store id; a string path infers the id from its parent folder. FUSE also detects AssetLoader's legacy immediate-child convention automatically, but native packages should be explicit. If two packages target the same exact store, FUSE chooses deterministically and reports both source files.
New packages should require FUSE, not AssetLoader. The installer's data-only
AssetLoader alias exists only for old manifests.
Use these commands while authoring:
/fuse.report/fuse.loaded/fuse.conflicts/fuse.graph/fuse.operations/fuse.progressions/fuse.assets/fuse.dumpgraph/fuse.dumpruntimegraph/fuse.dumpmandelas
Warnings should name package id, operation, object id, and field whenever possible.
Malformed JSON and validation faults are isolated to the affected definition.
/fuse.report and /fuse.report json include the absolute folder/file, JSON
path, line/column when available, and a suggested action. Treat a report with a
faulted package as an authoring failure even if unrelated packages still work.
For task-based examples, see Authoring Recipes.
Mirrored from docs/PACKAGE_AUTHOR_GUIDE.md — edit there, not here.