Skip to content

Add AI worldbuilding pipeline for pixel MMO - #1

Open
sdelo1185 wants to merge 34 commits into
masterfrom
claude/pixel-mmo-ai-worldbuilding-w7vwi
Open

Add AI worldbuilding pipeline for pixel MMO#1
sdelo1185 wants to merge 34 commits into
masterfrom
claude/pixel-mmo-ai-worldbuilding-w7vwi

Conversation

@sdelo1185

Copy link
Copy Markdown
Owner

Node.js/Express server with Claude API integration for player-driven
asset creation: players describe weapons, armor, rooms, clothing,
consumables, tools, and furniture in natural language; Claude generates
typed game attributes and a lore validation report; DALL-E 3 renders
a 32-bit pixel art image on submission. Admins review via dashboard
and approve/reject/commit assets to the world catalogue.

Includes: SQLite persistence, admin auth, player worldbuilder UI,
admin dashboard UI, and committed asset catalogue API.

claude added 30 commits May 22, 2026 10:41
Node.js/Express server with Claude API integration for player-driven
asset creation: players describe weapons, armor, rooms, clothing,
consumables, tools, and furniture in natural language; Claude generates
typed game attributes and a lore validation report; DALL-E 3 renders
a 32-bit pixel art image on submission. Admins review via dashboard
and approve/reject/commit assets to the world catalogue.

Includes: SQLite persistence, admin auth, player worldbuilder UI,
admin dashboard UI, and committed asset catalogue API.
GMCP packet system (Room.Info, Room.Players, Room.Items, Char.Status,
Char.Vitals, Move.Success/Fail, Admin.RoomInfo, Admin.AIDraft) over
Socket.io with JWT auth and per-character rate limiting.

Engine layer:
- roomManager: lazy-loaded room state, dig/link/unlink exits, void
  bootstrap, admin overlay with exit targets and item counts
- itemManager: write-through cache, persistent/temporary items,
  per-room item cap enforcement, 30s expiry tick with room broadcast
- playerManager: in-memory session + room index for O(1) "who's here"
- worldBuilder: Claude Opus draft generation (N rooms + connections),
  store→preview→commit workflow via Admin.AIDraft packets

REST API additions:
- /api/auth: register, login, character CRUD
- /api/world: rooms, exits (dig/link/unlink), item templates,
  room items (place/remove), regions, world stats

Admin socket commands: admin:look, admin:dig, admin:link, admin:unlink,
admin:setroom, admin:setcap, admin:placeitem, admin:removeitem,
admin:listrooms, admin:ai:generate, admin:ai:commit, admin:ai:discard,
admin:teleport
Bug fixes:
- trackJoin no longer pre-indexes into roomIndex with stale/null roomId;
  enterRoom now owns the full transition via trackMove
- enterRoom calls trackMove before Socket.io join so getPlayersInRoom is
  always accurate when Room.Info is built
- announceLeave broadcasts using io.to (not socket.leave first) so
  departing player's message reaches remaining occupants
- admin.js io reference renamed to _io and wired correctly via setIO;
  item broadcast calls no longer crash
- look handler uses imported getSession directly (removed broken dynamic import)

Game client (client/game.html):
- Auth screen: login + register tabs with JWT persistence
- Character select: list existing chars, create new with race picker
- Game view: room name/desc, exit buttons, player list, item list,
  HP/MP/EP bars, keyboard movement (WASD + arrows)
- Admin overlay panel: Room tab (dig, link, unlink, edit, teleport),
  Items tab (place/remove), AI tab (generate draft, commit, discard)
- GMCP handler for all modules: Room.Info, Room.Players, Room.Items,
  Char.Status, Char.Vitals, Move.Success/Fail, Admin.RoomInfo,
  Admin.AIDraft, Server.Message/Error
Communication (socket/handlers/communication.js):
- say: broadcasts Comm.Say to current room
- tell: private Comm.Tell to named online player
- yell: broadcasts Comm.Yell to current room + all adjacent rooms
- emote: Comm.Emote to room
- 500ms rate limit per socket, 500 char max

Inventory (socket/handlers/inventory.js):
- item:get  — moves room_item to character_items; merges stacks;
              refuses persistent items; broadcasts Room.Items.removed
- item:drop — moves character_items to room (cap checked); broadcasts
              Room.Items.added
- item:examine — sends item detail with parsed attributes
- inv — emits Char.Items.Inv to socket; also sent on play entry
- GMCP: Comm.Say/Tell/Yell/Emote and Char.Items.Inv added to GM registry

Game client (game.html):
- Phaser.js canvas (pixelArt mode, 240px tall) served from node_modules
  renders terrain background colour + accent scatter per terrain type,
  light overlay for dim/dark rooms, player sprites (self + others)
- Command input bar: say, tell, yell, emote, look, inv, get, drop,
  examine, n/s/e/w/u/d directions — full text command parsing
- Side panel with three tabs: Players, Ground (click to get),
  Inventory (click to drop)
- Keyboard arrow keys still work when not focused on input
- Admin panel carries over all prior admin commands
- engine/raceStats.js: 10 races + 10 classes with CON/INT/DEX-derived HP/MP/EP
- engine/npcManager.js: in-memory NPC index, keyword-matched dialogue, CRUD
- socket/handlers/npc.js: npc:talk, npc:examine, admin:npc:place/remove/dialogue
- schema.sql: npcs table with is_active, room_id, dialogue JSON
- roomManager.js: includes NPCs in Room.Info packets via getNpcsInRoom
- routes/auth.js: character creation uses deriveStats, adds /races /classes endpoints
- routes/world.js: /rooms/:id/npcs endpoint, npcs count in /stats
- socket/index.js: wires npcSetIO, sends full stats+lore in Char.Status
- game.html: class picker in char create, NPCs side tab with talk/examine buttons,
  Room.Npcs delta handler, stats display in vitals bar, admin NPC tab (place/remove/
  dialogue), item template create form in admin items tab, talk command

https://claude.ai/code/session_016DHRqhzhmtcHRRSeBjbFkp
Combat engine (combatManager.js):
- Player attack → damage roll (STR + weapon), NPC retaliation after 2s delay
- NPC health tracked in-memory, loaded lazily on first hit
- Player death: 25% HP restore + teleport to safe zone after 3s
- NPC death: XP + gold granted, kills tracked, respawn timer with Room.Npcs broadcast
- Level-up detection (XP = level² × 100); Char.XP GMCP packet

Equipment system (combat.js handler):
- equip/unequip/equipment socket events
- Slot rules: mainhand/offhand/head/chest/legs/hands/feet/ring/neck
- Equipped items affect combat damage (weapon) and armor reduction
- Char.Equipment GMCP packet for client sync

DB migrations (database.js):
- Adds is_combatant, max_health, attack_power, armor, XP reward, respawn, gold to npcs
- Adds kills, deaths columns to characters
- Migration system with _migrations table prevents re-runs

Passive regen (socket/index.js):
- 10s interval restores 2% HP, 3% MP, 5% EP per tick
- Persisted to DB, Char.Vitals broadcast on change

Client (game.html):
- Combat GMCP handlers: Hit/Miss/Kill/Death/LevelUp/XP/Equipment
- attack/flee/equip/unequip/equipment commands in parser
- NPC list: hostile NPCs shown in red with HP bar + attack button
- Equipment tab: 9-slot gear display, click to unequip
- Inventory: click equippable items to equip; shows equipped glyph
- Worldbuilder modal: 3-step flow (describe → AI preview → submit)
  - Type grid, lore validation display, image preview
  - Calls /api/wb/preview then /api/wb/submit
- Admin NPC panel: combat fields (HP/ATK/DEF/XP/gold/respawn) revealed by checkbox

https://claude.ai/code/session_016DHRqhzhmtcHRRSeBjbFkp
- combat.js flee: directly calls enterRoom instead of socket.emit('move')
  which was incorrectly sending to client rather than triggering server handler
- world.js: add JWT-authenticated submissions endpoints for in-game review:
  GET /submissions, POST /submissions/:id/approve, POST /submissions/:id/reject
- Admin panel: Review tab loads pending/approved submissions, inline approve/reject
- Admin panel: 5th tab (Review) wired into adminTab() tab switcher
- combatManager: fix _xpForLevel formula (was already correct)

https://claude.ai/code/session_016DHRqhzhmtcHRRSeBjbFkp
skillManager.js:
- 25 skills: 1 universal (focus) + 2-3 per class
- Skill types: damage (fireball/smite/shadowbolt/lifedrain/bladestorm/whirlwind/flurry),
  heal (secondwind/meditation/layonhands/natureheal/healingballad/heal),
  buff (arcaneshield/shadowstep/inspire), utility (entangle/rally)
- Cooldown tracking per socket (in-memory Map)
- MP/EP cost validation; class-access validation via CLASS_SKILL_MAP
- useSkill(io, socket, skillId, targetId) public API
- getCharSkills(class) for listing

combatManager.js:
- setNpcHp(npcId, hp) — allows skills to update NPC HP without triggering full attackNpc
- handleNpcDeathExternal() — allows skills to trigger death logic properly

skills.js handler: 'use' and 'skills' socket events → Char.Skills GMCP packet

game.html:
- use <skill_id> [target_id] and skills/sk commands
- Char.Skills GMCP handler → renderSkillList
- Skills section in equip tab with use button per skill
- Auto-loads skills on Char.Status (login)
- Char.Equipment + skills both load after play event

https://claude.ai/code/session_016DHRqhzhmtcHRRSeBjbFkp
raceStats.js: atk_bonus per class (blademaster +5, magi -3, occultist -4, etc.)

game.html:
- Minimap: 80×80px Phaser overlay in canvas bottom-right showing current room
  exits as directional vectors with colored dots (locked=red, normal=blue)
- Gold display: ⬡ gold value in vitals bar; auto-increments on Combat.Kill
- Skills tab: auto-loads skills on login via 'skills' socket event
- use <skill_id> [target_id] command; skills/sk shortcut
- Char.Skills GMCP handler → renderSkillList with per-skill use buttons
- Char.XP: shows gold gained in log message
- Command help updated with all new commands

https://claude.ai/code/session_016DHRqhzhmtcHRRSeBjbFkp
- world.js: remove dead require() call from the 501 stub NPC REST endpoint
- game.html: item template type select now shows valid DB types only
  (weapon/armor/clothing/consumable/tool/furniture/misc)
  Previously included key/currency/material which would fail the DB CHECK constraint

https://claude.ai/code/session_016DHRqhzhmtcHRRSeBjbFkp
Adds 13 new classes (alchemist, apostate, depthswalker, infernal, jester,
pariah, psion, runewarden, sentinel, serpent, shaman, sylvan, unnameable)
drawn from the official Achaea class roster. Each class gets unique
hp/mp/ep/atk_bonus stats, lore text, and 2-3 class-specific active skills
(39 new skills total). Updates character creation class grid in the client.

https://claude.ai/code/session_016DHRqhzhmtcHRRSeBjbFkp
- seed.js: auto-seeds a playable starting world on first boot —
  8 rooms (Taroth city hub + Darkwood danger zone), 10 NPCs (friendly
  + combatants), 8 item templates, all items pickupable
- server.js: calls seedWorld() after ensureVoidRoom()
- auth.js: new characters start in Town Square instead of The Void
- .env.example: documents all env vars including ADMIN_PASSWORD
- README.md: full ELI5 run guide, command reference, class table,
  world map, troubleshooting

https://claude.ai/code/session_016DHRqhzhmtcHRRSeBjbFkp
Allows the pixel-mmo folder to be extracted as its own repo.
npm install and npm start work from the pixel-mmo root directly.

https://claude.ai/code/session_016DHRqhzhmtcHRRSeBjbFkp
Lazy-load the OpenAI client only when actually generating an image,
so the server starts cleanly without API keys configured.

https://claude.ai/code/session_016DHRqhzhmtcHRRSeBjbFkp
- Register form now collects character name, password, email, race, and
  class in one step — no separate character-creation screen for new accounts
- Server creates account + character atomically and returns character_id
- Client calls playAs(character_id) immediately after register, bypassing
  the character select screen entirely
- Login also auto-skips character select when the account has exactly one character
- Auth box widened to 480 px with scroll to accommodate the new pickers

https://claude.ai/code/session_016DHRqhzhmtcHRRSeBjbFkp
Layout fix:
- Add min-height:0 to .screen, #playArea, #canvasCol and #logArea so
  the flex column properly constrains content and never clips #cmdBar
- cmd bar: 2px border, var(--surface2) background, brighter placeholder
  text so it stands out clearly at the bottom of the screen

World agent (admin panel → Agent tab):
- New server/services/worldAgent.js: calls Claude Opus to plan a
  complete area (rooms + exits + NPCs + items) from one prompt, then
  auto-commits everything in a single transaction — no preview step
- admin:agent:run socket event wired through admin.js with per-step
  progress messages streamed back to the client
- Admin.Agent GMCP module added for the final result packet
- Agent tab in the admin panel: prompt, direction, room count, NPC/item
  toggles, live progress log, and a summary on completion

https://claude.ai/code/session_016DHRqhzhmtcHRRSeBjbFkp
Pixel art image generation:
- rooms.image_url column added via migration (room_image_v1)
- sendRoomInfo now includes image_url; client shows it below room desc
  as a pixelated banner image when present
- World agent generates a DALL-E 3 pixel art cover image for the
  entry room after committing the area (skips gracefully if no key)
- Admin Room tab: "Generate Pixel Art" button triggers on-demand image
  generation for whatever room the admin is standing in; refreshes all
  connected clients in that room immediately

Admin panel toggle:
- Panel is now a fixed slide-in overlay (translateX) instead of a
  third column that overflows off-screen on normal monitors
- "PANEL" button in the vitals bar opens/closes it; ✕ closes it too
- toggleAdminPanel() auto-calls adminLook() when opening

Dig command template / inline dig command:
- "Dig Template" button in admin Room tab pastes a ready-to-edit
  dig command into the chat bar with field hints printed to the log
- dig command now parseable directly from the chat bar:
  dig <dir> name=.../terrain=.../desc=.../light=.../safe=0|1/indoor=0|1

https://claude.ai/code/session_016DHRqhzhmtcHRRSeBjbFkp
Replace git clone URL and path that pointed at the svof monorepo with
standalone pixel-mmo repo coordinates.

https://claude.ai/code/session_016DHRqhzhmtcHRRSeBjbFkp
Image generation:
- Rooms: world agent now generates pixel art for ALL new rooms (up to 4)
  in parallel rather than only the entry room; each uses its own
  room-specific prompt for a unique image
- NPC portraits: new npcs.image_url column (npc_portrait_v1 migration);
  agent generates portraits for every NPC it places, also in parallel
- Portrait 🎨 button on each NPC in the sidebar (admin only) triggers
  on-demand portrait regeneration via admin:npc:genimage
- is_combatant and image_url now included in Room.Info NPC packet so
  the client can show hostile indicators and portrait images correctly
- Entry room cover image previewed in the Agent result panel after run

World agent — richer output:
- Planning prompt now asks for area lore (stored as entry room long_desc),
  quest-flavored NPC dialogue, varied NPC archetypes (quest, merchant,
  creature, etc.), and items tied thematically to the lore
- New expandArea() function: queries connected rooms (names, terrain,
  NPC/item counts) and feeds that as context so expansions are thematically
  coherent with what already exists
- admin:agent:expand socket event wired through admin.js

Agent tab UI:
- Mode toggle: "New Area" vs "Expand" — switches the socket event,
  adjusts default room count, and updates the description label
- Lore excerpt shown in the result summary after completion
- Entry room cover image previewed inline in the panel

https://claude.ai/code/session_016DHRqhzhmtcHRRSeBjbFkp
…ization

- Replace flat rectangle self-sprite with 3-part pixel art character
  (race-tinted head + class/armor-colored body + legs)
- Weapon shape drawn to the right of the body based on equipped mainhand
  (sword, dagger, staff, axe, mace, bow shapes in Phaser Graphics)
- Other players rendered with race-appropriate skin tone sprites
- Race skin palette (10 races) and class body accent palette (23 classes)
- computeAppearance() derives appearance from equipment map
- Sprite auto-updates on Char.Status and Char.Equipment GMCP events
- Seed item templates gain visual attributes (weapon_type, armor_type, color)
  so equipped gear immediately changes how the character looks

https://claude.ai/code/session_016DHRqhzhmtcHRRSeBjbFkp
Admins see a ✏ button on every NPC in the room. Clicking it fetches
the full NPC record (including dialogue and combat stats not normally
sent to clients) and opens a comprehensive edit modal:

- Basic Info: name, title, description, race, role
- Combatant toggle: shows/hides HP, attack, armor, XP reward,
  gold drop, and respawn-time fields
- Dialogue editor: add/remove keyword-response entries inline,
  keywords entered as comma-separated values
- Delete NPC button (with confirmation)
- Save emits admin:npc:update; Room.Npcs broadcast refreshes
  the NPC list for all players in the room immediately

Server:
- npcManager.updateNpc() — atomic field + dialogue update
- admin:npc:get → Admin.Npc.Data packet with full NPC record
- admin:npc:update → validates, persists, broadcasts Room.Npcs updated
- Room.Npcs handler gains 'updated' delta on the client

https://claude.ai/code/session_016DHRqhzhmtcHRRSeBjbFkp
Admins and developers are presented as race "immortal" across all
outward-facing packets — Char.Status, Room.Info player list, and
Room.Players enter broadcasts — while their real race is preserved
in the DB for mechanical purposes.

Client sprite gains an immortal appearance:
- Golden aura glow behind the body
- Halo ring floating above the head
- Golden body color default (overridden by equipped armor)
- Pale gold skin tone distinct from all mortal races

https://claude.ai/code/session_016DHRqhzhmtcHRRSeBjbFkp
Standalone Canvas 2D preview of all character sprite variants —
immortal (with halo/aura), mortal races, and weapon shapes.
Open directly in a browser, no server required.

https://claude.ai/code/session_016DHRqhzhmtcHRRSeBjbFkp
- Bare gallery: all 11 races with skin swatch + hex + description
- Typical class: each race with lore-appropriate class, weapon, terrain
- Immortal variants: 6 combos (bare, sword, staff, axe, armoured, robed)
- Side-by-side: all races as warrior + iron sword for direct comparison

https://claude.ai/code/session_016DHRqhzhmtcHRRSeBjbFkp
Each race now has distinct proportions and visual features:
- Elf: pointed ears (triangle geometry), long side hair, taller/slender
- Dwarf: beard below chin, wider/shorter body, stocky legs
- Orc: lower tusks, heavy brow ridge, wide frame
- Troll: massive build, thick neck, stubble detail
- Undead: hollow red eye sockets, gaunt cheek shadows, rib suggestion
- Merfolk: horizontal fin ears, fish tail with scale shimmer (no legs)
- Celestial: ethereal glow aura, flowing side hair
- Gnome: big eyes with whites, tiny build, colorful hair tuft
- Halfling: rosy cheeks, curly hair, small frame
- Immortal: golden radial aura, halo ring
- All: boot color on leg bases, belt/shoulder body detail, improved
  weapon rendering (blade highlight, orb glint, arrow nocked on bow)

https://claude.ai/code/session_016DHRqhzhmtcHRRSeBjbFkp
4x zoom made each card 288x312px display, overflowing the viewport
horizontally and breaking page scroll. 3x (216x234px per card) fits
comfortably on typical screens.

https://claude.ai/code/session_016DHRqhzhmtcHRRSeBjbFkp
Replaces the flat coloured rectangle sprites with a full
outlined+shaded chibi character system inspired by Pixel Knights /
Drakantos aesthetics:

- _pSRect / _pSArc: outlined 3-tone shaded primitives (dark outline,
  shadow fill, base fill, highlight strip) used throughout
- _tintInt / _tintStr / _hexInt: colour math helpers
- _drawBackground: terrain-aware scene background — gradient wall,
  brick/tree/grid/cave/wave overlays, 8-px tiled floor with grout lines
- _drawCharSprite: full chibi sprite at scale=2 for self — 8×8 head,
  pauldrons, belt+buckle, centre-line, race-specific hair/eyes/features
  (elf pointed ears, dwarf beard, orc tusks, troll thick neck, undead
  hollow eyes, halfling rosy cheeks, merfolk fin+tail, celestial glow,
  immortal halo+aura); bottom-anchored ground coordinate
- _drawWeapon: detailed sword/dagger/staff/axe/mace/bow with blade
  edge highlights, orb shading, bowstring via lineStyle
- _drawSimplePlayerSprite: outlined chibi for other players
- WorldScene: uses bgGfx Graphics (replaces bg Rectangle + decorGroup),
  redrawn on every room change; self sprite at scale=2 ground=H/2+20
- sprite-preview.html: standalone visual reference for all 11 races

https://claude.ai/code/session_016DHRqhzhmtcHRRSeBjbFkp
Full pixel art engine using HSL hue-shifted shading, pillow-outlined
rects/circles, ambient occlusion at joints, cast shadow ellipses,
and per-race face detail (eyes, mouth, tusks, beard, glow, halo/aura,
scales, crest, leaf ears, frog face, cave-adapted eyes).

Races: human, elf, dwarf, gnome, halfling, orc, troll, undead,
merfolk, celestial, immortal + original set: xoran, mhun, grook, sylvari.
Classes: warrior, mage, rogue, ranger, cleric, monk with distinct
weapons (sword, staff, dagger, bow, mace, none).
Terrain backgrounds: plains, forest, dungeon, ocean, cave, void.

https://claude.ai/code/session_016DHRqhzhmtcHRRSeBjbFkp
ZOOM=3 caused canvas to display at 288px inside a 110px card.
ZOOM=2 fixes layout (192px canvas, 210px card) and also prevents
hair from clipping above the top of the 32px logical drawing area.

https://claude.ai/code/session_016DHRqhzhmtcHRRSeBjbFkp
Each race card now shows ♂ and ♀ side by side (420px wide card).
Female differences: narrower torso (bodyW-2), long flowing hair with
strands below neckline, eyelash marks at outer eye corners, defined
3-row lips, subtle cheek blush on all non-hollow-eyed races.

https://claude.ai/code/session_016DHRqhzhmtcHRRSeBjbFkp
claude added 4 commits May 31, 2026 03:58
Complete visual overhaul away from chibi proportions:
- 7:1 head-to-body ratio with anatomically realistic layout
- 96x160 logical canvas (2x display) for high-resolution detail
- 4-5 tone color ramps with vGrad/hGrad smooth shading bands
- Thin silhouette outlines only (no heavy internal borders)
- Detailed faces: iris/pupil/catchlight, shaped brows, lips, cheeks
- Tapered torso geometry, pauldrons, belt/buckle, armor detail lines
- Female: bust shaping, arched brows, eyelashes, defined lips, longer hair
- Race features use higher-res detail: scales, crest, fin-ears, leaf-ears,
  slit pupils, large eyes, tusk geometry, beard braids, throat pouch
- Weapons: fuller + pommel arc sword, orb-glow staff, bearded axe, flanged mace

https://claude.ai/code/session_016DHRqhzhmtcHRRSeBjbFkp
- Add viewport meta tag
- Replace fixed 420px card width with CSS grid auto-fill (minmax 380px)
- Canvas CSS: width 100% + aspect-ratio 96/160 so sprites scale to card width
- Remove hardcoded canvas.style.width/height from JS (CSS now owns sizing)
- Larger touch targets on controls (min-height 36px, padding 8px 12px)

Breakpoints: 1-col mobile, 2-col tablet, 3-col desktop.

https://claude.ai/code/session_016DHRqhzhmtcHRRSeBjbFkp
ZOOM=2 made the logical drawing area only 48x80px — the torso started
at y=-26 (off-screen). ZOOM=1 gives the full 96x160 logical space;
CSS aspect-ratio handles the 2x visual scale for display.

https://claude.ai/code/session_016DHRqhzhmtcHRRSeBjbFkp
Four rendering techniques side by side for Human Warrior:
- Style A: GBA/SNES retro (64x96, Bayer 4x4 dithering, strict palette)
- Style B: Modern indie (96x160, gradient bands, current approach)
- Style C: HD painterly (192x288, 16-20 gradient steps, detailed face)
- Style D: Pre-rendered 3D (128x200 ImageData, per-pixel Phong lighting
  with sphere/cylinder surface normals — most technically sophisticated)

Click any sprite to zoom 2x. Not committed to production style yet.

https://claude.ai/code/session_016DHRqhzhmtcHRRSeBjbFkp
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants