Keep several saves, with migration, atomic writes and import previews (Closes #37)
Savegames now lists independent save slots made with the loaded ROM: new game, continue, rename, duplicate, export and delete. The native database moves to IndexedDB version 2; the singleton save becomes "Save 1" inside the upgrade transaction, so it migrates exactly once and the old store is left untouched. Each write adds a generation and drops older ones in one transaction, keeping two records with CRC-32 checksums: a damaged newest record falls back to the previous one. Slots and records from a newer player are kept and never written. Imports are checked in a scratch world before anything changes and previewed with the trainer, progress, saved time, game data version and the slots of the same trainer; they go into a new save or replace one, whose previous record stays recoverable. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
7c12c81a27
commit
7d03f5c5ca
18 files changed
+2079
-56
No files matched your search
@@ -63,6 +63,7 @@ import {
|
||||
type DayTimerName,
|
||||
pageCues,
|
||||
type SoundCue,
|
||||
landmarkName,
|
||||
} from "../scripts/interpreter";
|
||||
import { initialMagikarpRecord, type MagikarpRecord } from "../scripts/lake-of-rage";
|
||||
import {
|
||||
@@ -126,6 +127,7 @@ import {
|
||||
type BattleSound,
|
||||
} from "../battle/battle";
|
||||
import { C } from "../battle/constants";
|
||||
import type { SlotSummary } from "../../storage/slots";
|
||||
import {
|
||||
DIRECTION_ORDER,
|
||||
VECTORS,
|
||||
@@ -845,6 +847,11 @@ export class GameWorld {
|
||||
this.initCallReceiveDelay();
|
||||
}
|
||||
|
||||
/** A new world on the same ROM, clock and random source. */
|
||||
fresh() {
|
||||
return new GameWorld(this.assets, this.now, this.random);
|
||||
}
|
||||
|
||||
get x() {
|
||||
return this.player.x;
|
||||
}
|
||||
@@ -4886,6 +4893,28 @@ export class GameWorld {
|
||||
|
||||
// ---------------------------------------------------------------- saves
|
||||
|
||||
/** The Savegames list entry for a save: the trainer, the landmark (the
|
||||
* backup map's in LANDMARK_SPECIAL rooms), play time, Johto badges and
|
||||
* caught count. */
|
||||
describe(save: NativeSave = this.save()): SlotSummary {
|
||||
let landmark = this.assets.map(save.map).landmark;
|
||||
if (landmark === OW.LANDMARK_SPECIAL && save.backupWarp)
|
||||
landmark = this.assets.map(save.backupWarp.map).landmark;
|
||||
let badges = 0;
|
||||
for (let bit = 0; bit < OW.NUM_JOHTO_BADGES; bit++)
|
||||
if (save.flags.includes(OW.ENGINE_ZEPHYRBADGE + bit)) badges++;
|
||||
return {
|
||||
player: save.name,
|
||||
playerId: save.playerId,
|
||||
place: landmarkName(this.assets.reader, landmark, this.host(PLAYER).text()),
|
||||
hours: save.gameTime.hours,
|
||||
minutes: save.gameTime.minutes,
|
||||
badges,
|
||||
caught: save.pokedex.caught.length,
|
||||
newGame: save.intro,
|
||||
};
|
||||
}
|
||||
|
||||
save(): NativeSave {
|
||||
// Incomplete interactions are replayed after reload; no partial quest writes.
|
||||
// The play time keeps counting through scenes, like GameTimer.
|
||||
|
||||
Reference in new issue
Block a user