import { type InventoryLayout, type InventorySet, type InventoryState, type ItemTraits } from "../../inventory/inventoryModel.js"; import type { ObjectStore } from "../../scene/objectStore.js"; /** Why an object slot mutation was refused — the instance, its catalog entry, the player inventory, or the declared `accepts`/capacity. */ export type ObjectSlotRejection = "unknown-object" | "no-slot-inventory" | "unknown-inventory" | "no-space" | "wrong-kind" | "slot-occupied" | "invalid-slot" | "insufficient"; /** Outcome of an object slot mutation: applied, or refused with a reason and no state change on either side. */ export type ObjectSlotResult = { status: "ok"; } | { status: "rejected"; reason: ObjectSlotRejection; }; /** Which player inventory a transfer moves between, and what it moves. */ export interface ObjectSlotTransfer { instanceId: string; userId: string; inventoryId: string; itemId: string; /** Defaults to `1`. */ count?: number; /** Explicit slot index **on the object**; omit to auto-place (transfer in) or drain the object's matching stacks (transfer out). */ slot?: number; } /** * Per-instance container contents for placed objects whose catalog entry declares `slotInventory` — * the engine side of "install a GPU into a rack", "put an item in a chest". Contents live on * `SceneObject.slots`, so they replicate and save with the object rather than needing a game-owned * table keyed by `instanceId`, and every mutation is validated against the declared `accepts` and * stack limits. * * @capability object-slot-inventory placed objects hold validated per-instance container contents that replicate and save with the placement */ export interface SceneObjectSlots { /** The catalog `slotInventory` layout for a placed instance, or `null` when its catalog entry declares none. */ layout(instanceId: string): InventoryLayout | null; /** Live contents, defaulting to the layout's empty slots. `null` when the instance is unplaced or has no `slotInventory`. */ state(instanceId: string): InventoryState | null; /** How many of `itemId` this object holds; `0` for an unplaced or slot-less instance. */ count(instanceId: string, itemId: string): number; /** Add items directly, bypassing any player inventory — world seeding, loot generation, admin tools. */ put(instanceId: string, itemId: string, count?: number, options?: { slot?: number; }): ObjectSlotResult; /** Remove items directly, bypassing any player inventory. */ take(instanceId: string, itemId: string, count?: number): ObjectSlotResult; /** Move items from a player inventory into the object's slots; nothing is consumed if the object rejects them. */ transferIn(transfer: ObjectSlotTransfer): ObjectSlotResult; /** Move items from the object's slots into a player inventory; nothing leaves the object if the inventory rejects them. */ transferOut(transfer: ObjectSlotTransfer): ObjectSlotResult; } /** @internal */ export interface ObjectSlotsDeps { objects: ObjectStore; layoutOf: (instanceId: string) => InventoryLayout | null; traits: () => ItemTraits; hasInventory: (inventoryId: string) => boolean; inventoryFor: (userId: string) => InventorySet | null; notify: () => void; } /** @internal */ export declare function createObjectSlots(d: ObjectSlotsDeps): SceneObjectSlots;