Skip to content

Def System Refactor Playbook (v1)

Relationship To Docs/backend/inventory-selection.md

This document is the Def-focused companion to Docs/backend/inventory-selection.md.

  • backend/inventory-selection.md is still the source of truth for inventory/selection transport behavior and Nakama RPC contracts.
  • This file is the source of truth for Def data model dependencies, tooling, and refactor impact.

Use both docs together when changing Def schemas or import/runtime behavior.

Scope

Covers all Def pipeline parts currently in project:

  • Runtime Def assets:
  • UTankItemDef
  • UTankCharacterDef
  • Def import tooling:
  • Source/Tools/TankInventoryTools
  • TankItemDefCsvImport
  • TankCharacterDefCsvImport
  • Authoring inputs:
  • Source/Tools/TankInventoryTools/TankItemDefs.xlsx
  • Source/Tools/TankInventoryTools/TankCharacterDefs.xlsx
  • External JSON helper tool:
  • Tools/NakamaInventoryWorkbench
  • GameFeature content packaging:
  • currently Plugins/GameFeatures/TankInventory_Base
  • designed to scale to more TankInventory* plugins

Def Contracts (Current)

UTankItemDef (Source/Metal_terra/Public/Data/TankItemDef.h)

Core identity:

  • ItemId (stable gameplay/backend id)
  • CategoryId (ownership bucket)
  • CatalogIndex (index inside category)
  • RequiredFeatureId (optional feature pack marker)

Presentation:

  • DisplayName
  • Icon
  • StaticMesh
  • SkeletalMesh

Editor constraint:

  • CatalogIndex is clamped to >= 0 in PostEditChangeProperty.

UTankCharacterDef (Source/Metal_terra/Public/Data/TankCharacterDef.h)

Core identity:

  • CharacterId (stable gameplay/backend id)
  • CategoryId
  • ClassId (import header class)
  • CatalogIndex
  • RequiredFeatureId

Gameplay/presentation/progression:

  • class refs: CharacterBP, AnimBP
  • montage refs: HitReactionMontage, DeathMontage
  • gameplay effects: PrimaryAttributes, SecondaryAttributes, VitalAttributes
  • StartupAbilities
  • DisplayName, Description, Icon, SkeletalMesh
  • StartingLevel, UnlockedSkillIds, StatDistribution

Editor constraints:

  • CatalogIndex >= 0
  • StartingLevel >= 1
  • movement/lives/stats/ability numeric values clamped non-negative

End-To-End Data Flow

  1. Designers edit XLSX (Source/Tools/TankInventoryTools/*.xlsx).
  2. Import scripts run commandlets (Run-TankItemImport.ps1, Run-TankCharacterImport.ps1).
  3. Commandlets create/update/prune Def assets under selected content root:
  4. Items forced under <OutputPath>/Item/...
  5. Characters forced under <OutputPath>/Character/...
  6. Def assets are packaged via GameFeature plugin content (currently TankInventory_Base).
  7. Runtime systems consume Def fields:
  8. ownership index (UTankInventorySubsystem)
  9. selection payload build (UOnlineSelectionPayloadLibrary)
  10. selection authority/broadcast (UOnlineManagerSubsystem, FOnlineSelectionTransportService)
  11. character spawn/ability/attribute runtime (ATankPlayerState, ATankGameMode, ATankCharacterBase, UTankAbilitySystemBPLibrary)
  12. Nakama RPC payloads use Def-derived category/index values.
  13. NakamaInventoryWorkbench uses workbook catalogs + bitset encoding for offline owned-snapshot generation and inspection.

Dependency Graph (What Breaks If Defs Change)

ItemDef dependencies

Def identity field usage (CategoryId, CatalogIndex, ItemId):

  • UTankInventorySubsystem
  • RebuildItemDefIndex() indexes TankItemDef assets by (CategoryId, CatalogIndex).
  • TryResolveItemDefAssetId() resolves from (CategoryId, CatalogIndex).
  • TryExtractAddressFromAssetData() reads asset registry tags for CategoryId and CatalogIndex.
  • UOnlineSelectionPayloadLibrary
  • reads ItemDef.CategoryId and ItemDef.CatalogIndex when building equipped.selected[].
  • TankItemDefCsvImportCommandlet
  • writes all item identity/presentation fields.

CharacterDef dependencies

Def identity field usage (CharacterId, CategoryId, CatalogIndex):

  • UOnlineSelectionPayloadLibrary
  • reads CharacterDef.CategoryId + CharacterDef.CatalogIndex.
  • ATankPlayerState
  • resolves selected character from equipped.selected[] by catalog index.
  • loads TankCharacterDef primary assets and applies to replicated state.
  • UTankBlueprintFunctionLibrary
  • resolves by CharacterId and reads StartupAbilities.
  • ATankPlayerController
  • local selection preview/prediction uses resolved CharacterId.
  • TankCharacterDefCsvImportCommandlet
  • writes identity/presentation/progression fields.

Character gameplay field usage:

  • ATankGameMode -> CharacterDef->CharacterBP for pawn class selection.
  • ATankCharacterBase and UTankAbilitySystemBPLibrary -> PrimaryAttributes, SecondaryAttributes, VitalAttributes.
  • ATankPlayerState -> StartupAbilities, Lives, MovementSpeed, sync-loads referenced soft assets.
  • UOnlineManagerSubsystem and FOnlineSelectionTransportService -> synchronous loading of CharacterDef bundles + soft references before submit/broadcast.

Import Tooling Contract

Item import (TankItemDefCsvImport)

Source columns (case-insensitive aliases supported):

  • required: itemId
  • optional: assetName, categoryId, catalogIndex, requiredFeatureId, displayName, iconPath, staticMeshPath, skeletalMeshPath

XLSX behavior:

  • every worksheet is imported
  • worksheet name becomes CategoryId for that sheet
  • optional row categoryId different from sheet name is ignored with warning

Output behavior:

  • output is forced to <OutputPath>/Item/<CategoryFolder>/<AssetName>
  • strict mirror mode: stale assets under output root are deleted

Character import (TankCharacterDefCsvImport)

Source columns (case-insensitive aliases supported):

  • required: characterId
  • optional: assetName, categoryId, class, catalogIndex, requiredFeatureId, displayName, description, iconPath, skeletalMeshPath, startingLevel, unlockedSkills, strength, agility, intellect, vitality

XLSX behavior:

  • currently requires worksheet named 1

Category fallback order:

  • row categoryId
  • commandlet -DefaultCategory
  • source label (worksheet name)
  • hard fallback 1

Output behavior:

  • output is forced to <OutputPath>/Character/<AssetName>
  • strict mirror mode: stale assets under output root are deleted

Shared commandlet flags

  • -StartIndex
  • -DefaultCategory
  • -PerCategory
  • -UseExistingMax
  • -DryRun

XLSX Inputs In Source/Tools

  • Source/Tools/TankInventoryTools/TankItemDefs.xlsx
  • Source/Tools/TankInventoryTools/TankCharacterDefs.xlsx

These files are part of the Def schema contract. If column names or semantics change in Def classes, update:

  • commandlet parser aliases
  • USAGE.md
  • designer workbook templates
  • NakamaInventoryWorkbench workbook parser if it consumes those columns

NakamaInventoryWorkbench Dependency

Primary files:

  • Tools/NakamaInventoryWorkbench/NakamaInventoryWorkbench/WorkbookReaders.cs
  • Tools/NakamaInventoryWorkbench/NakamaInventoryWorkbench/CoreModels.cs
  • Tools/NakamaInventoryWorkbench/NakamaInventoryWorkbench/InventoryCodec.cs

Important coupling:

  • category normalization: trim + lowercase
  • bitset encoding contract: bitset_b64_lsb0
  • owned snapshot JSON fields: schema_version, catalog_version, owned_epoch, owned_rev, encoding, owned[]
  • workbook parser reads item/character id/category/display fields and optional stats

Character indexing note:

  • Workbench treats character sheets by characterId header and auto-assigns catalogIndex by row order per category.
  • This may diverge from explicit character catalogIndex managed by commandlets if workbook/order rules are changed.

If character index semantics change, update both UE import and Workbench parser logic together.

GameFeature Packaging Dependency

Current runtime content pack:

  • Plugins/GameFeatures/TankInventory_Base

Current packaging/cook references:

  • Metal_terra.uproject enables TankInventory_Base plugin
  • Config/DefaultGame.ini includes +DirectoriesToAlwaysCook=(Path="/TankInventory_Base")

Import scripts (Run-TankItemImport.ps1, Run-TankCharacterImport.ps1) behavior:

  • patch picker scans Plugins/GameFeatures for plugin names matching ^TankInventory(?:_|$)
  • selected plugin Content folder is used as output root
  • scripts append /Item or /Character

Future expansion rule:

  • additional GameFeatures should keep TankInventory* naming if you want automatic picker discovery.
  • otherwise update script matcher logic.

Refactor Matrix: Change X -> Update Y

Change Type Must Update
Rename/add/remove Def property in UTankItemDef TankItemDef.h/.cpp, item commandlet parse/write (TankItemDefCsvImportCommandlet.cpp), XLSX headers/templates, USAGE.md, any runtime consumer reading the field
Rename/add/remove Def property in UTankCharacterDef TankCharacterDef.h/.cpp, character commandlet parse/write (TankCharacterDefCsvImportCommandlet.cpp), XLSX headers/templates, USAGE.md, runtime consumers (TankPlayerState, TankGameMode, selection payload/transport, ability init)
Change CategoryId or CatalogIndex semantics UTankInventorySubsystem, UOnlineSelectionPayloadLibrary, ATankPlayerState selection resolve, both commandlets, workbook conventions, backend validation expectations
Change equipped JSON shape generated from defs UOnlineSelectionPayloadLibrary, ATankPlayerState::TryExtractCharacterCatalogIndexFromEquippedJson, backend parser assumptions in backend/inventory-selection.md
Change character asset loading policy UOnlineManagerSubsystem::EnsureCharacterDefFullyLoadedForSelectionSubmit, FOnlineSelectionTransportService::EnsureCharacterDefFullyLoadedForBroadcast, ATankPlayerState::SyncLoadCharacterDefSource
Change import sheet rules both commandlets, USAGE.md, source .xlsx authoring guidance, Workbench reader behavior
Change feature-pack routing (RequiredFeatureId semantics) Def class comments/contract, both commandlets, any feature-gating runtime code (currently minimal usage), docs
Add new GameFeature def pack plugin enablement (.uproject), cook rules (DefaultGame.ini), import script picker compatibility, content path conventions

Add New Def Type (Future) Checklist

  1. Create new UPrimaryDataAsset Def class in Source/Metal_terra/Public/Data.
  2. Define stable identity fields up front (id/category/index + optional feature marker if needed).
  3. Mark identity fields AssetRegistrySearchable if runtime indexing/resolution needs tags.
  4. Add editor validation clamps in PostEditChangeProperty.
  5. Add import commandlet in Source/Tools/TankInventoryTools.
  6. Add run scripts and update USAGE.md.
  7. Add/maintain source workbook template in Source/Tools/TankInventoryTools.
  8. Add runtime subsystem indexing/resolution if this Def participates in ownership or selection.
  9. Update selection payload builder if this Def appears in equipped.selected[].
  10. Update Nakama contracts/docs (backend/inventory-selection.md) for any new payload fields.
  11. Update NakamaInventoryWorkbench if offline JSON generation/inspection should include this Def.
  12. Add cook/plugin/content routing for GameFeature distribution.

Known Current Gaps To Keep In Mind

  • Character import is still single-sheet (1) oriented, while tooling around catalogs is becoming more generalized.
  • RequiredFeatureId and ClassId are imported but currently have limited runtime consumers; they are mostly metadata right now.
  • Character def load-hardening exists in multiple paths (submit, broadcast, player-state sync-load). Refactors should avoid diverging behavior between these loaders.
  • Legacy UCharacterClassInfo still exists in source as historical data shape; active selection authority path is Def-driven.

Validation Checklist After Any Def Refactor

  1. Build C++ project and ensure Metal_terra + TankInventoryTools compile.
  2. Run item import with -DryRun, then real run; verify created/updated/deleted counts look expected.
  3. Run character import with -DryRun, then real run; verify sheet/category/index expectations.
  4. Verify runtime logs:
  5. RebuildItemDefIndex: indexed N item defs
  6. no duplicate (CategoryId, CatalogIndex) errors
  7. Verify selection submit path builds payload from defs without BuildEquippedJsonFromDefs errors.
  8. Verify server broadcast tick resolves character defs successfully.
  9. Verify Nakama selection confirm/lock RPCs still accept payloads.
  10. Verify NakamaInventoryWorkbench can load workbook and generate/parse owned snapshot JSON for changed schema.

Fast File Index

Core Def classes

  • Source/Metal_terra/Public/Data/TankItemDef.h
  • Source/Metal_terra/Private/Data/TankItemDef.cpp
  • Source/Metal_terra/Public/Data/TankCharacterDef.h
  • Source/Metal_terra/Private/Data/TankCharacterDef.cpp

Runtime consumers

  • Source/Metal_terra/Private/Core/Subsystems/TankInventorySubsystem.cpp
  • Source/Metal_terra/Private/Core/Subsystems/Online/OnlineSelectionPayloadLibrary.cpp
  • Source/Metal_terra/Private/Core/Subsystems/OnlineManagerSubsystem.cpp
  • Source/Metal_terra/Private/Core/Subsystems/Online/OnlineSelectionTransportService.cpp
  • Source/Metal_terra/Private/Core/TankPlayerState.cpp
  • Source/Metal_terra/Private/Core/TankPlayerController.cpp
  • Source/Metal_terra/Private/Core/TankGameMode.cpp
  • Source/Metal_terra/Private/AbilitySystem/TankAbilitySystemBPLibrary.cpp
  • Source/Metal_terra/Private/Character/TankCharacterBase.cpp

Import tooling

  • Source/Tools/TankInventoryTools/Private/Commandlets/TankItemDefCsvImportCommandlet.cpp
  • Source/Tools/TankInventoryTools/Private/Commandlets/TankCharacterDefCsvImportCommandlet.cpp
  • Source/Tools/TankInventoryTools/Run-TankItemImport.ps1
  • Source/Tools/TankInventoryTools/Run-TankCharacterImport.ps1
  • Source/Tools/TankInventoryTools/USAGE.md

External helper tool

  • Tools/NakamaInventoryWorkbench/README.md
  • Tools/NakamaInventoryWorkbench/NakamaInventoryWorkbench/WorkbookReaders.cs
  • Tools/NakamaInventoryWorkbench/NakamaInventoryWorkbench/CoreModels.cs
  • Tools/NakamaInventoryWorkbench/NakamaInventoryWorkbench/InventoryCodec.cs

Packaging/config

  • Plugins/GameFeatures/TankInventory_Base/TankInventory_Base.uplugin
  • Config/DefaultGame.ini
  • Metal_terra.uproject