Persistence
CatalystEngine uses the Snapshot pattern: save() exports a minimal state as pure JSON, and load() restores it. No derived state is saved — anything that can be computed is recomputed.
What gets saved
engine.save() produces an IEngineSaveState:
interface IEngineSaveState {
version: string;
timestamp: number;
experience: {
currentLevel: number;
currentXP: number;
};
stats: {
baseValues: Record<string, number>; // only the BASE values
};
skills: {
unspentPoints: number;
unlockedSkills: Record<string, number>; // id → level
};
}Note what is not there: no final stat value, no active modifier, no XP threshold. These are all derived data that the engine reconstructs.
Why save only the minimum
- Small files: ideal for
LocalStorageor a database column. - Robustness against balancing changes: if you change the XP curve or the values of the skills' passive modifiers, old saves remain valid — the numbers are recomputed with the new rules.
- No inconsistency: it is impossible to save a "final" state that does not match the current rules.
Saving and restoring
// Save
const save = engine.save();
localStorage.setItem('partita', JSON.stringify(save));
// Load
const raw = localStorage.getItem('partita');
if (raw) {
engine.load(JSON.parse(raw) as IEngineSaveState);
}What load() does
The restore:
- resets the
ExperienceManager's current level and XP; - reapplies the base values to the
StatManager(importState); - reconstructs the unlocked skills and re-injects the passive modifiers into the stats;
- re-emits a
LEVEL_UPevent (withlevelsGained: 0) to give the UI a chance to resync to the current values.
Important
load() reapplies the base values to the stats already existing in the engine. Create the engine with the same starting stat configuration before calling load(), then restore the snapshot.
// 1. create the engine with the initial config
const engine = new CatalystEngine(
{ hp: 100, attack: 10, defense: 5 },
{ type: 'EXPONENTIAL', baseXP: 100, multiplier: 1.5 }
);
// 2. (if the skill tree uses passive modifiers) load it before load
engine.skills.loadSkillTree(skillTreeJson);
// 3. restore the snapshot
engine.load(save);Try it
Build up a state (XP and a skill), press Save and look at the JSON snapshot: it contains only base, level and skills — no final values nor transient modifiers. Then Reset clears the live engine, and Load restores everything, re-injecting the skill's passive modifiers (the ATK goes back to its upgraded value).