Patching (type: cdo)
The property-patch document type. Covers how patches, target selectors, and modifiers fit together, plus where the deep-dive pages live.
This document type runs at the CDOChanges stage, after GameTags, Assets, and Localization,
and before any content-generation stage. Its entries live under the patches key as a sequence.
YAML changes are loaded on the next session start.
This is the workhorse document type. It edits any reflected property on any class default object or object instance in the game: items, recipes, buildings, schematics, research trees, KAPI/RRDA data assets, your own generated content, anything. Everything else this framework does (content creation, data assets, sink points) either patches through this same mechanism internally or exists alongside it.
Shape of a patch entry
Section titled “Shape of a patch entry”A type: cdo document is just a patches: list. Each entry needs at least one target selector
(target:, allAssetsOfClass:, or an ofClass: scope with filters such as matchTag:, matchName:, producedIn:, where:), optional modifiers, and a
properties: list describing the actual edits. The example below halves mManufactoringDuration
on the iron ingot recipe:
type: cdopatches: - # ---- one or more selectors are accepted; prefer one clear selector ---- target: /Game/FactoryGame/Recipes/Smelter/Recipe_IngotIron.Recipe_IngotIron_C # target: also accepts a sequence of paths, patching every entry with the same properties: # OR: allAssetsOfClass: ... # OR: ofClass: ... + filters (matchTag / matchName / producedIn / ingredient / product / where)
# ---- modifiers (all optional) ---- applyToSubclasses: false applyToSpawnedActors: false
# ---- the ops ---- properties: - path: mManufactoringDuration op: multiply value: 0.5Each entry needs at least one selector and a non-empty properties: list. The current implementation
accumulates matches when selectors are combined, but one selector per entry is easier to audit. One
document can hold any number of patch entries.
Hard asset references in native defaults
Section titled “Hard asset references in native defaults”Use full asset object paths for hard-reference properties such as
TArray<TObjectPtr<UStaticMesh>>. A YAML sequence replaces the array; string
allowlists remain ordinary strings. For example, with Periodic Madness installed:
type: cdopatches: - target: /Script/PeriodicMadness.PMCleanerSettings properties: - path: mStaticMeshesCleanlist value: - /Game/FactoryGame/Resource/RawResources/Nodes/ResourceNode_OreIron_01.ResourceNode_OreIron_01KDataForge keeps hard references added to permanent native defaults alive across garbage collection and session changes. These assets remain resident until the game exits, even if a later edit removes them from the array. No YAML opt-in or class declaration change is needed. After upgrading from a build where inspecting these arrays crashed, fully restart the game before loading the pack again.
Inline instances in property arrays
Section titled “Inline instances in property arrays”An ordinary properties: entry can replace an array of instanced UObject references. Write each
array entry as a map with class: and optional nested properties:. KDataForge creates the
instance as a subobject of the patched target, then applies the nested property operations. This
works for any compatible instanced object array, including schematic dependencies and unlocks.
Because set is the default operation, the following patch replaces the complete
mSchematicDependencies array on every target. It does not append to existing dependencies:
type: cdopatches: - target: - /RSS/Schematics/Flat/Sink_RSS_Flat_Belt.Sink_RSS_Flat_Belt_C - /RSS/Schematics/Flat/Sink_RSS_Flat_Ceiling.Sink_RSS_Flat_Ceiling_C properties: - path: mSchematicDependencies value: - class: /Game/FactoryGame/AvailabilityDependencies/BP_SchematicPurchasedDependency.BP_SchematicPurchasedDependency_C properties: - path: mSchematics value: - /SatisfactoryPlus/Content/SchematicManager/Schematics/Milestones/T1/Schematic_SF+_T1_0.Schematic_SF+_T1_0_C - path: mRequireAllSchematicsToBePurchased value: true - path: mDependenciesBlocksSchematicAccess value: trueclass: must resolve to a concrete subclass compatible with the array element type. For example,
mUnlocks accepts FGUnlock subclasses and mSchematicDependencies accepts
FGAvailabilityDependency subclasses. The nested properties: use the same paths and operations
as a top-level CDO patch.
The four things you need to know, and where they’re documented
Section titled “The four things you need to know, and where they’re documented”Writing a patch entry means answering four separate questions. Each one is covered by its own page rather than duplicated here: what to target, what operation to apply, how to write the value for the property’s type, and how to address nested/array/map properties in the path itself.
| Concern | Page |
|---|---|
Selecting what to patch: class path, object path, allAssetsOfClass:, ofClass: scope filters (matchTag:, matchName:, producedIn:/ingredient:/product:, where:), applyToSubclasses:, applyToSpawnedActors:, the bare class-name shortcut | Targeting |
| What you can do to a value: all 22 operations and which property kinds accept them | Operations |
| How to write a value: every property kind’s YAML form (bool, numerics, enums, strings, FText, object/class/soft refs, structs, arrays/sets/maps, gameplay tags) | Property Types |
| The path grammar: array indices, map keys, struct/object dereference, authored-name matching | YAML Schema → Property Paths |
Two curated example galleries put all of the above together for real FactoryGame classes: Balancing (recipes, items, resources, schematics, research, categories) and Power & Machines (buildables, power, extractors, pipelines, runtime actor patches).
Diagnostics, never failures
Section titled “Diagnostics, never failures”An unsupported op×type combination, an unresolvable path, or a target that matches nothing all
produce diagnostics. The specific patch entry is skipped, but the
rest of the document, and every other document, still applies. Run /kdf report after any change
to confirm exactly what was patched and see every warning/error in one place.
Vanilla snapshots
Section titled “Vanilla snapshots”Before the first write to a property path on an object, KDataForge records its original text value. The in-game editor uses it for diffing, undo, and changes-only export. The YAML pipeline runs once during initialization and exposes no general reload or document-revert operation.
Runtime actor patches are a separate boundary. They apply operations directly to every matching instance and do not preserve player-modified or save-restored values through snapshot comparison.
Troubleshooting
Section titled “Troubleshooting”- A patch “did nothing” and there’s no error: check
matchTag/where/producedIn/allAssetsOfClassselectors first. A selector that matches zero objects only warns (/kdf report). It doesn’t fail the document, and it’s an easy typo to miss because nothing looks broken until you actually check. - Not sure which of the three target selectors to reach for? Targeting → Choosing a selector has a quick lookup table.
