diff --git a/src/Corporation/OfficeSpace.ts b/src/Corporation/OfficeSpace.ts index 89e017548..57f95c640 100644 --- a/src/Corporation/OfficeSpace.ts +++ b/src/Corporation/OfficeSpace.ts @@ -238,17 +238,6 @@ export class OfficeSpace { } static fromJSON(value: IReviverValue): OfficeSpace { - // Convert employees from the old version - if (Object.hasOwn(value.data, "employees")) { - const empCopy: [{ data: { mor: number; ene: number; exp: number } }] = value.data.employees; - delete value.data.employees; - const ret = Generic_fromJSON(OfficeSpace, value.data); - ret.numEmployees = empCopy.length; - ret.avgMorale = empCopy.reduce((a, b) => a + b.data.mor, 0) / ret.numEmployees || 75; - ret.avgEnergy = empCopy.reduce((a, b) => a + b.data.ene, 0) / ret.numEmployees || 75; - ret.totalExperience = empCopy.reduce((a, b) => a + b.data.exp, 0); - return ret; - } return Generic_fromJSON(OfficeSpace, value.data); } } diff --git a/src/SaveObject.tsx b/src/SaveObject.tsx index e847afffa..09b8c030a 100755 --- a/src/SaveObject.tsx +++ b/src/SaveObject.tsx @@ -478,6 +478,51 @@ function evaluateVersionCompatibility(ver: string | number): void { const graft = anyPlayer.graftAugmentationName; if (graft) Player.augmentations.push({ name: graft, level: 1 }); } + if (ver < 31) { + // This section of 2.3.0 changes is intentionally OUT-OF-ORDER. + // This is because it upgrades how files and paths are handled, and other + // (old) upgrade sections have come to depend on the new format, via + // standard helper functions. + // Other 2.3.0 changes are in their regular place. + Terminal.warn("Migrating to 2.3.0, loading with no scripts."); + const newDirectory = resolveDirectory("v2.3FileChanges/") as Directory; + for (const server of GetAllServers()) { + // Do not load saved scripts on migration + server.savedScripts = []; + let invalidScriptCount = 0; + // There was a brief dev window where Server.scripts was already a map but the filepath changes weren't in yet. + const oldScripts = Array.isArray(server.scripts) ? (server.scripts as Script[]) : [...server.scripts.values()]; + server.scripts = new JSONMap(); + // In case somehow there are previously valid filenames that can't be sanitized, they will go in a new directory with a note. + for (const script of oldScripts) { + let newFilePath = resolveScriptFilePath(script.filename); + if (!newFilePath) { + newFilePath = `${newDirectory}script${++invalidScriptCount}.js` as ScriptFilePath; + script.content = `// Original path: ${script.filename}. Path was no longer valid\n` + script.content; + } + script.filename = newFilePath; + server.scripts.set(newFilePath, script); + } + // Handle changing textFiles to a map as well as FilePath changes at the same time. + if (Array.isArray(server.textFiles)) { + const oldTextFiles = server.textFiles as (TextFile & { fn?: string })[]; + server.textFiles = new JSONMap(); + let invalidTextCount = 0; + for (const textFile of oldTextFiles) { + const oldName = textFile.fn ?? textFile.filename; + delete textFile.fn; + + let newFilePath = resolveTextFilePath(oldName); + if (!newFilePath) { + newFilePath = `${newDirectory}text${++invalidTextCount}.txt` as TextFilePath; + textFile.content = `// Original path: ${textFile.filename}. Path was no longer valid\n` + textFile.content; + } + textFile.filename = newFilePath; + server.textFiles.set(newFilePath, textFile); + } + } + } + } if (ver < 22) { v22PlayerBreak(); v2APIBreak(); @@ -668,44 +713,6 @@ function evaluateVersionCompatibility(ver: string | number): void { anyPlayer.lastNodeReset = anyPlayer.lastUpdate - anyPlayer.playtimeSinceLastBitnode; } - Terminal.warn("Migrating to 2.3.0, loading with no scripts."); - const newDirectory = resolveDirectory("v2.3FileChanges/") as Directory; - for (const server of GetAllServers()) { - // Do not load saved scripts on migration - server.savedScripts = []; - let invalidScriptCount = 0; - // There was a brief dev window where Server.scripts was already a map but the filepath changes weren't in yet. - const oldScripts = Array.isArray(server.scripts) ? (server.scripts as Script[]) : [...server.scripts.values()]; - server.scripts = new JSONMap(); - // In case somehow there are previously valid filenames that can't be sanitized, they will go in a new directory with a note. - for (const script of oldScripts) { - let newFilePath = resolveScriptFilePath(script.filename); - if (!newFilePath) { - newFilePath = `${newDirectory}script${++invalidScriptCount}.js` as ScriptFilePath; - script.content = `// Original path: ${script.filename}. Path was no longer valid\n` + script.content; - } - script.filename = newFilePath; - server.scripts.set(newFilePath, script); - } - // Handle changing textFiles to a map as well as FilePath changes at the same time. - if (Array.isArray(server.textFiles)) { - const oldTextFiles = server.textFiles as (TextFile & { fn?: string })[]; - server.textFiles = new JSONMap(); - let invalidTextCount = 0; - for (const textFile of oldTextFiles) { - const oldName = textFile.fn ?? textFile.filename; - delete textFile.fn; - - let newFilePath = resolveTextFilePath(oldName); - if (!newFilePath) { - newFilePath = `${newDirectory}text${++invalidTextCount}.txt` as TextFilePath; - textFile.content = `// Original path: ${textFile.filename}. Path was no longer valid\n` + textFile.content; - } - textFile.filename = newFilePath; - server.textFiles.set(newFilePath, textFile); - } - } - } // Reset corporation to new format. const oldCorp = anyPlayer.corporation as Corporation | null | 0; if (oldCorp && Array.isArray(oldCorp.divisions)) { @@ -764,6 +771,7 @@ function loadGame(saveString: string): boolean { try { loadStockMarket(saveObj.StockMarketSave); } catch (e) { + console.error("Couldn't load stock market:", e); loadStockMarket(""); } } else { @@ -804,6 +812,7 @@ function loadGame(saveString: string): boolean { createNewUpdateText(); } } catch (e) { + console.error("Error upgrading versions:", e); createNewUpdateText(); } } else { diff --git a/src/SourceFile/SourceFiles.tsx b/src/SourceFile/SourceFiles.tsx index 85a4dab3c..9dec74bf4 100644 --- a/src/SourceFile/SourceFiles.tsx +++ b/src/SourceFile/SourceFiles.tsx @@ -1,12 +1,11 @@ import React from "react"; import { SourceFile } from "./SourceFile"; -import { initBitNodes, initBitNodeMultipliers } from "../BitNode/BitNode"; +import { initBitNodes } from "../BitNode/BitNode"; export const SourceFiles: Record = {}; /** Engine initializer for SourceFiles, BitNodes, and BitNodeMultipliers. Run once at engine load. */ export function initSourceFiles() { initBitNodes(); - initBitNodeMultipliers(); SourceFiles.SourceFile1 = new SourceFile( 1, ( diff --git a/src/engine.tsx b/src/engine.tsx index d86d8a355..4630c2caa 100644 --- a/src/engine.tsx +++ b/src/engine.tsx @@ -1,6 +1,7 @@ import { convertTimeMsToTimeElapsedString } from "./utils/StringHelperFunctions"; import { initAugmentations } from "./Augmentation/AugmentationHelpers"; import { AugmentationNames } from "./Augmentation/data/AugmentationNames"; +import { initBitNodeMultipliers } from "./BitNode/BitNode"; import { initSourceFiles } from "./SourceFile/SourceFiles"; import { generateRandomContract } from "./CodingContractGenerator"; import { initCompanies } from "./Company/Companies"; @@ -229,11 +230,14 @@ const Engine: { load: function (saveString) { startExploits(); setupUncaughtPromiseHandler(); + // Source files must be initialized early because save-game translation in + // loadGame() needs them sometimes. + initSourceFiles(); // Load game from save or create new game if (loadGame(saveString)) { FormatsNeedToChange.emit(); - initSourceFiles(); + initBitNodeMultipliers(); initAugmentations(); // Also calls Player.reapplyAllAugmentations() Player.reapplyAllSourceFiles(); if (Player.hasWseAccount) { @@ -374,7 +378,7 @@ const Engine: { } else { // No save found, start new game FormatsNeedToChange.emit(); - initSourceFiles(); + initBitNodeMultipliers(); Engine.start(); // Run main game loop and Scripts loop Player.init(); initForeignServers(Player.getHomeComputer()); diff --git a/src/utils/JSONReviver.ts b/src/utils/JSONReviver.ts index 93417b7d0..661e3b95d 100644 --- a/src/utils/JSONReviver.ts +++ b/src/utils/JSONReviver.ts @@ -34,6 +34,9 @@ export function Reviver(_key: string, value: unknown): any { case "Industry": console.warn("Converting a corp from pre-2.3"); return value.data; // Will immediately be overwritten by v2.3 save migration code + case "Employee": + console.warn("Converting a corp from pre-2.2"); + return value.data; // Will immediately be overwritten by v2.3 save migration code } // Missing constructor with no special handling. Throw error. throw new Error(`Could not locate constructor named ${value.ctor}. If the save data is valid, this is a bug.`); diff --git a/src/utils/v2APIBreak.ts b/src/utils/v2APIBreak.ts index 754419895..77d364cfc 100644 --- a/src/utils/v2APIBreak.ts +++ b/src/utils/v2APIBreak.ts @@ -229,7 +229,7 @@ export const v2APIBreak = () => { } // API break function is called before the version31 2.3.0 changes, scripts are still an array. - for (const script of home.scripts as unknown as Script[]) { + for (const script of home.scripts.values() as unknown as Script[]) { processScript(rules, script); }