KBVEItemDB
Overview
Section titled “Overview”Game-agnostic item database + inventory + Mass bridge. The data/inventory half to KBVEGameplay’s effect half:
FKBVEItemDef/FKBVEItemFood— runtime item def: identity, type flags, rarity, stacking, prices, tags, and consumable/food effect fields (heals / restoreMana / restoreEnergy / regenPerSecond / regenDuration / cooldown / animationRef) — aligned toFKBVEEffectSpecso a game maps item → effect.UKBVEItemDatabase(GameInstance subsystem) — loadsContent/Data/itemdb-data.jsonvia UE Json; lookup by key / ref. Mirrors thechuckItemDBpattern.FKBVEInventory/FKBVEInventoryBag/FKBVEInventoryStack+UKBVEInventoryLibrary(TryAdd/CountItem/FindFirstSlot) — generic inventory model.FKBVEDroppedItemFragment/FKBVEDroppedItemTag— Mass fragment for world-dropped items (key, count, rarity, lifetime, magnet/pickup radius).
Item DATA stays in the shared itemdb MDX. KBVEItemDB carries it + the inventory model; KBVEGameplay applies the consumable effects (atlas/icon rendering deferred).
Consumables (type- + data-driven)
Section titled “Consumables (type- + data-driven)”type_flags classify the consumable — FOOD (0x08) / DRINK (0x10) / POTION
(0x20) — and the food: block carries the numbers: heals / restore_mana /
restore_energy (instant), regen_per_second + regen_duration (heal-over-time),
plus top-level cooldown. A consumer builds an FKBVEEffectSpec from these
(instant Restores + Regens, cooldown-gated) and applies it through
KBVEGameplay’s UKBVEEffectComponent → IKBVEStatTarget. Type picks the regen
target (food → health, drink → mana/stamina); the data fills the magnitudes. An
item with a food: block or a food/drink/potion type bit is consumable without
needing an explicit consumable: true.
Dropped items (AKBVEDroppedItemActor / UKBVEDroppedItemPool)
Section titled “Dropped items (AKBVEDroppedItemActor / UKBVEDroppedItemPool)”Pooled, billboarded world-drop system — extracted from chuck’s
chuckDroppedItemActor / chuckDroppedItemPool and made game-agnostic.
AKBVEDroppedItemActor— sphere overlap root + icon/haloUMaterialBillboardComponent- rarity
UPointLightComponent. Idle bob, then pawn-overlap triggers a homing ease toward the picker; on complete it calls back into the pool. No game types.
- rarity
UKBVEDroppedItemPool(world subsystem) — preallocatesInitialPoolSize(64) actors, free-listSpawnDrop/ReleaseDrop, firesOnItemPickedUp(Picker, ItemKey, Count)on homing-complete so the game owns auth + inventory add.IKBVEDroppedItemVisualProvider(icon-provider seam) — game implementsGetDroppedItemVisual(ItemKey, FKBVEDroppedItemVisual&)to supply per-itemIconMID/HaloMID/RarityColor; registered viaSetVisualProvider. Keeps atlas/MID generation game-side while the pool stays generic.
The chuck-specific Cast<AchuckCoreCharacter> + ServerAddItemByKey pickup path
becomes: provider feeds visuals, OnItemPickedUp delegate feeds the inventory.
chuck now consumes this directly — UchuckItemDB implements
IKBVEDroppedItemVisualProvider (maps key → atlas icon MID + rarity halo) and
hosts the OnItemPickedUp handler (HandleDroppedItemPickedUp → authority-gated
ServerAddItemByKey); AchuckCoreCharacter::BeginPlay registers the DB as the
pool’s provider + pickup sink once, and ServerDropSlot just calls
SpawnDrop(ItemKey, Count, Loc). chuck’s old chuckDroppedItemActor /
chuckDroppedItemPool are deleted.
Generated proto types (gen-itemdb-uecpp.mjs)
Section titled “Generated proto types (gen-itemdb-uecpp.mjs)”The same itemdb.binpb descriptor that feeds the zod generator also feeds a UE
C++ emitter (packages/data/codegen/gen-itemdb-uecpp.mjs, run via
nx run astro-kbve:sync:itemdb-uecpp). It writes, into Public/Generated/:
KBVEItemDBProtoTypes.h— oneUSTRUCTper item-package proto message (FKBVEGenItem,FKBVEGenFoodInfo,FKBVEGenUseEffect, …), topo-ordered so definitions precede use; scalars/enums/nested/repeatedmap to UE types.KBVEItemDBProtoParse.h—KBVEItemDBProto::Populate(FStruct&, yyjson_val*)per message, reading the camelCase JSON keys the data codegen emits.
So a new proto field regenerates both the struct and its JSON reader — no
hand-written parser to drift (the class of bug that silently dropped consumable
data). The mirror of the zod generator, emitting UE-native USTRUCTs instead of
google::Message (no libprotobuf runtime). Pilot: generated + compiled by the
KBVEItemDB build; chuck keeps its hand-parser until it migrates onto these.
Persistence (FKBVEInventoryStore / UKBVEInventoryStoreSubsystem)
Section titled “Persistence (FKBVEInventoryStore / UKBVEInventoryStoreSubsystem)”Durable local inventory via the KBVESQLite plugin — row-per-slot
(player_inventory(player_id, bag_ref, slot_idx, item_key, count, durability, flags),
WAL), save/load/count/clear by player id, opened at Saved/KBVE/inventory.db.
Two boundaries to respect:
- SQLite ⟂ Mass. SQLite is a persistence boundary, not a per-tick datasource:
load → seed Mass fragments at spawn/login, mutate fragments on worker threads,
flush fragments → SQLite at intervals/logout (game thread / async). A single
sqlite3*is not thread-safe; never query it inside the Mass processor loop. - KBVESQLite ⟂ UE SQLiteCore. KBVESQLite is the single sqlite provider for
KBVE code (its own vendored
sqlite3). Do not also link the engine’sSQLiteCorein the same module — duplicatesqlite3_*symbols crash the build/run. Plugins depending on KBVESQLite declaredependency_plugins: packages/unreal/KBVESQLite.