GlobalVault¶
The GlobalVault table provides a cross-server item storage system, allowing players to deposit items on one server and withdraw them on another. Each row represents a single vault slot containing serialized item data, enabling inventory persistence across the entire QS-Bridge cluster.
Scope¶
🌍 Global — Vault contents are accessible from any server in the cluster. A player can deposit items on server A and retrieve them on server B.
Schema¶
| Column | Type | Constraints | Description |
|---|---|---|---|
vault_id |
u64 |
Primary Key, auto-increment | Unique identifier for this vault entry |
player_id |
String |
Indexed | Platform-wide player identifier who owns the vault slot |
item_data |
String |
— | Serialized item data (JSON format) |
slot |
u32 |
— | Vault slot number for ordering and UI display |
deposited_at |
Timestamp |
— | When the item was deposited into the vault |
source_server_id |
String |
— | The server_id of the server where the item was deposited |
Rust Definition¶
#[spacetimedb::table(public, name = global_vault)]
pub struct GlobalVault {
#[primary_key]
#[auto_inc]
pub vault_id: u64,
#[index(btree)]
pub player_id: String,
pub item_data: String,
pub slot: u32,
pub deposited_at: Timestamp,
pub source_server_id: String,
}
Usage Patterns¶
Game-Agnostic Item Serialization¶
The item_data column stores item information as a JSON string. The platform layer does not parse, validate, or interpret this data — it is treated as an opaque payload. The game-specific sub-database and game hook are responsible for serialization and deserialization.
Example item_data payload (game-specific — format varies by game hook):
{
"item_id": "iron_sword",
"quantity": 1,
"durability": 0.85,
"enchantments": ["sharpness_3"],
"custom_name": "Excalibur"
}
This design preserves the platform's game-agnostic architecture. The GlobalVault table can store items from any game without schema changes.
Deposit Flow¶
- Player opens the vault UI on server A.
- Game hook serializes the selected item to JSON.
- Item is removed from the player's in-game inventory.
- A new
GlobalVaultrow is inserted with the serialized data. - The insertion is confirmed via subscription callback.
// Pseudocode — vault deposit
fn deposit_item(player_id: &str, item: &GameItem, slot: u32, server_id: &str) {
let item_data = serde_json::to_string(item).unwrap();
GlobalVault::insert(GlobalVault {
vault_id: 0, // auto-incremented
player_id: player_id.to_string(),
item_data,
slot,
deposited_at: Timestamp::now(),
source_server_id: server_id.to_string(),
});
}
Withdrawal Flow¶
- Player opens the vault UI on server B.
- Game hook queries the player's vault slots.
- Player selects an item to withdraw.
- Game hook deserializes the
item_dataJSON and creates the in-game item. - The
GlobalVaultrow is deleted.
Slot Management¶
The slot column provides a stable ordering for the vault UI. Slot numbers are managed by the game hook — the platform does not enforce slot uniqueness or maximum slot counts. Game hooks may impose their own limits (e.g., maximum 20 vault slots per player).
Provenance Tracking¶
The source_server_id column records where the item originated. This enables:
- Audit trails: Administrators can see which server an item came from.
- Transfer rules: Game hooks can enforce rules like "items from PvP servers cannot be withdrawn on PvE servers."
- Duplication detection: Combined with timestamps, source tracking helps identify suspicious vault activity.
Security Considerations¶
Item Duplication Prevention¶
The vault system must coordinate with in-game inventory to prevent item duplication. The recommended pattern is:
- Remove from inventory first — Delete the item from the player's in-game inventory.
- Then insert into vault — Create the
GlobalVaultrow. - On withdrawal, reverse — Delete the
GlobalVaultrow, then add to inventory.
Because SpacetimeDB reducers are transactional, the vault insertion (or deletion) is atomic. However, the in-game inventory operation happens outside the WASM module, so game hooks must handle edge cases (e.g., server crash between inventory removal and vault insertion).
Data Integrity¶
Since item_data is an opaque JSON string, the platform cannot validate its contents. Game hooks are responsible for ensuring that deposited items are valid and that the JSON schema matches what the withdrawal logic expects.
Related Reducers¶
Vault operations are typically handled by game-specific reducers in the sub-database layer rather than platform-level reducers. The platform provides the table; the game hook provides the logic.
Related Subscriptions¶
| Subscriber | Query | Purpose |
|---|---|---|
| Game Hook | SELECT * FROM global_vault WHERE player_id = '{player_id}' |
Player vault contents |
| Admin Panel | SELECT * FROM global_vault |
Vault administration, item inspection |
For full subscription architecture, see Subscriptions.
Related Pages¶
- ServerTransferQueue — Full character transfers (vault is for individual items)
- PlayerServerPresence — Player location tracking
- Multi-Server Architecture — Item vault as a cross-server capability
- Platform Overview — How GlobalVault fits in the 12-table platform model