mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-18 21:53:50 +01:00
Various fixes to our upgrade logic (#536)
Stuff broke over time, especially with the major changes we made leading up to 2.3. We should test with older saves if/when we make large changes in the future. Fixes #532
This commit is contained in:
parent
ab207ce36c
commit
db26d054fc
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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<string, SourceFile> = {};
|
||||
/** Engine initializer for SourceFiles, BitNodes, and BitNodeMultipliers. Run once at engine load. */
|
||||
export function initSourceFiles() {
|
||||
initBitNodes();
|
||||
initBitNodeMultipliers();
|
||||
SourceFiles.SourceFile1 = new SourceFile(
|
||||
1,
|
||||
(
|
||||
|
@ -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());
|
||||
|
@ -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.`);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user