Phase 2 foundation. Do this first — smelting (#3), tools (#4) and farming (#5) all build on the recipe registry and slot/UI patterns established here.
Context
The inventory already ships a disabled 2x2 crafting grid placeholder at src/ui/InventoryUI.ts:77-88 — four slot slot-disabled divs with no backing data model. There is no recipe registry and no matcher anywhere in the codebase today.
Scope
- New
src/game/Recipes.ts — does not exist. Define:
Recipe type supporting shaped (pattern + key→itemId) and shapeless (set of inputs) recipes
RECIPES registry array
match(grid: (ItemId | null)[]): ItemId | null matcher that scans both 2x2 (inventory) and 3x3 (table) subregions
src/ui/InventoryUI.ts:77-88 — replace the four slot-disabled divs with interactive craft-input slots and a live output slot that re-resolves on every grid mutation; consume inputs on craft.
src/game/Inventory.ts — add a craftingGrid: ItemStack[9] field (separate from backpack slots); reuse existing getSlot/setSlot/add/remove helpers (lines 31-91). Persist craft-grid state with the save.
src/game/Items.ts — register newly craftable item ids (e.g. planks, stick, crafting_table); add to CREATIVE_PALETTE (line 84) and DROP_TABLE (line 114) as needed.
src/ui/ui.css (~.inv-craft-grid lines 695-712) — drop slot-disabled styling, add hover/active/drag state.
- (Optional, unlock 3x3) Add a
crafting_table block — requires touching Blocks.ts + BlockIds.ts + Textures.ts in lockstep per AGENTS.md (block ids must stay stable; atlas is 8x8 = 64 tiles).
Starter recipe set
- 1 log → 4 planks (shapeless)
- 2 planks → 4 sticks (shaped)
- 4 planks → crafting table (shaped)
Acceptance criteria
Roadmap reference
Phase 2 — "Crafting system".
Phase 2 foundation. Do this first — smelting (#3), tools (#4) and farming (#5) all build on the recipe registry and slot/UI patterns established here.
Context
The inventory already ships a disabled 2x2 crafting grid placeholder at
src/ui/InventoryUI.ts:77-88— fourslot slot-disableddivs with no backing data model. There is no recipe registry and no matcher anywhere in the codebase today.Scope
src/game/Recipes.ts— does not exist. Define:Recipetype supporting shaped (pattern + key→itemId) and shapeless (set of inputs) recipesRECIPESregistry arraymatch(grid: (ItemId | null)[]): ItemId | nullmatcher that scans both 2x2 (inventory) and 3x3 (table) subregionssrc/ui/InventoryUI.ts:77-88— replace the fourslot-disableddivs with interactive craft-input slots and a live output slot that re-resolves on every grid mutation; consume inputs on craft.src/game/Inventory.ts— add acraftingGrid: ItemStack[9]field (separate from backpackslots); reuse existinggetSlot/setSlot/add/removehelpers (lines 31-91). Persist craft-grid state with the save.src/game/Items.ts— register newly craftable item ids (e.g.planks,stick,crafting_table); add toCREATIVE_PALETTE(line 84) andDROP_TABLE(line 114) as needed.src/ui/ui.css(~.inv-craft-gridlines 695-712) — dropslot-disabledstyling, add hover/active/drag state.crafting_tableblock — requires touchingBlocks.ts+BlockIds.ts+Textures.tsin lockstep perAGENTS.md(block ids must stay stable; atlas is 8x8 = 64 tiles).Starter recipe set
Acceptance criteria
Recipes.tsis exported and unit-testable (purematch()function).Roadmap reference
Phase 2 — "Crafting system".