[Bug] Prevent an empty starterpreferences object from being saved (#6410)

* Prevent an empty starterpreferences object from being saved

* Fix ssui nullish coalescing

* Update src/utils/data.ts

Co-authored-by: Dean <69436131+emdeann@users.noreply.github.com>

---------

Co-authored-by: Dean <69436131+emdeann@users.noreply.github.com>
This commit is contained in:
Sirz Benjie 2025-08-26 01:48:55 -05:00 committed by GitHub
parent f0c24cd16e
commit c8a66b2e59
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 24 additions and 6 deletions

View File

@ -1828,9 +1828,9 @@ export class StarterSelectUiHandler extends MessageUiHandler {
// The persistent starter data to apply e.g. candy upgrades // The persistent starter data to apply e.g. candy upgrades
const persistentStarterData = globalScene.gameData.starterData[this.lastSpecies.speciesId]; const persistentStarterData = globalScene.gameData.starterData[this.lastSpecies.speciesId];
// The sanitized starter preferences // The sanitized starter preferences
let starterAttributes = this.starterPreferences[this.lastSpecies.speciesId]; let starterAttributes = this.starterPreferences[this.lastSpecies.speciesId] ?? {};
// The original starter preferences // The original starter preferences
const originalStarterAttributes = this.originalStarterPreferences[this.lastSpecies.speciesId]; const originalStarterAttributes = this.originalStarterPreferences[this.lastSpecies.speciesId] ?? {};
// this gets the correct pokemon cursor depending on whether you're in the starter screen or the party icons // this gets the correct pokemon cursor depending on whether you're in the starter screen or the party icons
if (!this.starterIconsCursorObj.visible) { if (!this.starterIconsCursorObj.visible) {
@ -3408,8 +3408,9 @@ export class StarterSelectUiHandler extends MessageUiHandler {
if (species) { if (species) {
const defaultDexAttr = this.getCurrentDexProps(species.speciesId); const defaultDexAttr = this.getCurrentDexProps(species.speciesId);
const defaultProps = globalScene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr); const defaultProps = globalScene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr);
// Bang is correct due to the `?` before variant
const variant = this.starterPreferences[species.speciesId]?.variant const variant = this.starterPreferences[species.speciesId]?.variant
? (this.starterPreferences[species.speciesId].variant as Variant) ? (this.starterPreferences[species.speciesId]!.variant as Variant)
: defaultProps.variant; : defaultProps.variant;
const tint = getVariantTint(variant); const tint = getVariantTint(variant);
this.pokemonShinyIcon.setFrame(getVariantIcon(variant)).setTint(tint); this.pokemonShinyIcon.setFrame(getVariantIcon(variant)).setTint(tint);

View File

@ -64,7 +64,7 @@ const StarterPrefers_DEFAULT: string = "{}";
let StarterPrefers_private_latest: string = StarterPrefers_DEFAULT; let StarterPrefers_private_latest: string = StarterPrefers_DEFAULT;
export interface StarterPreferences { export interface StarterPreferences {
[key: number]: StarterAttributes; [key: number]: StarterAttributes | undefined;
} }
// called on starter selection show once // called on starter selection show once
@ -74,10 +74,27 @@ export function loadStarterPreferences(): StarterPreferences {
localStorage.getItem(`starterPrefs_${loggedInUser?.username}`) || StarterPrefers_DEFAULT), localStorage.getItem(`starterPrefs_${loggedInUser?.username}`) || StarterPrefers_DEFAULT),
); );
} }
// called on starter selection clear, always
/**
* Check if an object has no properties of its own (its shape is `{}`)
* @param obj - Object to check
* @returns - Whether the object is bare
*/
export function isBareObject(obj: object): boolean {
for (const _ in obj) {
return false;
}
return true;
}
export function saveStarterPreferences(prefs: StarterPreferences): void { export function saveStarterPreferences(prefs: StarterPreferences): void {
const pStr: string = JSON.stringify(prefs); // Fastest way to check if an object has any properties (does no allocation)
if (isBareObject(prefs)) {
console.warn("Refusing to save empty starter preferences");
return;
}
// no reason to store `{}` (for starters not customized)
const pStr: string = JSON.stringify(prefs, (_, value) => (isBareObject(value) ? undefined : value));
if (pStr !== StarterPrefers_private_latest) { if (pStr !== StarterPrefers_private_latest) {
// something changed, store the update // something changed, store the update
localStorage.setItem(`starterPrefs_${loggedInUser?.username}`, pStr); localStorage.setItem(`starterPrefs_${loggedInUser?.username}`, pStr);