Getting Started
Build the smallest possible pack, confirm it loads, and learn the report, logging, and restart workflow.
Start here if you have never written a KDataForge pack before.
It walks through the smallest useful pack: one folder with two files. Along the way you’ll touch every piece of tooling you need on day one, including where files go, the /kdf chat commands, how to read the load report, debug logging, multiplayer, and the most common ways a fresh pack silently does nothing.
The Task Guides build on this shape to accomplish specific goals. Examples contains complete packs that combine several capabilities, while Features explains each capability.
Where files go
Section titled “Where files go”Author packs under your mod’s canonical root:
<your-mod>/DataForge/ pack.yml faster-smelting.cdo.ymlKDataForge starts its recursive scan at the Unreal project directory, which is FactoryGame/ in a
packaged game. Up to six levels below that project root, it recognizes any directory named
DataForge, the legacy name data-editor, or any directory that directly contains pack.yml.
Names are case-insensitive. Every *.yml or *.yaml file below a detected root is a document, or
several documents when separated with ---. See
Multiple Documents Per File.
Detected roots may nest. A YAML file belongs only to its deepest enclosing root, so a nested pack
is not also loaded by its parent. Heavy engine directories such as Content, Saved, Plugins,
and Source are pruned during root discovery.
pack.yml
Section titled “pack.yml”A pack.yml manifest is how a set of documents becomes a named, versioned unit instead of a pile of loose files.
It is optional. Without a manifest, the implicit pack ref and name come from the parent directory
of the detected root. That fallback can change when a folder moves, so declare an explicit stable
ref from day one. The ref is the save-persistence contract:
ref: MyFirstPackname: My First Packversion: 1.0.0The first patch: half smelting time
Section titled “The first patch: half smelting time”A type: cdo document patches properties directly on a class’s default object. Setting mManufactoringDuration to a fraction of its original value halves the crafting time. It’s a good first patch to try because the result is immediately visible in-game:
type: cdopatches: - target: /Game/FactoryGame/Recipes/Smelter/Recipe_IngotIron.Recipe_IngotIron_C properties: - path: mManufactoringDuration op: multiply value: 0.5Start the game and iron ingots now smelt twice as fast.
The type: key is optional here. The .cdo.yml filename suffix would set the root type via the filename convention (<name>.<type>.yml), but an explicit type: always wins.
/kdf report and loading changes
Section titled “/kdf report and loading changes”/kdf report: prints the load report, showing which packs and documents were found, what was applied, and every diagnostic (see below)./kdf reload: restores KDataForge-touched reflected properties to their original session baseline, rescans every pack file (including edited configuration values files: hot values apply, cold values report “restart required”), then runs the normal deterministic stage pipeline again.KDF.Reload: runs the same smart reload from a host or dedicated-server console./kdf sound PackRef Id: previews an imported Wwise sound on the local client. Console equivalent:KDF.Sound PackRef Id. See Wwise Sounds.
After editing a file, run /kdf reload, then use /kdf report to inspect the replacement load.
Only the listen host, a dedicated-server administrator, or the server console may reload.
Smart reload
Section titled “Smart reload”Reload does not blindly apply an add, append, or multiply operation on top of its previous
result. Before re-applying files, KDataForge restores every touched top-level reflected property to
the value captured before KDataForge first changed it this session. This also removes property
changes from files deleted since the previous load. Invalid documents are skipped under normal
diagnostic rules, so their old property effects are not retained.
Reload clears and rebuilds actor patches, lazy-class watches, content-removal rules, resource-node
rules, registration queues, diagnostics, and patch history. Any open /kdf editor window closes
because its undo history refers to the pre-reload state.
Restart boundaries
Section titled “Restart boundaries”Some engine state cannot be reversed safely after world startup:
- SML freezes recipe, schematic, research-tree, and sink-point registrations before BeginPlay. New, deleted, or re-registered entries need a session restart to change those live registries.
- Content already removed by a
remove:rule is not re-added when that rule disappears. Reload updates the rule set for later checks; restart the session to rebuild availability from startup. - Generated UObject identities, gameplay tags, and localization entries are process-lifetime state. Current files can update existing objects or strings, but deleting their definitions does not unload them. Restart to prove removal.
resourcenodereload rules apply immediately. Node destruction is server-authoritative and may create vanilla save tombstones; removing the rule cannot resurrect already destroyed nodes.- Reload is process-local. Multiplayer clients do not receive the host’s reload. Restart every process with the same pack set when changes must be multiplayer-consistent.
Prefer clicking over typing? /kdf editor opens the in-game editor. Runtime browses
reflected objects, applies supported property operations live, and exports YAML. Packs browses
files grouped by their owning pack.yml, creates packs below
<ProjectDir>/Mods/DataForge/<pack-name>/, and edits every YAML node through Form or Raw YAML mode.
Form mode includes schema-aware field/entry templates, filtered class selectors, reflected property
paths, supported-operation choices, and enum/boolean presets. Save validates and writes atomically;
/kdf reload applies live-safe file changes.
Reading the report
Section titled “Reading the report”Diagnostics are never fatal. A broken file is skipped and the load continues. Each one carries a severity that tells you how much attention it deserves:
| Severity | Meaning | Example |
|---|---|---|
| Info | Expected skips, not printed by /kdf report | A document’s conditions: failed (mod not installed, version mismatch) |
| Warning | Tolerated problems | Unknown root type, duplicate pack ref |
| Error | A file, document, or single patch was skipped | Malformed YAML, target class not found, unsupported op×type combination |
Debugging
Section titled “Debugging”Every applied op can be traced with debug logging, and you get to choose how wide the net is cast: per document, per pack, or globally across every pack loaded.
Per document: add debug: true at the top level of any document type. Every applied op from that file logs:
type: cdodebug: truepatches: - target: /Game/FactoryGame/Recipes/Smelter/Recipe_IngotIron.Recipe_IngotIron_C properties: - path: mManufactoringDuration op: multiply value: 0.5Per pack: add debug: true to pack.yml. Every document of the pack logs:
ref: MyFirstPackname: My First Packversion: 1.0.0debug: trueGlobal: set the console variable KDF.Debug 1 (open the console with ~) or launch the game with -KDFDebug. Everything logs then, including ops originating from the in-game editor.
Each applied op produces one line at Log verbosity:
[KDF DEBUG] faster-smelting.cdo.yml: /Game/FactoryGame/Recipes/Smelter/Recipe_IngotIron.Recipe_IngotIron_C.mManufactoringDuration multiply : 2.000000 -> 1.000000The format is <file>: <target path>.<property path> <op> : <pre value> -> <post value>. The pre/post pair is what makes it useful: you see exactly what a multiply or append actually did.
Where the log lives: in a packaged game the log file is
%LOCALAPPDATA%\FactoryGame\Saved\Logs\FactoryGame.log. Search it for [KDF DEBUG].
Multiplayer
Section titled “Multiplayer”KDataForge loads YAML independently in every game process. It does not negotiate pack checksums, reject mismatches, or stream applied operations from the server. Install the same pack set and versions on the dedicated server or host and on every client. The one thing the host does send to clients is the value of each pack configuration field, held in memory only.
The in-game editor’s live property changes are local to the process where they are made. Export those changes to YAML and distribute the resulting pack when they must be consistent for all players.
Troubleshooting
Section titled “Troubleshooting”Most “nothing happened” reports trace back to one of a small handful of causes. Check these before assuming something is broken:
| Symptom | Likely cause / fix |
|---|---|
| File is ignored entirely | Missing type: key and the filename doesn’t follow the <name>.<type>.yml convention. Add one of the two |
| One document of a multi-document file is ignored | Every document in a ----separated file needs its own type: key. The filename convention only works for single-document files, see Multiple Documents Per File |
| “class not found” | Check the path form: cooked Blueprint asset classes use _C (/Game/....Asset.Asset_C, auto-retried if omitted), native classes use /Script/Module.Class, and KDataForge-generated classes use /KDataForge/Gen/<PackRef>.Gen_<PackRef>_<Id> with no _C. The short id: also works when unambiguous; see Generated Content Short Ids |
| Op rejected at load time | Unsupported op×type combination. Check the op table in the YAML Schema and the per-op examples in Operations |
| Data-asset instance not found | Instances (not classes) have no _C suffix, see Targeting |
| Change applied but not visible on placed buildings | Saves/archetypes override CDO values. Use a runtime actor patch (applyToSpawnedActors), see Buildings |
Next steps
Section titled “Next steps”- Desktop Pack Manager: edit YAML and catch malformed documents or schema mistakes before launching the game
- Lint Your Pack: reproduce existing KPatchwork pull-request policy checks
- Targeting: every way to select what a patch applies to
- Balancing: recipes, items, schematics, research
- Items, Recipes, Schematics: new content from YAML, or the tied-together End-to-End Pack
- Item + Icon + Recipe + Tier-1 Unlock: this tutorial series’ natural next step, walking through exactly that trio
- Pack Configuration: let players change numbers, toggles and texts of your pack without editing YAML
