Add AI worldbuilding pipeline for pixel MMO - #1
Open
sdelo1185 wants to merge 34 commits into
Open
Conversation
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
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.