Gameplay — Save & Load
The gameplay layer uses localStorage for persistence. Save format v3 captures all player progression state: inventory, quests, equipment, XP, skills, world flags. Area-specific entity state (enemy HP, entity positions) is not saved — enemies reset on area reload.
API
// In your GameManager / game.js
gameMgr.saveGame(); // serialize and write to localStorage
gameMgr.loadGame(); // read from localStorage and restore state
// Check if a save exists
localStorage.getItem('dn_save_v3') !== null;
The key is dn_save_v3. Each game typically uses its own key — update the constant in your game’s game.js to avoid collision with other DN games.
What IS Saved (v3 format)
{
version: 3,
// Player progression
playerLevel: 4,
playerXP: 250,
skillPoints: 1,
learnedSkills: ['iron_skin', 'quick_strike'],
// Vitals
playerHp: 80,
playerMaxHp: 100,
playerShield: { current: 40, max: 80 },
// Equipment slots
equipment: {
mainhand: 'iron_sword',
offhand: 'iron_shield',
armor: null,
ring: null,
},
// Inventory
inventory: {
items: { iron_bar: 3, fish: 5, wheat_seeds: 2 },
currencies: { gold: 127 },
stats: { attack: 8, defense: 5 },
},
// Quest state
quests: {
goblin_bounty: {
status: 'turned_in',
currentPhase: 0,
objectives: [{ current: 3, count: 3 }],
},
fishing_quest: {
status: 'active',
currentPhase: 0,
objectives: [{ current: 2, count: 5 }],
},
},
// World flags (any key/value set via setFlag)
flags: {
bridge_rebuilt: true,
met_elder: true,
},
// Player position (tile coordinates)
position: { areaId: 'rpg_world', x: 15, y: 10 },
}
What Is NOT Saved
| Not saved | Why |
|---|---|
| Enemy HP + positions | Enemies reset when the area reloads — stateless design |
| Chest loot state | Chests (LootBehavior with oneTime: true) reset on reload unless you save the looted ID list explicitly |
| Farm plot growth progress | Growth uses Date.now() — if the area is reloaded, growth timer resets |
| Fishing pond state | Resets on unload |
| NPC dialogue node | Always starts at root on next open |
If you need any of the above to persist (e.g., a chest that stays empty after reload), save a flag: gameMgr.flags.set('chest_a1_looted', true) and check it in the area’s entity definition to spawn the chest in an already-looted state.
Save on Demand vs. Auto-Save
The framework does not auto-save — call gameMgr.saveGame() explicitly. Common save points:
- After quest turn-in
- After equipping an item
- After leveling up
- On area transition
- On a dedicated “Save” button in the pause menu
The pause menu’s Missions tab includes a Save button by default in the rpg-test reference implementation.
Multiple Save Slots
v3 uses a single slot. To support multiple slots, namespace the key:
const SAVE_KEY = `dn_save_v3_slot${slotIndex}`;
localStorage.setItem(SAVE_KEY, JSON.stringify(saveData));
Upgrade Path
When the save format changes, bump the version and add a migration function:
function loadGame() {
const raw = localStorage.getItem('dn_save_v3');
if (!raw) return;
const data = JSON.parse(raw);
if (data.version < 3) {
// migrate from v2 — e.g., shield was added in v3
data.playerShield = { current: 0, max: 0 };
data.version = 3;
}
// restore state from data...
}
Old saves with missing fields get safe defaults. Never break a player’s save on an update.