Meme Wars · design notes

The inventory becomes a screen.

The first grid inventory just wrapped your held items into a bordered strip — a row with a box drawn around it. What you asked for is a menu: something you open over the paused-feeling game, a panel of slots you look across and act on, with a hotbar that lives at the bottom and shows up inside the panel too. Here's the target, the one real architectural fork it raises, and a phased way in.

Exploratory · designing the menu inventory before building it
The target

What you open when you press I

A centered window over a dimmed world. A grid of slots — filled ones carry an icon and a stack count, empty ones sit waiting. Hovering names the item. A strip along the bottom is the hotbar: the same eight slots you carry into the fight, shown here so the screen and the HUD agree. This is a mock — real icons are the game's own pickup art, not emoji.

Inventory

I / Esc to close
AllCropsFood ToolsBlocks
🌱12
🌾4
🍖3
🔥1
🧱28
🥔6
Seeds· plant them to grow cropsclick to drop one · drag to move
Hotbar — carried into the game
🌱12
🔥1
🧱28

…and with the screen closed, only the hotbar strip stays on the HUD:

🌱12
🔥1
🧱28

The screen (top) and the always-on hotbar (bottom) are one system seen two ways.

The gap

Why the first pass fell flat

The shipped grid reads the same held-item map the row hotbar does and lays it out in rows inside a panel. Functionally it's the hotbar with a border — no new capability, no sense of "opening" your pack. The menu is a different mode: it takes over the screen, gives every item room, and is where arranging, dropping, and (later) crafting happen.

shipped · a widget

The bordered row

  • always drawn top-left, competing with the HUD
  • a sorted view — order isn't yours to set
  • no hover, no selection, no actions
  • wraps to a second row and stops there
target · a mode

The screen you open

  • a modal over a dimmed world — a deliberate pause in feel
  • a full grid: every slot visible, empties included
  • hover to name, click to act, drag to arrange
  • a hotbar strip that persists on the HUD and mirrors here
The one real fork

Do items live in slots?

Everything else is presentation over the inventory model we already have. This is the question that changes the data: is the grid a view of your item counts, or do items occupy fixed slots you rearrange — the Minecraft model, where an empty slot 3 is a real, saved fact?

Option A · recommended first

A sorted view of the counts

The grid renders the same item → count map, sorted (by category, then name). No new server state; the screen is pure client. Dropping/eating already work through the model.

For: ships now, reuses the wheel's drop path, nothing to persist or sync.

Against: you can't hand-place items or keep an empty gap; layout is the game's choice, not yours.

Option B · later layer

Fixed, arrangeable slots

The player gains a slots component — an array where index is position and empties are real. Drag moves an item between indices; the hotbar is just slots 1–8.

For: muscle-memory layout, real hotbar assignment, the base crafting needs.

Against: new authoritative state to persist (Set 13) + sync; migration when items appear/vanish; more UI.

Recommendation

Build the screen against Option A now — a sorted view, drawn client-side, drop-on-click — so you get the menu feel this playtest. Add Option B's slots component as an opt-in later step once the screen exists and we know what arranging should feel like. The UI built for A (grid, hover, selection, hotbar strip) is exactly what B reuses; only the data source under it changes.

Where it's drawn

Canvas overlay, like the wheel

Two homes are possible: a DOM modal (like the settings menu) or a canvas overlay (like the item wheel). The inventory wants the game's own pickup icons — which are canvas art (pickupIcon) — and it wants to sit in the same input mode the wheel already established. So it lives on the canvas, reusing the exact plumbing the wheel shipped with:

-- the grid-inventory plugin stays thin: it only claims the mode + the key.
local inv = engine.require("inventory")
inv.suppressHotbar()                 -- the row hotbar steps aside; the strip replaces it
plugin.control("open", { default = "KeyI", label = "Inventory" }, function() end)

-- client.lua opens the built-in screen; the engine draws it (icons, grid, hotbar).
on_input("grid-inventory.open", function() screen.toggle("inventory") end)

The screen itself is engine client UI — a new UIService state (open/closed, selection, hover) plus a renderer.drawInventory, both modeled on the itemWheel pair already in the tree. Input (hover, click-to-drop, later drag) extends the same InputService block that handles the wheel. The plugin contributes the key and the hotbar-suppression; it doesn't reinvent the drawing. This is also the concrete next step toward Lua-declared menus — the inventory is the first menu rich enough to prove that surface.

A way in

Phased, testable each step

Phase 1

The screen + the strip

Modal grid over a dimmed game (Option A data), a persistent hotbar strip on the HUD, open/close on a key, hover-to-name. Replaces the bordered row. This is the playtestable menu.

Phase 2

Acting on items

Click a slot to drop one (reusing the wheel's validated drop path); number keys 1–8 select the active hotbar item. Still no new server state.

Phase 3

Arranging — the slots component

Opt into Option B: fixed slots, drag to move, real hotbar assignment, split/merge stacks. New authoritative state, persisted with the world (Set 13) and synced.

Phase 4

Categories + search

The tabs in the mock (Crops / Food / Tools / Blocks) filter by the item category we already tag; a filter field for big inventories. Cosmetic once the grid exists.

Before I build

Three calls I'd like from you

Q1

Sorted view first (Option A), or hold for arrangeable slots (Option B)? My rec is A now, B later — but if hand-arranging is core to the feel you want, we can start with slots and skip the throwaway.

Q2

The key. I reads as "inventory," but blocks currently own an I panel. Reuse and replace it, or a different key (Tab is scores)? Your call on the binding.

Q3

Dim + pause feel. The mock dims the world behind the screen. Do you want it to read as paused (dark overlay, muted), or stay light so you can watch the fight while you sort?

If you just say "go"

I'll build Phase 1 + 2 against Option A on the I key with a dimmed overlay — the menu you can open, look across, and drop from — and leave arrangement (Phase 3) for after you've felt it. That's the version worth playtesting next.