From b2990aaa15f8ef673ff9af7c5f72a7e84f8b2aa1 Mon Sep 17 00:00:00 2001 From: Sirz Benjie <142067137+SirzBenjie@users.noreply.github.com> Date: Thu, 14 Aug 2025 16:57:01 -0500 Subject: [PATCH] [Bug] [Beta] Fix renaming runs (#6268) Rename run name field, don't encrypt before updating --- package.json | 1 + pnpm-lock.yaml | 8 ++ src/account.ts | 71 ++++++++--------- .../api/pokerogue-session-savedata-api.ts | 8 +- src/system/game-data.ts | 79 +++++++++---------- src/ui/run-info-ui-handler.ts | 2 +- src/ui/save-slot-select-ui-handler.ts | 6 +- src/utils/data.ts | 16 ++-- 8 files changed, 96 insertions(+), 95 deletions(-) diff --git a/package.json b/package.json index d3494da677c..3f523ed5c3e 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "devDependencies": { "@biomejs/biome": "2.0.0", "@ls-lint/ls-lint": "2.3.1", + "@types/crypto-js": "^4.2.0", "@types/jsdom": "^21.1.7", "@types/node": "^22.16.5", "@vitest/coverage-istanbul": "^3.2.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 900be6fd76e..c3b58a60f48 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -48,6 +48,9 @@ importers: '@ls-lint/ls-lint': specifier: 2.3.1 version: 2.3.1 + '@types/crypto-js': + specifier: ^4.2.0 + version: 4.2.2 '@types/jsdom': specifier: ^21.1.7 version: 21.1.7 @@ -718,6 +721,9 @@ packages: '@types/cookie@0.6.0': resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} + '@types/crypto-js@4.2.2': + resolution: {integrity: sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==} + '@types/deep-eql@4.0.2': resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} @@ -2525,6 +2531,8 @@ snapshots: '@types/cookie@0.6.0': {} + '@types/crypto-js@4.2.2': {} + '@types/deep-eql@4.0.2': {} '@types/estree@1.0.8': {} diff --git a/src/account.ts b/src/account.ts index b01691ce940..c97721889ae 100644 --- a/src/account.ts +++ b/src/account.ts @@ -17,45 +17,42 @@ export function initLoggedInUser(): void { }; } -export function updateUserInfo(): Promise<[boolean, number]> { - return new Promise<[boolean, number]>(resolve => { - if (bypassLogin) { - loggedInUser = { - username: "Guest", - lastSessionSlot: -1, - discordId: "", - googleId: "", - hasAdminRole: false, - }; - let lastSessionSlot = -1; - for (let s = 0; s < 5; s++) { - if (localStorage.getItem(`sessionData${s ? s : ""}_${loggedInUser.username}`)) { - lastSessionSlot = s; - break; - } +export async function updateUserInfo(): Promise<[boolean, number]> { + if (bypassLogin) { + loggedInUser = { + username: "Guest", + lastSessionSlot: -1, + discordId: "", + googleId: "", + hasAdminRole: false, + }; + let lastSessionSlot = -1; + for (let s = 0; s < 5; s++) { + if (localStorage.getItem(`sessionData${s ? s : ""}_${loggedInUser.username}`)) { + lastSessionSlot = s; + break; } - loggedInUser.lastSessionSlot = lastSessionSlot; - // Migrate old data from before the username was appended - ["data", "sessionData", "sessionData1", "sessionData2", "sessionData3", "sessionData4"].map(d => { - const lsItem = localStorage.getItem(d); - if (lsItem && !!loggedInUser?.username) { - const lsUserItem = localStorage.getItem(`${d}_${loggedInUser.username}`); - if (lsUserItem) { - localStorage.setItem(`${d}_${loggedInUser.username}_bak`, lsUserItem); - } - localStorage.setItem(`${d}_${loggedInUser.username}`, lsItem); - localStorage.removeItem(d); - } - }); - return resolve([true, 200]); } - pokerogueApi.account.getInfo().then(([accountInfo, status]) => { - if (!accountInfo) { - resolve([false, status]); - return; + loggedInUser.lastSessionSlot = lastSessionSlot; + // Migrate old data from before the username was appended + ["data", "sessionData", "sessionData1", "sessionData2", "sessionData3", "sessionData4"].forEach(d => { + const lsItem = localStorage.getItem(d); + if (lsItem && !!loggedInUser?.username) { + const lsUserItem = localStorage.getItem(`${d}_${loggedInUser.username}`); + if (lsUserItem) { + localStorage.setItem(`${d}_${loggedInUser.username}_bak`, lsUserItem); + } + localStorage.setItem(`${d}_${loggedInUser.username}`, lsItem); + localStorage.removeItem(d); } - loggedInUser = accountInfo; - resolve([true, 200]); }); - }); + return [true, 200]; + } + + const [accountInfo, status] = await pokerogueApi.account.getInfo(); + if (!accountInfo) { + return [false, status]; + } + loggedInUser = accountInfo; + return [true, 200]; } diff --git a/src/plugins/api/pokerogue-session-savedata-api.ts b/src/plugins/api/pokerogue-session-savedata-api.ts index 4ffb0a5d8da..39fa292f9f1 100644 --- a/src/plugins/api/pokerogue-session-savedata-api.ts +++ b/src/plugins/api/pokerogue-session-savedata-api.ts @@ -56,15 +56,15 @@ export class PokerogueSessionSavedataApi extends ApiBase { /** * Update a session savedata. - * @param params The {@linkcode UpdateSessionSavedataRequest} to send - * @param rawSavedata The raw savedata (as `string`) + * @param params - The request to send + * @param rawSavedata - The raw, unencrypted savedata * @returns An error message if something went wrong */ - public async update(params: UpdateSessionSavedataRequest, rawSavedata: string) { + public async update(params: UpdateSessionSavedataRequest, rawSavedata: string): Promise { try { const urlSearchParams = this.toUrlSearchParams(params); - const response = await this.doPost(`/savedata/session/update?${urlSearchParams}`, rawSavedata); + const response = await this.doPost(`/savedata/session/update?${urlSearchParams}`, rawSavedata); return await response.text(); } catch (err) { console.warn("Could not update session savedata!", err); diff --git a/src/system/game-data.ts b/src/system/game-data.ts index a1213990053..90cbf6e18cc 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -128,7 +128,8 @@ export interface SessionSaveData { battleType: BattleType; trainer: TrainerData; gameVersion: string; - runNameText: string; + /** The player-chosen name of the run */ + name: string; timestamp: number; challenges: ChallengeData[]; mysteryEncounterType: MysteryEncounterType | -1; // Only defined when current wave is ME, @@ -986,51 +987,45 @@ export class GameData { } async renameSession(slotId: number, newName: string): Promise { - return new Promise(async resolve => { - if (slotId < 0) { - return resolve(false); - } - const sessionData: SessionSaveData | null = await this.getSession(slotId); + if (slotId < 0) { + return false; + } + if (newName === "") { + return true; + } + const sessionData: SessionSaveData | null = await this.getSession(slotId); - if (!sessionData) { - return resolve(false); - } + if (!sessionData) { + return false; + } - if (newName === "") { - return resolve(true); - } + sessionData.name = newName; + // update timestamp by 1 to ensure the session is saved + sessionData.timestamp += 1; + const updatedDataStr = JSON.stringify(sessionData); + const encrypted = encrypt(updatedDataStr, bypassLogin); + const secretId = this.secretId; + const trainerId = this.trainerId; - sessionData.runNameText = newName; - const updatedDataStr = JSON.stringify(sessionData); - const encrypted = encrypt(updatedDataStr, bypassLogin); - const secretId = this.secretId; - const trainerId = this.trainerId; + if (bypassLogin) { + localStorage.setItem( + `sessionData${slotId ? slotId : ""}_${loggedInUser?.username}`, + encrypt(updatedDataStr, bypassLogin), + ); + return true; + } - if (bypassLogin) { - localStorage.setItem( - `sessionData${slotId ? slotId : ""}_${loggedInUser?.username}`, - encrypt(updatedDataStr, bypassLogin), - ); - resolve(true); - return; - } - pokerogueApi.savedata.session - .update({ slot: slotId, trainerId, secretId, clientSessionId }, encrypted) - .then(error => { - if (error) { - console.error("Failed to update session name:", error); - resolve(false); - } else { - localStorage.setItem(`sessionData${slotId ? slotId : ""}_${loggedInUser?.username}`, encrypted); - updateUserInfo().then(success => { - if (success !== null && !success) { - return resolve(false); - } - }); - resolve(true); - } - }); - }); + const response = await pokerogueApi.savedata.session.update( + { slot: slotId, trainerId, secretId, clientSessionId }, + updatedDataStr, + ); + + if (response) { + return false; + } + localStorage.setItem(`sessionData${slotId ? slotId : ""}_${loggedInUser?.username}`, encrypted); + const success = await updateUserInfo(); + return !(success !== null && !success); } loadSession(slotId: number, sessionData?: SessionSaveData): Promise { diff --git a/src/ui/run-info-ui-handler.ts b/src/ui/run-info-ui-handler.ts index 8facd8e73b1..572b8ccf560 100644 --- a/src/ui/run-info-ui-handler.ts +++ b/src/ui/run-info-ui-handler.ts @@ -208,7 +208,7 @@ export class RunInfoUiHandler extends UiHandler { headerText.setOrigin(0, 0); headerText.setPositionRelative(headerBg, 8, 4); this.runContainer.add(headerText); - const runName = addTextObject(0, 0, this.runInfo.runNameText, TextStyle.WINDOW); + const runName = addTextObject(0, 0, this.runInfo.name, TextStyle.WINDOW); runName.setOrigin(0, 0); runName.setPositionRelative(headerBg, 60, 4); this.runContainer.add(runName); diff --git a/src/ui/save-slot-select-ui-handler.ts b/src/ui/save-slot-select-ui-handler.ts index 52e145e6439..e9f9c5a0038 100644 --- a/src/ui/save-slot-select-ui-handler.ts +++ b/src/ui/save-slot-select-ui-handler.ts @@ -377,7 +377,7 @@ export class SaveSlotSelectUiHandler extends MessageUiHandler { "select_cursor_highlight_thick", undefined, 294, - this.sessionSlots[prevSlotIndex ?? 0]?.saveData?.runNameText ? 50 : 60, + this.sessionSlots[prevSlotIndex ?? 0]?.saveData?.name ? 50 : 60, 6, 6, 6, @@ -553,10 +553,10 @@ class SessionSlot extends Phaser.GameObjects.Container { } async setupWithData(data: SessionSaveData) { - const hasName = data?.runNameText; + const hasName = data?.name; this.remove(this.loadingLabel, true); if (hasName) { - const nameLabel = addTextObject(8, 5, data.runNameText, TextStyle.WINDOW); + const nameLabel = addTextObject(8, 5, data.name, TextStyle.WINDOW); this.add(nameLabel); } else { const fallbackName = this.decideFallback(data); diff --git a/src/utils/data.ts b/src/utils/data.ts index 932ea38d504..6580ecf2ee9 100644 --- a/src/utils/data.ts +++ b/src/utils/data.ts @@ -45,17 +45,17 @@ export function deepMergeSpriteData(dest: object, source: object) { } export function encrypt(data: string, bypassLogin: boolean): string { - return (bypassLogin - ? (data: string) => btoa(encodeURIComponent(data)) - : (data: string) => AES.encrypt(data, saveKey))(data) as unknown as string; // TODO: is this correct? + if (bypassLogin) { + return btoa(encodeURIComponent(data)); + } + return AES.encrypt(data, saveKey).toString(); } export function decrypt(data: string, bypassLogin: boolean): string { - return ( - bypassLogin - ? (data: string) => decodeURIComponent(atob(data)) - : (data: string) => AES.decrypt(data, saveKey).toString(enc.Utf8) - )(data); + if (bypassLogin) { + return decodeURIComponent(atob(data)); + } + return AES.decrypt(data, saveKey).toString(enc.Utf8); } // the latest data saved/loaded for the Starter Preferences. Required to reduce read/writes. Initialize as "{}", since this is the default value and no data needs to be stored if present.