This page answers common questions that come up while integrating ItemVault.
How should I add ItemVault services to a scene?
Add an ItemVaultRuntime node to scenes that need an item database and
pickup-to-inventory routing. The runtime owns scoped services for the scene and
keeps tests, menus, split-screen scenes, and demos isolated.
If your game already has a global inventory service, keep it in the game layer
and pass the relevant inventory target into ItemVaultRuntime.
Where do game-specific item terms go?
Use ItemDefinition.id, category, and tags for item-type vocabulary. Use
ItemStack.instance_id when a specific stack needs to link to game-owned
instance data.
Use WorldItemStackMeta only for the spawned world-node handoff of an ItemVault
ItemStack.
What happens if a pickup disappears or the world unloads?
WorldItemStackMeta stores the stack on the pickup node's Godot metadata. It is
not a global registry.
If the pickup node is freed, the stack metadata is freed with the node. If the world unloads, unsaved pickup-node metadata is gone. No registry cleanup is required.
If dropped pickups need to persist, save the stack before removing the node:
var stack:= WorldItemStackMeta.read(pickup)
if stack!= null:
save_world_drop(pickup.global_position, stack.to_dict())On load, recreate the pickup node, rebuild the stack from saved data, and write
it back with WorldItemStackMeta.write(pickup, stack).
Why is the pickup connector called a bridge?
Pickup nodes emit PickupEvent values. InventoryPickupBridge consumes those
events and mutates the configured Inventory or Wallet.
That keeps pickup nodes simple while keeping the default flow tightly integrated:
PickupEvent -> InventoryPickupBridge -> Inventory or WalletWhy is SpawnEvent.dimension not a routing key?
The field is diagnostic. Your code should branch on the actual node type when it needs dimension-specific behavior:
if event.spawneris Node3D:
var position:Vector3 = event.spawner.global_position
elif event.spawneris Node2D:
var position:Vector2 = event.spawner.global_positionSee dimension-neutral-handling.md.
Why is SpawnEvent.stack null?
The spawned pickup node probably did not carry ItemVault stack metadata. If you spawn pickup scenes manually, attach the stack before the event is emitted:
WorldItemStackMeta.write(pickup, stack)If you use RandomDrops or InventoryDrop, ItemVault writes this metadata for
you when a valid DropEntry or inventory item resolves an ItemStack.
Why did an item disappear when loading a save?
ItemVault drops stacks whose id cannot be resolved by ItemDatabase. This
keeps old saves loadable after an item is removed or renamed, but stable ids
matter.
Fix:
- Keep
ItemDefinition.idstable after release. - Register every item definition in
ItemDatabase. - Add migration code before changing save ids.
What 3D support is in 1.0?
ItemVault 1.0 scopes core 3D item flow:
SceneSpawner3DSpawnSceneAtPoint3DPickup3DPickupsCollector3D- 3D move-on-spawn
- pickup-to-inventory routing
3D convenience spawners ShapeEdgeSceneSpawner3D and
LaunchForceSceneSpawner3D are planned for a future ItemVault release and are
not shipped in 1.0.
Why does the showroom number differ from the scene filename?
Scene files keep stable historical names (01_roundtrip.tscn,
05_pickup_to_inventory.tscn, …) so tests and docs links do not churn. The
demo showroom renumbers cards by marketability (pickup and 3D first, JSON
round-trip last). Capture GIFs follow that same presentation order. See
Getting Started → Included demos.
Why don't storefront screenshots show unknown-id / null paths?
Storefront stills and GIFs are golden-path only: successful serialize/restore,
successful rolls into inventory, buy → sell → buyback economics, and live
collection. Robustness (unknown id → null, full inventory overflow) is
covered by automated tests so marketing art stays readable.
Shop buyback price looks wrong — is that a bug?
Buy uses the shop catalog price. Sell credits the wallet at the sell price. Buyback restores the item at the recorded sale credit for that slot, not the original catalog buy price. That matches typical shop UX (no free markup on refund).
My inventory is full. How do I show feedback?
Connect the bridge rejection signal:
runtime.bridge.pickup_rejected.connect(_on_pickup_rejected)
func _on_pickup_rejected(event:PickupEvent, overflow:ItemStack)-> void:
print("Inventory full:%s x%s" % [overflow.item.id, overflow.quantity])Where should I start?
Start with getting-started.md, then read
item-data-and-stack-metadata.md,
json-catalogs-and-saves.md, and
drop-tables.md.