Imported from ai2-claw/stardew-living-rpg-mod (
AGENTS.md). Install upstream withnpx skills add ai2-claw/stardew-living-rpg-mod. Copyright stays with the author.
Repository Guidelines
This file provides guidance when working with code in this repository.
Project Overview
Stardew Living RPG is a SMAPI (Stardew Modding API) mod that adds a living RPG layer to Stardew Valley. The mod integrates with Player2 (an AI service) to create dynamic NPCs, economy systems, and quests while maintaining the cozy feel of vanilla Stardew Valley.
Core Design Philosophy: "Stardew, but alive" — not a different genre pasted on top. All systems should create meaningful but gentle consequences with warm, legible, low-friction UX.
Rules
Think Before Coding
- State assumptions explicitly; if uncertain, use the
AskUserQuestiontool rather than guess - When ambiguity exists, present multiple interpretations via
AskUserQuestion— don't pick silently - Push back if a simpler approach exists; stop and ask via
AskUserQuestionwhen confused
Simplicity First
- No features, abstractions, or error handling beyond what was asked
- No speculative "flexibility" or "configurability"
- If 200 lines could be 50, rewrite it
- Only create an abstraction if it's actually needed
Surgical Changes
- Touch only what you must; don't "improve" adjacent code, comments, or formatting
- Match existing style, even if you'd do it differently
- If you notice unrelated dead code, mention it — don't delete it
- Remove imports/variables/functions that YOUR changes made unused, not pre-existing dead code
Goal-Driven Execution
- Define verifiable success criteria before implementing
- Write or run tests first to confirm the change works
- Every action should trace back to the user's stated goal
General
- ALWAYS read and understand relevant files before proposing edits
- If critical info is needed and you suspect your knowledge may be outdated, fetch the latest docs via Context7 MCP first
- Before writing new code, check for existing related methods/classes and reuse them
- Prefer clear function/variable names over inline comments
- Don't use emojis
Localization / Encoding Safety
- Localization files must be stored as readable UTF-8 text with native characters on disk, for example Japanese, Chinese, Russian, Korean, and other target-language scripts
- Do NOT rewrite localization files into ASCII-escaped
\\uXXXXform - Do NOT accept mojibake, replacement
?, or mixed-encoding corruption in localization files - Console success, JSON parse success, and build success are NOT sufficient validation for non-ASCII localization edits
- After editing any file with non-ASCII text, ALWAYS reopen the exact file from disk and inspect the stored content itself
- The read pass must verify representative lines still contain real native characters on disk, not escaped sequences and not console-decoded stand-ins
- Decoded Python output, escaped previews, or command success logs do NOT count as the verification pass
- Do NOT use write paths that silently coerce Unicode; if a tool path is likely to corrupt non-ASCII text, stop and choose a UTF-8-safe path first
- Do NOT use
ensure_ascii=Trueor equivalent when writing hand-maintained localization assets - Never finish a localization task without a raw on-disk read pass of the edited file
Bash Guidelines
- Do NOT pipe output through
head,tail,less, ormore - Do NOT use
| head -n Xor| tail -n Xto truncate output — these cause buffering problems - Let commands complete fully, or use
--max-linesflags if the command supports them - For log monitoring, prefer reading files directly rather than piping through filters
- Run commands directly without pipes when possible
- Use command-specific flags to limit output (e.g.,
git log -n 10instead ofgit log | head -10) - Avoid chained pipes that can cause output to buffer indefinitely
When to Read Documentation
| Task | Read |
|---|---|
| Product direction, pillars, scope | ARCHITECTURE.md |
| State schemas, resolver pipeline, determinism | DATA_MODEL.md, EVENT_RESOLUTION.md |
| UX principles, interaction surfaces, diegetic design | IN_WORLD_UI_ARCHITECTURE.md |
| Recent changes history | CHANGELOG.md |
| Full doc index and reading order | DOC_INDEX.md |
Build and Development
Prerequisites
- .NET 6.0 SDK
- SMAPI installed with game path set as
SMAPI_PATHenvironment variable SMAPI_PATHmust point to directory containing:StardewModdingAPI.dll,Stardew Valley.dll,xTile.dll
Build Commands
# Build the mod (copies to Mods folder automatically)
dotnet build
# The post-build step copies output to:
# $(SMAPI_PATH)\Mods\StardewLivingRPG
Testing in Game
- Build the project
- Launch Stardew Valley via SMAPI
- Press console key (
~by default) to access SMAPI console for debug commands
Architecture
Service-Based Architecture
The mod follows a clean service-oriented pattern. ModEntry.cs is the central hub that:
- Manages all service lifetimes
- Handles SMAPI event subscriptions (DayStarted, DayEnding, SaveLoaded, Saving, etc.)
- Implements 40+ console commands for debugging
- Manages Player2 integration (AI NPC conversations)
Core Services (Systems/)
| Service | Responsibility |
|---|---|
DailyTickService |
Orchestrates daily simulation transitions |
EconomyService |
Dynamic crop pricing based on supply/demand/sentiment |
NpcIntentResolver |
Validates and applies AI-proposed world changes via command schema |
MarketBoardService |
UI for market information (K key) |
NewspaperService |
Daily newspaper generation from world state |
RumorBoardService |
Quest board system (L key) |
AnchorEventService |
Major scripted milestone events |
NpcMemoryService |
Persistent NPC memory across sessions |
TownMemoryService |
Shared town events and NPC awareness |
SalesIngestionService |
Tracks shipping bin sales at day end |
Player2 Integration (Integrations/Player2Client.cs)
The mod connects to Player2 API for dynamic NPC conversations:
- Base URL:
https://api.player2.game/v1(configurable) - Local auth fast-path:
http://localhost:4315/v1(Player2 desktop app) - NPC commands flow through
NpcIntentResolverfor validation - Implements exponential backoff for stream reconnection
- Maintains NPC sessions with grounding prompts
NPC Command Schema (NPC_COMMAND_SCHEMA.json)
AI can only propose 5 safe, deterministic commands:
propose_quest- Generate quests from validated templatesadjust_reputation- Modify NPC relationships (-10 to +10)shift_interest_influence- Town group influence (-5 to +5)apply_market_modifier- Temporary price changes (-15% to +15%)publish_rumor- Spread town information
All commands are validated against JSON schema with bounded deltas and cooldown gates.
State Management (State/)
SaveState- Top-level state with version field for migrationsEconomyState- Crop prices, demand factors, rolling 7-day sell volumesSocialState- NPC reputation, town interests/influenceQuestState- Active/completed/failed quests with template-based rewardsFactTable- Idempotency keys and fact locks to prevent duplicate AI intents- Deterministic serialization; versioned for save compatibility
UI Components (UI/)
| Component | Hotkey | Purpose |
|---|---|---|
MarketBoardMenu |
K | Shows crop prices, trends, demand outlook |
NewspaperMenu |
J | Daily town news and events |
RumorBoardMenu |
L | Quest board with AI-generated requests |
RequestJournalMenu |
O | Track active/completed quests |
NpcChatInputMenu |
- | Persistent NPC conversation interface |
Experience Modes
Configured via config.json → Mode:
cozy_canon(default) - Gentle changes, safe economy floorsstory_depth- Stronger consequences, heavier reputation effectsliving_chaos- High volatility economy, large world-state shifts
Critical Policies
Additive Dialogue Policy
NEVER replace original vanilla NPC dialogue. Mod dialogue must be additive follow-up only.
The policy is enforced by scripts/check-dialogue-policy.mjs which validates that key phrases exist in documentation. When adding NPC interaction code:
- Always show vanilla dialogue first via SMAPI
- After vanilla dialogue closes, optionally show a custom follow-up prompt
- Never intercept or replace standard NPC对话
The guardrail is codified in ModEntry.cs:~200 where _npcDialogueHookArmed tracks whether to show follow-up options.
Deterministic Safety
- All world changes must go through
NpcIntentResolveror service layers - AI outputs are first-class intents, never direct state writes
- Use bounded deltas: reputation ±10, influence ±5, market ±15%
- Fact locks prevent duplicate quest acceptance/resolution
- Cozy mode enforces daily caps and generous price floors (80% of base)
Diegetic UX Principle
From IN_WORLD_UI_ARCHITECTURE.md:
- Player should complete core loop without opening SMAPI console
- Actions happen through world objects, dialogue menus, and journals
- Console commands are developer tools only
- Use natural board-era labels ("New Postings"), avoid modern/digital phrasing
Debug Console Commands (Key Commands)
slrpg_debug_state Compact daily diagnostics snapshot
slrpg_p2_health Player2 connection one-line health summary
slrpg_intent_smoketest Run automated resolver QA with pass/fail
slrpg_demo_bootstrap Seed reproducible vertical-slice scenario
slrpg_open_board Open Market Board menu
slrpg_open_news Open latest newspaper
slrpg_open_rumors Open Town Request Board
slrpg_open_journal Open Request Journal
Full command list in ModEntry.cs:94-122 (40+ commands).
Documentation
DOC_INDEX.md- Reading order guide for all docsARCHITECTURE.md- Product direction, pillars, scopeDATA_MODEL.md- Authoritative save state schemasEVENT_RESOLUTION.md- Deterministic resolver pipelineIN_WORLD_UI_ARCHITECTURE.md- UX principles and interaction surfaces
Config Options (via config.json)
Key settings in Config/ModConfig.cs:
EnablePlayer2- Enable Player2 AI integrationPlayer2GameClientId- Your Player2 game client IDAutoConnectPlayer2OnLoad- Auto-connect on save loadPlayer2NpcRosterCsv- NPC roster for work requestsMaxUiGeneratedRequestsPerDay- Daily cap for AI-generated requestsStrictNpcTemplateValidation- Reject unknown quest templates (default: repair)
Save File Location
SMAPI save data stored at:
<Stardew Save Path>/StardewLivingRPG/<SaveName>/state.json
State is persisted via StateStore.cs using SMAPI's Helper.Data.