From Live Editor Edits to a Shareable Pack
You tweaked values in /kdf editor to see what feels right. Now turn that into a real YAML pack that survives a restart and that you can hand to other people.
You opened /kdf editor, found a recipe or item, dragged a slider, and typed a new number. It felt
right immediately. That said, nothing you just did is saved anywhere yet. This tutorial covers the
one step between “it works right now” and “it still works next time I launch the game” (or “my
friend can install it too”): exporting.
Apply KDataForge operations directly
Section titled “Apply KDataForge operations directly”Every editable property row has an OP menu. It contains only operations accepted by that
property’s runtime type, using the same validation as a YAML properties: entry. Numeric fields
offer arithmetic and clamp; arrays offer insertion, removal, ordering, replacement, duplication,
and deduplication; strings and containers expose their applicable append/prepend/remove/clear
operations. copy and move are available for every property.
Choosing an operation opens an argument form containing only fields that operation needs:
valueaccepts a normal KDataForge YAML scalar, sequence, or map;clampasks forminandmax;- indexed array operations ask for
indexand, forswap,with; copyandmoveask for afromproperty path on the same object;clear,sort,unique, andreverseneed no arguments.
Apply changes the live object immediately. Invalid YAML, an unsupported value, or an out-of-range
index leaves the property unchanged and reports the op-engine error. Undo and Redo also
remove and restore the corresponding export entry; move restores both source and destination.
Use the inspector search to filter fields by property name, full path, or reflected type. The
Ops side tab shows the ordered operation sequence currently queued for the selected object.
Export Diff vs. Export Full
Section titled “Export Diff vs. Export Full”Both buttons sit in the editor’s inspector panel, and both call the same underlying export,
ExportObjectToYaml. They differ in a single flag, bDiffOnly, and that flag changes what ends up
in the file.
Export Diff prefers the ordered operations authored in the editor for the selected object. An
add, multiply, append, remove_at, copy, or other operation therefore remains that
operation in YAML instead of being flattened into a final set. Direct value editing is recorded
as set. If no editor-authored operation exists, Diff falls back to properties with a vanilla
snapshot recorded during this session. Either way, untouched properties stay absent and continue
tracking vanilla or whatever other patches apply to them.
Export Full includes every reflected property on the class that is not deprecated, transient, or
editor-only. This is broader than the normal Unreal “editable” surface: fields without
EditDefaultsOnly/EditAnywhere can still be exported if they are reflected FProperty members.
The file is large: the reflected surface of the class, frozen at its current value. The risk is that
any vanilla default you never meant to touch gets written into your pack at today’s value. If the
base game changes that default later, your pack silently overrides the update.
Use Export Diff almost always. The “diff” here really means “session-changed,” not
“changed-vs-file-on-disk”. A property counts as changed the moment any op, whether a live edit or
an earlier-loaded YAML patch, first touches it in the current session. That’s because this is when
FKDFVanillaCache::RecordSnapshot fires, since the first write wins. Properties you only looked at
in the inspector never get a snapshot and never show up in a Diff export.
Both buttons write to the same place:
<ProjectDir>/DataForge/exported/<ObjectName>.cdo.ymlThis is a source-hardcoded editor staging path. The editor creates DataForge/exported/
automatically when needed. <ProjectDir> is Unreal’s project directory, which is the
FactoryGame/ project directory in a packaged game.
<ObjectName> is Selected->GetName(). For the common case of editing a recipe, item, or
schematic class (its CDO), that name is the engine’s synthetic default-object name. A patch to
Recipe_IngotIron_C’s CDO therefore exports as Default__Recipe_IngotIron_C.cdo.yml, not
Recipe_IngotIron.cdo.yml. You don’t need to rename it: KDataForge doesn’t care what the file is
called, only what’s inside it.
Moving the export into a real pack
Section titled “Moving the export into a real pack”<ProjectDir>/DataForge/exported/ sits under a scanner-recognized DataForge root, so a freshly
exported file can be discovered on the next session start.
That’s not a reason to leave it there, though. exported/ is a scratch folder the editor writes
into every time you click the button, so exports from unrelated sessions and experiments pile up
there with no grouping and no ref:. Handing a file to someone else means handing them something
self-contained: its own folder, its own pack.yml with a stable ref: (the save-persistence
contract), not your personal working directory.
Before shipping, create a proper author pack and move the file into it:
<your-mod>/DataForge/ pack.yml Default__Recipe_IngotIron_C.cdo.yml <-- moved from <ProjectDir>/DataForge/exported/ref: MyTweaksname: My Tweaksversion: 1.0.0The exported file is already valid type: cdo YAML. For the common case of one specific class and
one specific patch, you don’t need to touch it at all. You’d hand-edit it when you want to
broaden what it applies to:
- Swap
target: /Game/.../Recipe_IngotIron.Recipe_IngotIron_CforallAssetsOfClass: /Game/.../Recipe_IngotIron.Recipe_IngotIron_Cif you want the patch to also reach subclasses or every asset resolving to that class, not just the one CDO you had selected. - Add
applyToSubclasses: truealongsidetarget:for the same broadening effect without switching selector kind. - Add
applyToSpawnedActors: trueif this is a buildable and you also want already-placed instances (not just newly spawned ones) to pick up the change. See Targeting for the full selector/modifier reference, and Patching (type: cdo) for the patch shape.
Managing packs inside the in-game editor
Section titled “Managing packs inside the in-game editor”Switch the editor from Runtime to Packs to work on files instead of live objects. The left
pane groups every discovered YAML file below its owning pack.yml. Nested packs are separate: the
deepest pack.yml owns a file. Files with invalid YAML remain selectable and open directly in Raw
mode so you can repair them.
The New pack action creates exactly:
<ProjectDir>/Mods/DataForge/<pack-name>/pack.ymlPack names and document names accept letters, digits, _, and -. Existing files are never
overwritten. Select a pack, choose a document type, enter a file name, and click Create. The
type list covers every KDataForge root handler: cdo, gametag, asset, localization, class,
item, resource, building, unlock, recipe, schematic, research, dataasset, curve,
sinkpoints, resourcenode, and sublevel.
Each file has two editing surfaces:
- Form exposes every YAML map, sequence, scalar, and null node. Select a node to replace its
complete YAML fragment, add a map member or sequence item, or remove it. Scalar values can also
be edited inline. The guided controls provide context-sensitive field and sequence-entry
templates for every KDataForge document type. Class-valued rows use a searchable class picker
filtered to the expected base class; it includes loaded native classes and Blueprint classes
known to the asset registry. Once a target, class, or parent is selected, property-path rows can
be chosen from inherited reflected fields, including nested struct and array paths. Operation
choices are filtered against the resolved property type, while enum and boolean values offer
valid presets. Selecting a
propertiesorwheresequence also offers ready-made entries for fields on the resolved class. - Raw YAML edits the exact file text, including comments and formatting. Switching back to Form first validates and parses the text. Invalid YAML stays in Raw mode with an error message.
Raw edits keep their exact text until a Form mutation occurs. A Form mutation serializes the parsed document again, so comments, quoting choices, and custom whitespace can be normalized or removed. Use Raw mode when those details matter.
Save validates YAML syntax and required document shape, writes a temporary file, then replaces
the destination atomically. A failed validation or write leaves the previous file intact. Unsaved
changes block file/pack switching and closing until you save or explicitly discard them. Save does
not apply semantic changes by itself: use /kdf reload for live-safe updates, or restart for
content registrations and other startup-only stages.
The Create panel: drafting new content instead of hand-writing YAML
Section titled “The Create panel: drafting new content instead of hand-writing YAML”The editor’s CREATE section, below the YAML preview, drafts brand-new content: item, resource,
building, recipe, schematic, research, unlock, dataasset, or a generic class, without you typing
a document by hand. Pick a kind, type an Id, pick a parent class (or class: for dataasset),
optionally pick a registerAs: target for generic class drafts, and click Create.
This writes a starting-point document to:
<ProjectDir>/DataForge/created/<Id>.<Kind>.ymlCreate the DataForge/created/ directory before using the action. This is also a staging directory,
not the canonical shipping location.
For example, MySuperIngot.item.yml. It’s a skeleton: type:, the plural entries key
(items:/recipes:/schematics:/research:/unlocks:/assets:/classes:), and one entry with
id: and parent: (or class:). There’s no properties: yet. You still add those by hand, same
as in Item + Icon + Recipe + Tier-1 Unlock,
just starting from a correctly-shaped file instead of a blank one.
Create writes a draft file; it does not apply the draft to the running session. Every kind,
including dataasset, is loaded from YAML on the next session start. The status message shows the
written path and reminds you to restart. created/ is a scratch area, so move the finished draft
into a real pack before relying on it long-term.
Worked scenario: retuning a recipe’s craft time
Section titled “Worked scenario: retuning a recipe’s craft time”-
Open chat, type
/kdf editor. -
Switch to the Recipes category, search for the recipe you want (e.g. the Super Ingot recipe from the item/recipe/schematic tutorial), and select it. Browser rows show content icons when available: item/building icons, schematic and research-tree icons, recipe product icons, and direct icon properties such as
mSmallIconormIcon. -
In the inspector tree, find
mManufactoringDurationand commit a new value, say2.0instead of4.0. The change applies immediately. Go build one and confirm it’s actually faster. -
Click Export Diff. Because
mManufactoringDurationis the only property you touched on this object this session, the exported file is short:type: cdopatches:- target: /KDataForge/Gen/KDFSample.Gen_KDFSample_Recipe_SuperIngotproperties:- path: mManufactoringDurationvalue: 2.0 -
Check the status bar. It read
Exported to <ProjectDir>/DataForge/exported/Default__Gen_KDFSample_Recipe_SuperIngot.cdo.yml(or similar, matching the generated class’s CDO name). -
Create
<your-mod>/DataForge/pack.yml(ref: MyTweaks) if you don’t already have a pack folder, and move the exported file in next to it. -
Restart the game. The recipe still takes 2 seconds: same value, now coming from a real pack file instead of a session-only edit, applied through the identical
type: cdopipeline as before.
If you’d clicked Export Full instead, the file would list every reflected, non-deprecated, non-transient, non-editor-only property of the recipe class: ingredients, product, produced-in, display name, and possibly internal reflected fields too. Each value is frozen at its current value, not just the duration. That’s usually more than you want to ship.
Troubleshooting
Section titled “Troubleshooting”- Exported file has an empty
properties:list or almost nothing under Diff mode. Diff only includes properties that were actually written this session on that specific object. Browsing or inspecting a value without committing an edit never creates a snapshot, so it never shows up. Double-check you selected the same object you edited, and that you actually committed a value, not just opened the row. - I edited something, then undid it, then exported, and the property still shows up. The vanilla snapshot is recorded on first write and never cleared by Undo. Diff mode checks “was this property ever touched this session”, not “does it currently differ from vanilla”. So a touched-then-reverted property can still appear in the export, just with its value back at vanilla. This is harmless, it’s a no-op patch, but worth knowing if the file looks odd.
- Export/Create button seems to do nothing. Check the status bar text at the bottom of the
editor window. Both actions always set it: green for success (with the exact file path), or
red for failure (
Nothing selected,Could not write <path>, etc.). It’s easy to miss because it’s small, not because the click didn’t register. - Can’t find the exported/created file. It is under the source-hardcoded
<ProjectDir>/DataForge/exported/or<ProjectDir>/DataForge/created/staging directory. The legacycreated/directory must already exist. The Packs workspace creates its ownMods/DataForge/<pack-name>/directory. Move legacy staging files into a real pack before shipping. - Form mode rejects the file. Switch to Raw YAML and repair the syntax. Form requires
pack.ymlto contain one map, and every normal YAML document root to be a map. Runtime-specific semantic errors are reported when KDataForge loads or reloads the file. - New item/recipe/schematic from Create still isn’t there. Create only writes a draft. Move it into a real pack and restart the session. The SML content registry freezes at world begin play.
- Export Full includes fields from
Non-UPROPERTY / Internal. The current UI label is misleading. Those rows are still reflectedFPropertymembers; they only lack Unreal’s normal edit flag or category metadata. Export Full may include them unless they are deprecated, transient, or editor-only.
Getting Started covers pack roots, /kdf report,
session restarts, and the same debug format used for editor-originated operations. The separate
UE Editor Integration workflow uses the
WITH_EDITOR-only KDF.ApplyToAssets command to change Unreal Editor assets; it is not the in-game
/kdf editor described here. Every export uses the
Patching (type: cdo) document shape. To fill a
Create-panel draft’s properties: from scratch, follow
Item + Icon + Recipe + Tier-1 Unlock.
