Files
dflike/CLAUDE.md
T
2026-03-08 23:31:13 +00:00

5.8 KiB

CLAUDE.md

Project

Multiplayer NPC simulation game (Dwarf Fortress-inspired). Server-authoritative ECS architecture.

Structure

  • shared/ -- Types and constants (no runtime code)
  • server/ -- Node.js + Socket.io game server with ECS
  • client/ -- Phaser 3 + TypeScript renderer
  • chars/ -- Character sprite assets (do not modify)
  • docs/plans/ -- Design and implementation docs

Commands

  • npm install -- install all workspace dependencies
  • npm -w server run dev -- start server (port 3001)
  • npm -w server run test -- run server tests (338 tests)
  • npm -w server run test:watch -- run server tests in watch mode
  • npm -w client run dev -- start client dev server (port 3000)
  • npm -w client run build -- build client for production
  • npx -w shared tsc -- rebuild shared types (required after modifying shared/src/)

Tooling

  • ESM modules throughout ("type": "module")
  • Server: tsx (runtime), vitest (tests)
  • Client: vite (bundler), Phaser 3
  • Shared: compiled to shared/dist/ (auto-built)

Key Entry Points

  • server/src/main.ts -- server startup
  • server/src/game/GameLoop.ts -- tick loop orchestration
  • server/src/spawner/appearanceGenerator.ts -- NPC appearance + portrait feature generation
  • server/src/spawner/nameGenerator.ts -- NPC name generation
  • server/src/spawner/statGenerator.ts -- 3d6 stat generation for NPCs
  • server/src/systems/statHelpers.ts -- getEffectiveStat (base + modifiers, clamped 3-18)
  • server/src/systems/statModifierSystem.ts -- modifier decay and needs-based modifiers
  • server/src/systems/socialSystem.ts -- NPC social interaction phases and stat integration
  • server/src/systems/relationshipSystem.ts -- relationship delta calculation and despawn handling
  • server/src/systems/relationshipHelpers.ts -- classify, getPartnerCap, getFriendCap, getEffectiveClassification
  • server/src/config/relationshipConfig.ts -- tuning values for relationship system (config-driven)
  • server/src/systems/industrySystem.ts -- craft/build/gather decision tree
  • server/src/systems/craftingSystem.ts -- input consumption, timer, output production
  • server/src/systems/buildingSystem.ts -- structure creation with build progress
  • server/src/systems/dropoffSystem.ts -- stockpile item deposit
  • server/src/industry/recipeRegistry.ts -- recipe registry with seed recipes
  • server/src/config/industryConfig.ts -- tuning values for gathering, crafting, building
  • client/src/main.ts -- Phaser game bootstrap
  • client/src/scenes/GameScene.ts -- main game scene (camera/avatar/follow modes)
  • client/src/sprites/CharacterCompositor.ts -- sprite layer compositing
  • client/src/sprites/PortraitCompositor.ts -- portrait layer compositing (data URL output)
  • client/src/ui/NpcInfoPanel.ts -- follow-mode NPC info panel (HTML/CSS overlay)
  • shared/src/types.ts -- protocol types
  • shared/src/constants.ts -- game constants (incl. portrait slots, folder mapping)

Key Conventions

  • ECS components are plain data objects, systems are pure functions
  • Server owns all game state; clients are renderers
  • Character sprites are 48x48 per frame, 6 cols x 4 rows spritesheet layout
  • Compositing: skins + accessories layered in z-order, cached as single textures
  • Portraits: skin-specific layers composited client-side, exported as data URLs for HTML panel
  • Portrait assets are in chars/baseman/accessories/portraits/ organized by skin folder (skin01-07)
  • Sprite skin shape00_skinXX maps to portrait folder skin{XX+1}, base file skin{XX}.png
  • Shared types ensure client/server protocol agreement
  • Systems run in order: statModifier -> needsDecay -> npcBrain -> social -> narration -> relationship -> industry -> gathering -> crafting -> building -> dropoff -> movement -> thought
  • Follow mode shows EarthBound-styled NPC info panel with live-updating needs bars and stats
  • NPC stats use 3d6 generation (range 3-18, bell curve): 5 physical (STR/DEX/CON/INT/PER) + 5 personality (SOC/COU/CUR/EMP/TMP)
  • Stats have transient modifiers (needs-based permanent + event-based decaying); effective value = base + modifiers, clamped 3-18
  • Base stats are floats (drift slowly from experience); getEffectiveStat floors to int for gameplay use
  • Wire protocol sends effective (computed) stats only; modifiers stay server-side
  • Relationships: per-NPC Map<EntityId, RelationshipData> component, lazy-initialized on first encounter
  • Relationship values range -100 to 100, classified into tiers (Partner/Friend/Acquaintance/Stranger/Wary/Rival/Enemy/Nemesis)
  • Relationship deltas use diminishing returns and blended asymmetry (30% shared + 70% individual outcome)
  • Stats influence relationships: empathy (positive gain), temperament (negative loss), sociability (friend cap + bonus)
  • Partner cap: default 1, poly (2) requires sociability 15+ AND empathy 14+; friend cap scales with sociability
  • Despawned strong relationships (|value| >= 20) persist as memories; weak ones fade and get cleaned up
  • SocialSystem emits lastOutcome on SocialState; relationshipSystem consumes and clears it
  • NPC info panel has Status/Relations tabs; relationships tab shows tier-grouped sliders with colored markers
  • All relationship tuning values in server/src/config/relationshipConfig.ts (designed for future admin UI)
  • Industry system decides craft/build/gather based on inventory and existing structures
  • RecipeRegistry singleton holds seed recipes (craft_wooden_axe, craft_hammer, build_stockpile, build_workbench)
  • Crafting: 40 tick base, dexterity modifier; consumes inputs, produces output item
  • Building: creates structure entity with buildProgress 0→1; structures have type (stockpile/workshop) + subtype + inventory
  • After gathering, NPCs drop off items at nearest completed stockpile via 'dropoff' goal
  • Movement pauses during gathering, crafting, and building (same skip pattern)