Give the player an inventory
Goal
Press C to collect coins and B to buy something costing three coins. Overflow is visible.
Files you will edit
src/game.ts
Steps
Use this isolated definition in the template shell. Owner 0 is a seat index, not the player's ECS entity id. Definitions and the HUD are hoisted.
tsimport { createInventory, defineGame, type GameContext } from 'gameable'; const bag = createInventory({ owners: 1, slots: 2, items: [{ id: 'coin', stack: 5 }] }); const model = { bars: { coins: { value: 0, max: 10 } }, message: 'Collect' }; function inventory(ctx: GameContext): void { if (ctx.input.pressed('KeyC')) { const overflow = bag.add(0, 'coin', 4); model.message = overflow > 0 ? 'Bag full' : 'Collected'; } if (ctx.input.pressed('KeyB')) { model.message = bag.remove(0, 'coin', 3) ? 'Bought' : 'Need coins'; } model.bars.coins.value = bag.count(0, 'coin'); ctx.hud.set(model); } export default defineGame({ init() { bag.reset(); model.message = 'Collect'; }, systems: [{ run: inventory, on: 'authority' }], snapshot: () => bag.snapshot(), restore: (state) => bag.restore(state), });In a room, size
ownersfor the seat ceiling and validate the checked message sender on the authority. Send the result to that player's HUD.addreturns the amount that did not fit: leave that much in the pickup.removeis atomic; a failed purchase consumes nothing.movemerges or swaps slots, andtransfersucceeds only when the full amount fits.
Verify
sh
npm run devPress C three times: the coin meter reads 4, 8, then 10 and says Bag full (two coins overflow). Press B: it reads 7. After spending down to 1, a further B says Need coins and leaves the meter at 1. Reload empties the bag.