Compare commits

..

1 Commits

Author SHA1 Message Date
fabske0
16d6030434
Merge 1b57ee0959 into ee4950633e 2025-08-14 22:17:35 +02:00
8 changed files with 96 additions and 97 deletions

View File

@ -29,7 +29,6 @@
"devDependencies": { "devDependencies": {
"@biomejs/biome": "2.0.0", "@biomejs/biome": "2.0.0",
"@ls-lint/ls-lint": "2.3.1", "@ls-lint/ls-lint": "2.3.1",
"@types/crypto-js": "^4.2.0",
"@types/jsdom": "^21.1.7", "@types/jsdom": "^21.1.7",
"@types/node": "^22.16.5", "@types/node": "^22.16.5",
"@vitest/coverage-istanbul": "^3.2.4", "@vitest/coverage-istanbul": "^3.2.4",

View File

@ -48,9 +48,6 @@ importers:
'@ls-lint/ls-lint': '@ls-lint/ls-lint':
specifier: 2.3.1 specifier: 2.3.1
version: 2.3.1 version: 2.3.1
'@types/crypto-js':
specifier: ^4.2.0
version: 4.2.2
'@types/jsdom': '@types/jsdom':
specifier: ^21.1.7 specifier: ^21.1.7
version: 21.1.7 version: 21.1.7
@ -721,9 +718,6 @@ packages:
'@types/cookie@0.6.0': '@types/cookie@0.6.0':
resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} 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': '@types/deep-eql@4.0.2':
resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==}
@ -2531,8 +2525,6 @@ snapshots:
'@types/cookie@0.6.0': {} '@types/cookie@0.6.0': {}
'@types/crypto-js@4.2.2': {}
'@types/deep-eql@4.0.2': {} '@types/deep-eql@4.0.2': {}
'@types/estree@1.0.8': {} '@types/estree@1.0.8': {}

View File

@ -17,42 +17,45 @@ export function initLoggedInUser(): void {
}; };
} }
export async function updateUserInfo(): Promise<[boolean, number]> { export function updateUserInfo(): Promise<[boolean, number]> {
if (bypassLogin) { return new Promise<[boolean, number]>(resolve => {
loggedInUser = { if (bypassLogin) {
username: "Guest", loggedInUser = {
lastSessionSlot: -1, username: "Guest",
discordId: "", lastSessionSlot: -1,
googleId: "", discordId: "",
hasAdminRole: false, googleId: "",
}; hasAdminRole: false,
let lastSessionSlot = -1; };
for (let s = 0; s < 5; s++) { let lastSessionSlot = -1;
if (localStorage.getItem(`sessionData${s ? s : ""}_${loggedInUser.username}`)) { for (let s = 0; s < 5; s++) {
lastSessionSlot = s; if (localStorage.getItem(`sessionData${s ? s : ""}_${loggedInUser.username}`)) {
break; lastSessionSlot = s;
} break;
}
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.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 = accountInfo;
resolve([true, 200]);
}); });
return [true, 200]; });
}
const [accountInfo, status] = await pokerogueApi.account.getInfo();
if (!accountInfo) {
return [false, status];
}
loggedInUser = accountInfo;
return [true, 200];
} }

View File

@ -56,15 +56,15 @@ export class PokerogueSessionSavedataApi extends ApiBase {
/** /**
* Update a session savedata. * Update a session savedata.
* @param params - The request to send * @param params The {@linkcode UpdateSessionSavedataRequest} to send
* @param rawSavedata - The raw, unencrypted savedata * @param rawSavedata The raw savedata (as `string`)
* @returns An error message if something went wrong * @returns An error message if something went wrong
*/ */
public async update(params: UpdateSessionSavedataRequest, rawSavedata: string): Promise<string> { public async update(params: UpdateSessionSavedataRequest, rawSavedata: string) {
try { try {
const urlSearchParams = this.toUrlSearchParams(params); 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(); return await response.text();
} catch (err) { } catch (err) {
console.warn("Could not update session savedata!", err); console.warn("Could not update session savedata!", err);

View File

@ -128,8 +128,7 @@ export interface SessionSaveData {
battleType: BattleType; battleType: BattleType;
trainer: TrainerData; trainer: TrainerData;
gameVersion: string; gameVersion: string;
/** The player-chosen name of the run */ runNameText: string;
name: string;
timestamp: number; timestamp: number;
challenges: ChallengeData[]; challenges: ChallengeData[];
mysteryEncounterType: MysteryEncounterType | -1; // Only defined when current wave is ME, mysteryEncounterType: MysteryEncounterType | -1; // Only defined when current wave is ME,
@ -987,45 +986,51 @@ export class GameData {
} }
async renameSession(slotId: number, newName: string): Promise<boolean> { async renameSession(slotId: number, newName: string): Promise<boolean> {
if (slotId < 0) { return new Promise(async resolve => {
return false; if (slotId < 0) {
} return resolve(false);
if (newName === "") { }
return true; const sessionData: SessionSaveData | null = await this.getSession(slotId);
}
const sessionData: SessionSaveData | null = await this.getSession(slotId);
if (!sessionData) { if (!sessionData) {
return false; return resolve(false);
} }
sessionData.name = newName; if (newName === "") {
// update timestamp by 1 to ensure the session is saved return resolve(true);
sessionData.timestamp += 1; }
const updatedDataStr = JSON.stringify(sessionData);
const encrypted = encrypt(updatedDataStr, bypassLogin);
const secretId = this.secretId;
const trainerId = this.trainerId;
if (bypassLogin) { sessionData.runNameText = newName;
localStorage.setItem( const updatedDataStr = JSON.stringify(sessionData);
`sessionData${slotId ? slotId : ""}_${loggedInUser?.username}`, const encrypted = encrypt(updatedDataStr, bypassLogin);
encrypt(updatedDataStr, bypassLogin), const secretId = this.secretId;
); const trainerId = this.trainerId;
return true;
}
const response = await pokerogueApi.savedata.session.update( if (bypassLogin) {
{ slot: slotId, trainerId, secretId, clientSessionId }, localStorage.setItem(
updatedDataStr, `sessionData${slotId ? slotId : ""}_${loggedInUser?.username}`,
); encrypt(updatedDataStr, bypassLogin),
);
if (response) { resolve(true);
return false; return;
} }
localStorage.setItem(`sessionData${slotId ? slotId : ""}_${loggedInUser?.username}`, encrypted); pokerogueApi.savedata.session
const success = await updateUserInfo(); .update({ slot: slotId, trainerId, secretId, clientSessionId }, encrypted)
return !(success !== null && !success); .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);
}
});
});
} }
loadSession(slotId: number, sessionData?: SessionSaveData): Promise<boolean> { loadSession(slotId: number, sessionData?: SessionSaveData): Promise<boolean> {

View File

@ -208,7 +208,7 @@ export class RunInfoUiHandler extends UiHandler {
headerText.setOrigin(0, 0); headerText.setOrigin(0, 0);
headerText.setPositionRelative(headerBg, 8, 4); headerText.setPositionRelative(headerBg, 8, 4);
this.runContainer.add(headerText); this.runContainer.add(headerText);
const runName = addTextObject(0, 0, this.runInfo.name, TextStyle.WINDOW); const runName = addTextObject(0, 0, this.runInfo.runNameText, TextStyle.WINDOW);
runName.setOrigin(0, 0); runName.setOrigin(0, 0);
runName.setPositionRelative(headerBg, 60, 4); runName.setPositionRelative(headerBg, 60, 4);
this.runContainer.add(runName); this.runContainer.add(runName);

View File

@ -377,7 +377,7 @@ export class SaveSlotSelectUiHandler extends MessageUiHandler {
"select_cursor_highlight_thick", "select_cursor_highlight_thick",
undefined, undefined,
294, 294,
this.sessionSlots[prevSlotIndex ?? 0]?.saveData?.name ? 50 : 60, this.sessionSlots[prevSlotIndex ?? 0]?.saveData?.runNameText ? 50 : 60,
6, 6,
6, 6,
6, 6,
@ -553,10 +553,10 @@ class SessionSlot extends Phaser.GameObjects.Container {
} }
async setupWithData(data: SessionSaveData) { async setupWithData(data: SessionSaveData) {
const hasName = data?.name; const hasName = data?.runNameText;
this.remove(this.loadingLabel, true); this.remove(this.loadingLabel, true);
if (hasName) { if (hasName) {
const nameLabel = addTextObject(8, 5, data.name, TextStyle.WINDOW); const nameLabel = addTextObject(8, 5, data.runNameText, TextStyle.WINDOW);
this.add(nameLabel); this.add(nameLabel);
} else { } else {
const fallbackName = this.decideFallback(data); const fallbackName = this.decideFallback(data);

View File

@ -45,17 +45,17 @@ export function deepMergeSpriteData(dest: object, source: object) {
} }
export function encrypt(data: string, bypassLogin: boolean): string { export function encrypt(data: string, bypassLogin: boolean): string {
if (bypassLogin) { return (bypassLogin
return btoa(encodeURIComponent(data)); ? (data: string) => btoa(encodeURIComponent(data))
} : (data: string) => AES.encrypt(data, saveKey))(data) as unknown as string; // TODO: is this correct?
return AES.encrypt(data, saveKey).toString();
} }
export function decrypt(data: string, bypassLogin: boolean): string { export function decrypt(data: string, bypassLogin: boolean): string {
if (bypassLogin) { return (
return decodeURIComponent(atob(data)); bypassLogin
} ? (data: string) => decodeURIComponent(atob(data))
return AES.decrypt(data, saveKey).toString(enc.Utf8); : (data: string) => AES.decrypt(data, saveKey).toString(enc.Utf8)
)(data);
} }
// 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. // 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.