mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-05-07 17:05:18 +01:00
[Refactor] Re-implement save migration system (#5634)
This commit is contained in:
parent
0479b9dfcc
commit
1b79d1f832
7
package-lock.json
generated
7
package-lock.json
generated
@ -10,6 +10,7 @@
|
|||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@material/material-color-utilities": "^0.2.7",
|
"@material/material-color-utilities": "^0.2.7",
|
||||||
|
"compare-versions": "^6.1.1",
|
||||||
"crypto-js": "^4.2.0",
|
"crypto-js": "^4.2.0",
|
||||||
"i18next": "^24.2.2",
|
"i18next": "^24.2.2",
|
||||||
"i18next-browser-languagedetector": "^8.0.4",
|
"i18next-browser-languagedetector": "^8.0.4",
|
||||||
@ -3605,6 +3606,12 @@
|
|||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/compare-versions": {
|
||||||
|
"version": "6.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.1.tgz",
|
||||||
|
"integrity": "sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/concat-map": {
|
"node_modules/concat-map": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||||
|
@ -55,6 +55,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@material/material-color-utilities": "^0.2.7",
|
"@material/material-color-utilities": "^0.2.7",
|
||||||
|
"compare-versions": "^6.1.1",
|
||||||
"crypto-js": "^4.2.0",
|
"crypto-js": "^4.2.0",
|
||||||
"i18next": "^24.2.2",
|
"i18next": "^24.2.2",
|
||||||
"i18next-browser-languagedetector": "^8.0.4",
|
"i18next-browser-languagedetector": "^8.0.4",
|
||||||
|
6
src/@types/SessionSaveMigrator.ts
Normal file
6
src/@types/SessionSaveMigrator.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import type { SessionSaveData } from "#app/system/game-data";
|
||||||
|
|
||||||
|
export interface SessionSaveMigrator {
|
||||||
|
version: string;
|
||||||
|
migrate: (data: SessionSaveData) => void;
|
||||||
|
}
|
5
src/@types/SettingsSaveMigrator.ts
Normal file
5
src/@types/SettingsSaveMigrator.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export interface SettingsSaveMigrator {
|
||||||
|
version: string;
|
||||||
|
// biome-ignore lint/complexity/noBannedTypes: TODO - refactor settings
|
||||||
|
migrate: (data: Object) => void;
|
||||||
|
}
|
6
src/@types/SystemSaveMigrator.ts
Normal file
6
src/@types/SystemSaveMigrator.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import type { SystemSaveData } from "#app/system/game-data";
|
||||||
|
|
||||||
|
export interface SystemSaveMigrator {
|
||||||
|
version: string;
|
||||||
|
migrate: (data: SystemSaveData) => void;
|
||||||
|
}
|
@ -1,19 +1,104 @@
|
|||||||
import type { SessionSaveData, SystemSaveData } from "../game-data";
|
import type { SessionSaveMigrator } from "#app/@types/SessionSaveMigrator";
|
||||||
|
import type { SettingsSaveMigrator } from "#app/@types/SettingsSaveMigrator";
|
||||||
|
import type { SystemSaveMigrator } from "#app/@types/SystemSaveMigrator";
|
||||||
|
import type { SessionSaveData, SystemSaveData } from "#app/system/game-data";
|
||||||
|
import { compareVersions } from "compare-versions";
|
||||||
import { version } from "../../../package.json";
|
import { version } from "../../../package.json";
|
||||||
|
|
||||||
|
/*
|
||||||
|
// template for save migrator creation
|
||||||
|
// versions/vA_B_C.ts
|
||||||
|
|
||||||
|
// The version for each migrator should match the filename, ie: `vA_B_C.ts` -> `version: "A.B.C"
|
||||||
|
// This is the target version (aka the version we're ending up on after the migrators are run)
|
||||||
|
|
||||||
|
// The name for each migrator should match its purpose. For example, if you're fixing
|
||||||
|
// the ability index of a pokemon, it might be called `migratePokemonAbilityIndex`
|
||||||
|
|
||||||
|
const systemMigratorA: SystemSaveMigrator = {
|
||||||
|
version: "A.B.C",
|
||||||
|
migrate: (data: SystemSaveData): void => {
|
||||||
|
// migration code goes here
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const systemMigrators: Readonly<SystemSaveMigrator[]> = [systemMigratorA] as const;
|
||||||
|
|
||||||
|
const sessionMigratorA: SessionSaveMigrator = {
|
||||||
|
version: "A.B.C",
|
||||||
|
migrate: (data: SessionSaveData): void => {
|
||||||
|
// migration code goes here
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const sessionMigrators: Readonly<SessionSaveMigrator[]> = [sessionMigratorA] as const;
|
||||||
|
|
||||||
|
const settingsMigratorA: SettingsSaveMigrator = {
|
||||||
|
version: "A.B.C",
|
||||||
|
// biome-ignore lint/complexity/noBannedTypes: TODO - refactor settings
|
||||||
|
migrate: (data: Object): void => {
|
||||||
|
// migration code goes here
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const settingsMigrators: Readonly<SettingsSaveMigrator[]> = [settingsMigratorA] as const;
|
||||||
|
*/
|
||||||
|
|
||||||
|
// --- vA.B.C PATCHES --- //
|
||||||
|
// import * as vA_B_C from "./versions/vA_B_C";
|
||||||
|
|
||||||
// --- v1.0.4 (and below) PATCHES --- //
|
// --- v1.0.4 (and below) PATCHES --- //
|
||||||
import * as v1_0_4 from "./versions/v1_0_4";
|
import * as v1_0_4 from "./versions/v1_0_4";
|
||||||
|
|
||||||
// --- v1.1.0 PATCHES --- //
|
|
||||||
import * as v1_1_0 from "./versions/v1_1_0";
|
|
||||||
|
|
||||||
// --- v1.7.0 PATCHES --- //
|
// --- v1.7.0 PATCHES --- //
|
||||||
import * as v1_7_0 from "./versions/v1_7_0";
|
import * as v1_7_0 from "./versions/v1_7_0";
|
||||||
|
|
||||||
// --- v1.8.3 PATCHES --- //
|
// --- v1.8.3 PATCHES --- //
|
||||||
import * as v1_8_3 from "./versions/v1_8_3";
|
import * as v1_8_3 from "./versions/v1_8_3";
|
||||||
|
|
||||||
const LATEST_VERSION = version.split(".").map(value => Number.parseInt(value));
|
/** Current game version */
|
||||||
|
const LATEST_VERSION = version;
|
||||||
|
|
||||||
|
type SaveMigrator = SystemSaveMigrator | SessionSaveMigrator | SettingsSaveMigrator;
|
||||||
|
|
||||||
|
// biome-ignore lint/complexity/noBannedTypes: TODO - refactor settings
|
||||||
|
type SaveData = SystemSaveData | SessionSaveData | Object;
|
||||||
|
|
||||||
|
// To add a new set of migrators, create a new `.push()` line like so:
|
||||||
|
// `systemMigrators.push(...vA_B_C.systemMigrators);`
|
||||||
|
|
||||||
|
/** All system save migrators */
|
||||||
|
const systemMigrators: SystemSaveMigrator[] = [];
|
||||||
|
systemMigrators.push(...v1_0_4.systemMigrators);
|
||||||
|
systemMigrators.push(...v1_7_0.systemMigrators);
|
||||||
|
systemMigrators.push(...v1_8_3.systemMigrators);
|
||||||
|
|
||||||
|
/** All session save migrators */
|
||||||
|
const sessionMigrators: SessionSaveMigrator[] = [];
|
||||||
|
sessionMigrators.push(...v1_0_4.sessionMigrators);
|
||||||
|
sessionMigrators.push(...v1_7_0.sessionMigrators);
|
||||||
|
|
||||||
|
/** All settings migrators */
|
||||||
|
const settingsMigrators: SettingsSaveMigrator[] = [];
|
||||||
|
settingsMigrators.push(...v1_0_4.settingsMigrators);
|
||||||
|
|
||||||
|
/** Sorts migrators by their stated version, ensuring they are applied in order from oldest to newest */
|
||||||
|
const sortMigrators = (migrators: SaveMigrator[]): void => {
|
||||||
|
migrators.sort((a, b) => compareVersions(a.version, b.version));
|
||||||
|
};
|
||||||
|
|
||||||
|
sortMigrators(systemMigrators);
|
||||||
|
sortMigrators(sessionMigrators);
|
||||||
|
sortMigrators(settingsMigrators);
|
||||||
|
|
||||||
|
const applyMigrators = (migrators: readonly SaveMigrator[], data: SaveData, saveVersion: string) => {
|
||||||
|
for (const migrator of migrators) {
|
||||||
|
const isMigratorVersionHigher = compareVersions(saveVersion, migrator.version) === -1;
|
||||||
|
if (isMigratorVersionHigher) {
|
||||||
|
migrator.migrate(data as any);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts incoming {@linkcode SystemSaveData} that has a version below the
|
* Converts incoming {@linkcode SystemSaveData} that has a version below the
|
||||||
@ -26,12 +111,12 @@ const LATEST_VERSION = version.split(".").map(value => Number.parseInt(value));
|
|||||||
* @see {@link SystemVersionConverter}
|
* @see {@link SystemVersionConverter}
|
||||||
*/
|
*/
|
||||||
export function applySystemVersionMigration(data: SystemSaveData) {
|
export function applySystemVersionMigration(data: SystemSaveData) {
|
||||||
const curVersion = data.gameVersion.split(".").map(value => Number.parseInt(value));
|
const prevVersion = data.gameVersion;
|
||||||
|
const isCurrentVersionHigher = compareVersions(prevVersion, LATEST_VERSION) === -1;
|
||||||
|
|
||||||
if (!curVersion.every((value, index) => value === LATEST_VERSION[index])) {
|
if (isCurrentVersionHigher) {
|
||||||
const converter = new SystemVersionConverter();
|
applyMigrators(systemMigrators, data, prevVersion);
|
||||||
converter.applyStaticPreprocessors(data);
|
console.log(`System data successfully migrated to v${LATEST_VERSION}!`);
|
||||||
converter.applyMigration(data, curVersion);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,12 +131,15 @@ export function applySystemVersionMigration(data: SystemSaveData) {
|
|||||||
* @see {@link SessionVersionConverter}
|
* @see {@link SessionVersionConverter}
|
||||||
*/
|
*/
|
||||||
export function applySessionVersionMigration(data: SessionSaveData) {
|
export function applySessionVersionMigration(data: SessionSaveData) {
|
||||||
const curVersion = data.gameVersion.split(".").map(value => Number.parseInt(value));
|
const prevVersion = data.gameVersion;
|
||||||
|
const isCurrentVersionHigher = compareVersions(prevVersion, LATEST_VERSION) === -1;
|
||||||
|
|
||||||
if (!curVersion.every((value, index) => value === LATEST_VERSION[index])) {
|
if (isCurrentVersionHigher) {
|
||||||
const converter = new SessionVersionConverter();
|
// Always sanitize money as a safeguard
|
||||||
converter.applyStaticPreprocessors(data);
|
data.money = Math.floor(data.money);
|
||||||
converter.applyMigration(data, curVersion);
|
|
||||||
|
applyMigrators(sessionMigrators, data, prevVersion);
|
||||||
|
console.log(`Session data successfully migrated to v${LATEST_VERSION}!`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,156 +153,13 @@ export function applySessionVersionMigration(data: SessionSaveData) {
|
|||||||
* @param data Settings data object
|
* @param data Settings data object
|
||||||
* @see {@link SettingsVersionConverter}
|
* @see {@link SettingsVersionConverter}
|
||||||
*/
|
*/
|
||||||
|
// biome-ignore lint/complexity/noBannedTypes: TODO - refactor settings
|
||||||
export function applySettingsVersionMigration(data: Object) {
|
export function applySettingsVersionMigration(data: Object) {
|
||||||
const gameVersion: string = data.hasOwnProperty("gameVersion") ? data["gameVersion"] : "1.0.0";
|
const prevVersion: string = data.hasOwnProperty("gameVersion") ? data["gameVersion"] : "1.0.0";
|
||||||
const curVersion = gameVersion.split(".").map(value => Number.parseInt(value));
|
const isCurrentVersionHigher = compareVersions(prevVersion, LATEST_VERSION) === -1;
|
||||||
|
|
||||||
if (!curVersion.every((value, index) => value === LATEST_VERSION[index])) {
|
if (isCurrentVersionHigher) {
|
||||||
const converter = new SettingsVersionConverter();
|
applyMigrators(settingsMigrators, data, prevVersion);
|
||||||
converter.applyStaticPreprocessors(data);
|
console.log(`Settings successfully migrated to v${LATEST_VERSION}!`);
|
||||||
converter.applyMigration(data, curVersion);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstract class encapsulating the logic for migrating data from a given version up to
|
|
||||||
* the current version listed in `package.json`.
|
|
||||||
*
|
|
||||||
* Note that, for any version converter, the corresponding `applyMigration`
|
|
||||||
* function would only need to be changed once when the first migration for a
|
|
||||||
* given version is introduced. Similarly, a version file (within the `versions`
|
|
||||||
* folder) would only need to be created for a version once with the appropriate
|
|
||||||
* array nomenclature.
|
|
||||||
*/
|
|
||||||
abstract class VersionConverter {
|
|
||||||
/**
|
|
||||||
* Iterates through an array of designated migration functions that are each
|
|
||||||
* called one by one to transform the data.
|
|
||||||
* @param data The data to be operated on
|
|
||||||
* @param migrationArr An array of functions that will transform the incoming data
|
|
||||||
*/
|
|
||||||
callMigrators(data: any, migrationArr: readonly any[]) {
|
|
||||||
for (const migrate of migrationArr) {
|
|
||||||
migrate(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Applies any version-agnostic data sanitation as defined within the function
|
|
||||||
* body.
|
|
||||||
* @param data The data to be operated on
|
|
||||||
*/
|
|
||||||
applyStaticPreprocessors(_data: any): void {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Uses the current version the incoming data to determine the starting point
|
|
||||||
* of the migration which will cascade up to the latest version, calling the
|
|
||||||
* necessary migration functions in the process.
|
|
||||||
* @param data The data to be operated on
|
|
||||||
* @param curVersion [0] Current major version
|
|
||||||
* [1] Current minor version
|
|
||||||
* [2] Current patch version
|
|
||||||
*/
|
|
||||||
abstract applyMigration(data: any, curVersion: number[]): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class encapsulating the logic for migrating {@linkcode SessionSaveData} from
|
|
||||||
* a given version up to the current version listed in `package.json`.
|
|
||||||
* @extends VersionConverter
|
|
||||||
*/
|
|
||||||
class SessionVersionConverter extends VersionConverter {
|
|
||||||
override applyStaticPreprocessors(data: SessionSaveData): void {
|
|
||||||
// Always sanitize money as a safeguard
|
|
||||||
data.money = Math.floor(data.money);
|
|
||||||
}
|
|
||||||
|
|
||||||
override applyMigration(data: SessionSaveData, curVersion: number[]): void {
|
|
||||||
const [curMajor, curMinor, curPatch] = curVersion;
|
|
||||||
|
|
||||||
if (curMajor === 1) {
|
|
||||||
if (curMinor === 0) {
|
|
||||||
if (curPatch <= 5) {
|
|
||||||
console.log("Applying v1.0.4 session data migration!");
|
|
||||||
this.callMigrators(data, v1_0_4.sessionMigrators);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (curMinor <= 1) {
|
|
||||||
console.log("Applying v1.1.0 session data migration!");
|
|
||||||
this.callMigrators(data, v1_1_0.sessionMigrators);
|
|
||||||
}
|
|
||||||
if (curMinor < 7) {
|
|
||||||
console.log("Applying v1.7.0 session data migration!");
|
|
||||||
this.callMigrators(data, v1_7_0.sessionMigrators);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Session data successfully migrated to v${version}!`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class encapsulating the logic for migrating {@linkcode SystemSaveData} from
|
|
||||||
* a given version up to the current version listed in `package.json`.
|
|
||||||
* @extends VersionConverter
|
|
||||||
*/
|
|
||||||
class SystemVersionConverter extends VersionConverter {
|
|
||||||
override applyMigration(data: SystemSaveData, curVersion: number[]): void {
|
|
||||||
const [curMajor, curMinor, curPatch] = curVersion;
|
|
||||||
|
|
||||||
if (curMajor === 1) {
|
|
||||||
if (curMinor === 0) {
|
|
||||||
if (curPatch <= 4) {
|
|
||||||
console.log("Applying v1.0.4 system data migraton!");
|
|
||||||
this.callMigrators(data, v1_0_4.systemMigrators);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (curMinor <= 1) {
|
|
||||||
console.log("Applying v1.1.0 system data migraton!");
|
|
||||||
this.callMigrators(data, v1_1_0.systemMigrators);
|
|
||||||
}
|
|
||||||
if (curMinor < 7) {
|
|
||||||
console.log("Applying v1.7.0 system data migration!");
|
|
||||||
this.callMigrators(data, v1_7_0.systemMigrators);
|
|
||||||
}
|
|
||||||
if (curMinor === 8) {
|
|
||||||
if (curPatch <= 2) {
|
|
||||||
console.log("Applying v1.8.3 system data migration!");
|
|
||||||
this.callMigrators(data, v1_8_3.systemMigrators);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`System data successfully migrated to v${version}!`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class encapsulating the logic for migrating settings data from
|
|
||||||
* a given version up to the current version listed in `package.json`.
|
|
||||||
* @extends VersionConverter
|
|
||||||
*/
|
|
||||||
class SettingsVersionConverter extends VersionConverter {
|
|
||||||
override applyMigration(data: Object, curVersion: number[]): void {
|
|
||||||
const [curMajor, curMinor, curPatch] = curVersion;
|
|
||||||
|
|
||||||
if (curMajor === 1) {
|
|
||||||
if (curMinor === 0) {
|
|
||||||
if (curPatch <= 4) {
|
|
||||||
console.log("Applying v1.0.4 settings data migraton!");
|
|
||||||
this.callMigrators(data, v1_0_4.settingsMigrators);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (curMinor <= 1) {
|
|
||||||
console.log("Applying v1.1.0 settings data migraton!");
|
|
||||||
this.callMigrators(data, v1_1_0.settingsMigrators);
|
|
||||||
}
|
|
||||||
if (curMinor < 7) {
|
|
||||||
console.log("Applying v1.7.0 settings data migration!");
|
|
||||||
this.callMigrators(data, v1_7_0.settingsMigrators);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Settings data successfully migrated to v${version}!`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,15 +4,18 @@ import { AbilityAttr, defaultStarterSpecies, DexAttr } from "#app/system/game-da
|
|||||||
import { allSpecies } from "#app/data/pokemon-species";
|
import { allSpecies } from "#app/data/pokemon-species";
|
||||||
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||||
import { isNullOrUndefined } from "#app/utils";
|
import { isNullOrUndefined } from "#app/utils";
|
||||||
|
import type { SystemSaveMigrator } from "#app/@types/SystemSaveMigrator";
|
||||||
|
import type { SettingsSaveMigrator } from "#app/@types/SettingsSaveMigrator";
|
||||||
|
import type { SessionSaveMigrator } from "#app/@types/SessionSaveMigrator";
|
||||||
|
|
||||||
export const systemMigrators = [
|
/**
|
||||||
/**
|
* Migrate ability starter data if empty for caught species.
|
||||||
* Migrate ability starter data if empty for caught species.
|
* @param data - {@linkcode SystemSaveData}
|
||||||
* @param data {@linkcode SystemSaveData}
|
*/
|
||||||
*/
|
const migrateAbilityData: SystemSaveMigrator = {
|
||||||
function migrateAbilityData(data: SystemSaveData) {
|
version: "1.0.4",
|
||||||
|
migrate: (data: SystemSaveData): void => {
|
||||||
if (data.starterData && data.dexData) {
|
if (data.starterData && data.dexData) {
|
||||||
// biome-ignore lint/complexity/noForEach: <explanation>
|
|
||||||
Object.keys(data.starterData).forEach(sd => {
|
Object.keys(data.starterData).forEach(sd => {
|
||||||
if (data.dexData[sd]?.caughtAttr && data.starterData[sd] && !data.starterData[sd].abilityAttr) {
|
if (data.dexData[sd]?.caughtAttr && data.starterData[sd] && !data.starterData[sd].abilityAttr) {
|
||||||
data.starterData[sd].abilityAttr = 1;
|
data.starterData[sd].abilityAttr = 1;
|
||||||
@ -20,12 +23,15 @@ export const systemMigrators = [
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Populate legendary Pokémon statistics if they are missing.
|
* Populate legendary Pokémon statistics if they are missing.
|
||||||
* @param data {@linkcode SystemSaveData}
|
* @param data - {@linkcode SystemSaveData}
|
||||||
*/
|
*/
|
||||||
function fixLegendaryStats(data: SystemSaveData) {
|
const fixLegendaryStats: SystemSaveMigrator = {
|
||||||
|
version: "1.0.4",
|
||||||
|
migrate: (data: SystemSaveData): void => {
|
||||||
if (
|
if (
|
||||||
data.gameStats &&
|
data.gameStats &&
|
||||||
data.gameStats.legendaryPokemonCaught !== undefined &&
|
data.gameStats.legendaryPokemonCaught !== undefined &&
|
||||||
@ -34,7 +40,6 @@ export const systemMigrators = [
|
|||||||
data.gameStats.subLegendaryPokemonSeen = 0;
|
data.gameStats.subLegendaryPokemonSeen = 0;
|
||||||
data.gameStats.subLegendaryPokemonCaught = 0;
|
data.gameStats.subLegendaryPokemonCaught = 0;
|
||||||
data.gameStats.subLegendaryPokemonHatched = 0;
|
data.gameStats.subLegendaryPokemonHatched = 0;
|
||||||
// biome-ignore lint/complexity/noForEach: <explanation>
|
|
||||||
allSpecies
|
allSpecies
|
||||||
.filter(s => s.subLegendary)
|
.filter(s => s.subLegendary)
|
||||||
.forEach(s => {
|
.forEach(s => {
|
||||||
@ -66,12 +71,15 @@ export const systemMigrators = [
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unlock all starters' first ability and female gender option.
|
* Unlock all starters' first ability and female gender option.
|
||||||
* @param data {@linkcode SystemSaveData}
|
* @param data - {@linkcode SystemSaveData}
|
||||||
*/
|
*/
|
||||||
function fixStarterData(data: SystemSaveData) {
|
const fixStarterData: SystemSaveMigrator = {
|
||||||
|
version: "1.0.4",
|
||||||
|
migrate: (data: SystemSaveData): void => {
|
||||||
if (!isNullOrUndefined(data.starterData)) {
|
if (!isNullOrUndefined(data.starterData)) {
|
||||||
for (const starterId of defaultStarterSpecies) {
|
for (const starterId of defaultStarterSpecies) {
|
||||||
if (data.starterData[starterId]?.abilityAttr) {
|
if (data.starterData[starterId]?.abilityAttr) {
|
||||||
@ -83,17 +91,22 @@ export const systemMigrators = [
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const systemMigrators: Readonly<SystemSaveMigrator[]> = [
|
||||||
|
migrateAbilityData,
|
||||||
|
fixLegendaryStats,
|
||||||
|
fixStarterData,
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
export const settingsMigrators = [
|
/**
|
||||||
/**
|
* Migrate from `REROLL_TARGET` property to {@linkcode SettingKeys.Shop_Cursor_Target}
|
||||||
* Migrate from "REROLL_TARGET" property to {@linkcode
|
* @param data - The `settings` object
|
||||||
* SettingKeys.Shop_Cursor_Target}.
|
*/
|
||||||
* @param data the `settings` object
|
const fixRerollTarget: SettingsSaveMigrator = {
|
||||||
*/
|
version: "1.0.4",
|
||||||
|
// biome-ignore lint/complexity/noBannedTypes: TODO - refactor settings
|
||||||
// biome-ignore lint/complexity/noBannedTypes: TODO: fix the type to not be object...
|
migrate: (data: Object): void => {
|
||||||
function fixRerollTarget(data: Object) {
|
|
||||||
if (data.hasOwnProperty("REROLL_TARGET") && !data.hasOwnProperty(SettingKeys.Shop_Cursor_Target)) {
|
if (data.hasOwnProperty("REROLL_TARGET") && !data.hasOwnProperty(SettingKeys.Shop_Cursor_Target)) {
|
||||||
data[SettingKeys.Shop_Cursor_Target] = data["REROLL_TARGET"];
|
data[SettingKeys.Shop_Cursor_Target] = data["REROLL_TARGET"];
|
||||||
// biome-ignore lint/performance/noDelete: intentional
|
// biome-ignore lint/performance/noDelete: intentional
|
||||||
@ -101,16 +114,20 @@ export const settingsMigrators = [
|
|||||||
localStorage.setItem("settings", JSON.stringify(data));
|
localStorage.setItem("settings", JSON.stringify(data));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
] as const;
|
};
|
||||||
|
|
||||||
export const sessionMigrators = [
|
export const settingsMigrators: Readonly<SettingsSaveMigrator[]> = [fixRerollTarget] as const;
|
||||||
/**
|
|
||||||
* Converts old lapsing modifiers (battle items, lures, and Dire Hit) and
|
/**
|
||||||
* other miscellaneous modifiers (vitamins, White Herb) to any new class
|
* Converts old lapsing modifiers (battle items, lures, and Dire Hit) and
|
||||||
* names and/or change in reload arguments.
|
* other miscellaneous modifiers (vitamins, White Herb) to any new class
|
||||||
* @param data {@linkcode SessionSaveData}
|
* names and/or change in reload arguments.
|
||||||
*/
|
* @param data - {@linkcode SessionSaveData}
|
||||||
function migrateModifiers(data: SessionSaveData) {
|
*/
|
||||||
|
const migrateModifiers: SessionSaveMigrator = {
|
||||||
|
version: "1.0.4",
|
||||||
|
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: necessary?
|
||||||
|
migrate: (data: SessionSaveData): void => {
|
||||||
for (const m of data.modifiers) {
|
for (const m of data.modifiers) {
|
||||||
if (m.className === "PokemonBaseStatModifier") {
|
if (m.className === "PokemonBaseStatModifier") {
|
||||||
m.className = "BaseStatModifier";
|
m.className = "BaseStatModifier";
|
||||||
@ -163,12 +180,11 @@ export const sessionMigrators = [
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/**
|
};
|
||||||
* Converts old Pokemon natureOverride and mysteryEncounterData
|
|
||||||
* to use the new conjoined {@linkcode Pokemon.customPokemonData} structure instead.
|
const migrateCustomPokemonData: SessionSaveMigrator = {
|
||||||
* @param data {@linkcode SessionSaveData}
|
version: "1.0.4",
|
||||||
*/
|
migrate: (data: SessionSaveData): void => {
|
||||||
function migrateCustomPokemonDataAndNatureOverrides(data: SessionSaveData) {
|
|
||||||
// Fix Pokemon nature overrides and custom data migration
|
// Fix Pokemon nature overrides and custom data migration
|
||||||
for (const pokemon of data.party) {
|
for (const pokemon of data.party) {
|
||||||
if (pokemon["mysteryEncounterPokemonData"]) {
|
if (pokemon["mysteryEncounterPokemonData"]) {
|
||||||
@ -186,4 +202,6 @@ export const sessionMigrators = [
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
] as const;
|
};
|
||||||
|
|
||||||
|
export const sessionMigrators: Readonly<SessionSaveMigrator[]> = [migrateModifiers, migrateCustomPokemonData] as const;
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
export const systemMigrators = [] as const;
|
|
||||||
|
|
||||||
export const settingsMigrators = [] as const;
|
|
||||||
|
|
||||||
export const sessionMigrators = [] as const;
|
|
@ -1,15 +1,18 @@
|
|||||||
|
import type { SessionSaveMigrator } from "#app/@types/SessionSaveMigrator";
|
||||||
|
import type { SystemSaveMigrator } from "#app/@types/SystemSaveMigrator";
|
||||||
import { getPokemonSpecies, getPokemonSpeciesForm } from "#app/data/pokemon-species";
|
import { getPokemonSpecies, getPokemonSpeciesForm } from "#app/data/pokemon-species";
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { DexAttr, type SessionSaveData, type SystemSaveData } from "#app/system/game-data";
|
import { DexAttr, type SessionSaveData, type SystemSaveData } from "#app/system/game-data";
|
||||||
import * as Utils from "#app/utils";
|
import { isNullOrUndefined } from "#app/utils";
|
||||||
|
|
||||||
export const systemMigrators = [
|
/**
|
||||||
/**
|
* If a starter is caught, but the only forms registered as caught are not starterSelectable,
|
||||||
* If a starter is caught, but the only forms registered as caught are not starterSelectable,
|
* unlock the default form.
|
||||||
* unlock the default form.
|
* @param data - {@linkcode SystemSaveData}
|
||||||
* @param data {@linkcode SystemSaveData}
|
*/
|
||||||
*/
|
const migrateUnselectableForms: SystemSaveMigrator = {
|
||||||
function migrateUnselectableForms(data: SystemSaveData) {
|
version: "1.7.0",
|
||||||
|
migrate: (data: SystemSaveData): void => {
|
||||||
if (data.starterData && data.dexData) {
|
if (data.starterData && data.dexData) {
|
||||||
Object.keys(data.starterData).forEach(sd => {
|
Object.keys(data.starterData).forEach(sd => {
|
||||||
const caughtAttr = data.dexData[sd]?.caughtAttr;
|
const caughtAttr = data.dexData[sd]?.caughtAttr;
|
||||||
@ -30,12 +33,13 @@ export const systemMigrators = [
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
] as const;
|
};
|
||||||
|
|
||||||
export const settingsMigrators = [] as const;
|
export const systemMigrators: Readonly<SystemSaveMigrator[]> = [migrateUnselectableForms] as const;
|
||||||
|
|
||||||
export const sessionMigrators = [
|
const migrateTera: SessionSaveMigrator = {
|
||||||
function migrateTera(data: SessionSaveData) {
|
version: "1.7.0",
|
||||||
|
migrate: (data: SessionSaveData): void => {
|
||||||
for (let i = 0; i < data.modifiers.length; ) {
|
for (let i = 0; i < data.modifiers.length; ) {
|
||||||
if (data.modifiers[i].className === "TerastallizeModifier") {
|
if (data.modifiers[i].className === "TerastallizeModifier") {
|
||||||
data.party.forEach(p => {
|
data.party.forEach(p => {
|
||||||
@ -63,15 +67,17 @@ export const sessionMigrators = [
|
|||||||
}
|
}
|
||||||
|
|
||||||
data.party.forEach(p => {
|
data.party.forEach(p => {
|
||||||
if (Utils.isNullOrUndefined(p.teraType)) {
|
if (isNullOrUndefined(p.teraType)) {
|
||||||
p.teraType = getPokemonSpeciesForm(p.species, p.formIndex).type1;
|
p.teraType = getPokemonSpeciesForm(p.species, p.formIndex).type1;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
data.enemyParty.forEach(p => {
|
data.enemyParty.forEach(p => {
|
||||||
if (Utils.isNullOrUndefined(p.teraType)) {
|
if (isNullOrUndefined(p.teraType)) {
|
||||||
p.teraType = getPokemonSpeciesForm(p.species, p.formIndex).type1;
|
p.teraType = getPokemonSpeciesForm(p.species, p.formIndex).type1;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
] as const;
|
};
|
||||||
|
|
||||||
|
export const sessionMigrators: Readonly<SessionSaveMigrator[]> = [migrateTera] as const;
|
||||||
|
@ -1,14 +1,16 @@
|
|||||||
|
import type { SystemSaveMigrator } from "#app/@types/SystemSaveMigrator";
|
||||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||||
import { DexAttr, type SystemSaveData } from "#app/system/game-data";
|
import { DexAttr, type SystemSaveData } from "#app/system/game-data";
|
||||||
import { Species } from "#enums/species";
|
import { Species } from "#enums/species";
|
||||||
|
|
||||||
export const systemMigrators = [
|
/**
|
||||||
/**
|
* If a starter is caught, but the only forms registered as caught are not starterSelectable,
|
||||||
* If a starter is caught, but the only forms registered as caught are not starterSelectable,
|
* unlock the default form.
|
||||||
* unlock the default form.
|
* @param data - {@linkcode SystemSaveData}
|
||||||
* @param data {@linkcode SystemSaveData}
|
*/
|
||||||
*/
|
const migratePichuForms: SystemSaveMigrator = {
|
||||||
function migratePichuForms(data: SystemSaveData) {
|
version: "1.8.3",
|
||||||
|
migrate: (data: SystemSaveData): void => {
|
||||||
if (data.starterData && data.dexData) {
|
if (data.starterData && data.dexData) {
|
||||||
// This is Pichu's Pokédex number
|
// This is Pichu's Pokédex number
|
||||||
const sd = 172;
|
const sd = 172;
|
||||||
@ -23,8 +25,6 @@ export const systemMigrators = [
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
] as const;
|
};
|
||||||
|
|
||||||
export const settingsMigrators = [] as const;
|
export const systemMigrators: Readonly<SystemSaveMigrator[]> = [migratePichuForms] as const;
|
||||||
|
|
||||||
export const sessionMigrators = [] as const;
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user