From df499e2f71ebd70bf3bbef6849f9e02d847b293f Mon Sep 17 00:00:00 2001 From: Nexllon <75459029+Nexllon@users.noreply.github.com> Date: Tue, 14 May 2024 16:42:30 -0300 Subject: [PATCH] offline mode - adds daily run and fixes clear freezes (#834) * offline mode - adds daily run and fixes clear freezes * removed unused import --- src/data/daily-run.ts | 5 +++-- src/phases.ts | 29 ++++++++++++++++++++++++----- src/system/game-data.ts | 30 ++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 7 deletions(-) diff --git a/src/data/daily-run.ts b/src/data/daily-run.ts index 5371b87a6..c1a1206f3 100644 --- a/src/data/daily-run.ts +++ b/src/data/daily-run.ts @@ -13,14 +13,15 @@ export interface DailyRunConfig { } export function fetchDailyRunSeed(): Promise { - return new Promise(resolve => { + return new Promise((resolve, reject) => { Utils.apiFetch('daily/seed').then(response => { if (!response.ok) { resolve(null); return; } return response.text(); - }).then(seed => resolve(seed)); + }).then(seed => resolve(seed)) + .catch(err => reject(err)); }); } diff --git a/src/phases.ts b/src/phases.ts index 8aa179d35..123169021 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -289,7 +289,7 @@ export class TitlePhase extends Phase { } this.scene.sessionSlotId = slotId; - fetchDailyRunSeed().then(seed => { + const generateDaily = (seed: string) => { this.scene.gameMode = gameModes[GameModes.DAILY]; this.scene.setSeed(seed); @@ -332,9 +332,18 @@ export class TitlePhase extends Phase { this.scene.sessionPlayTime = 0; this.end(); }); - }).catch(err => { - console.error("Failed to load daily run:\n", err); - }); + }; + + // If Online, calls seed fetch from db to generate daily run. If Offline, generates a daily run based on current date. + if (!Utils.isLocal) { + fetchDailyRunSeed().then(seed => { + generateDaily(seed); + }).catch(err => { + console.error("Failed to load daily run:\n", err); + }); + } else { + generateDaily(btoa(new Date().toISOString().substring(0, 10))); + } }); } @@ -3612,10 +3621,20 @@ export class GameOverPhase extends BattlePhase { }); }); }; + + /* Added a local check to see if the game is running offline on victory + If Online, execute apiFetch as intended + If Offline, execute offlineNewClear(), a localStorage implementation of newClear daily run checks */ if (this.victory) { - Utils.apiFetch(`savedata/newclear?slot=${this.scene.sessionSlotId}`, true) + if (!Utils.isLocal) { + Utils.apiFetch(`savedata/newclear?slot=${this.scene.sessionSlotId}`, true) .then(response => response.json()) .then(newClear => doGameOver(newClear)); + } else { + this.scene.gameData.offlineNewClear(this.scene).then(result => { + doGameOver(result); + }); + } } else doGameOver(false); } diff --git a/src/system/game-data.ts b/src/system/game-data.ts index 7f6e1475b..5e942b4fa 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -759,6 +759,36 @@ export class GameData { }); } + /* Defines a localStorage item 'daily' to check on clears, offline implementation of savedata/newclear API + If a GameModes clear other than Daily is checked, newClear = true as usual + If a Daily mode is cleared, checks if it was already cleared before, based on seed, and returns true only to new daily clear runs */ + offlineNewClear(scene: BattleScene): Promise { + return new Promise(resolve => { + const sessionData = this.getSessionSaveData(scene); + const seed = sessionData.seed; + let daily: string[] = []; + + if (sessionData.gameMode == GameModes.DAILY) { + if (localStorage.hasOwnProperty('daily')) { + daily = JSON.parse(atob(localStorage.getItem('daily'))); + if (daily.includes(seed)) { + return resolve(false); + } else { + daily.push(seed); + localStorage.setItem('daily', btoa(JSON.stringify(daily))); + return resolve(true); + } + } else { + daily.push(seed); + localStorage.setItem('daily', btoa(JSON.stringify(daily))); + return resolve(true); + } + } else { + return resolve(true); + } + }); + } + tryClearSession(scene: BattleScene, slotId: integer): Promise<[success: boolean, newClear: boolean]> { return new Promise<[boolean, boolean]>(resolve => { if (bypassLogin) {