mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-09-19 20:38:42 +02: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 {
|
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);
|
return Generic_fromJSON(OfficeSpace, value.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -478,6 +478,51 @@ function evaluateVersionCompatibility(ver: string | number): void {
|
|||||||
const graft = anyPlayer.graftAugmentationName;
|
const graft = anyPlayer.graftAugmentationName;
|
||||||
if (graft) Player.augmentations.push({ name: graft, level: 1 });
|
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) {
|
if (ver < 22) {
|
||||||
v22PlayerBreak();
|
v22PlayerBreak();
|
||||||
v2APIBreak();
|
v2APIBreak();
|
||||||
@ -668,44 +713,6 @@ function evaluateVersionCompatibility(ver: string | number): void {
|
|||||||
anyPlayer.lastNodeReset = anyPlayer.lastUpdate - anyPlayer.playtimeSinceLastBitnode;
|
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.
|
// Reset corporation to new format.
|
||||||
const oldCorp = anyPlayer.corporation as Corporation | null | 0;
|
const oldCorp = anyPlayer.corporation as Corporation | null | 0;
|
||||||
if (oldCorp && Array.isArray(oldCorp.divisions)) {
|
if (oldCorp && Array.isArray(oldCorp.divisions)) {
|
||||||
@ -764,6 +771,7 @@ function loadGame(saveString: string): boolean {
|
|||||||
try {
|
try {
|
||||||
loadStockMarket(saveObj.StockMarketSave);
|
loadStockMarket(saveObj.StockMarketSave);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
console.error("Couldn't load stock market:", e);
|
||||||
loadStockMarket("");
|
loadStockMarket("");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -804,6 +812,7 @@ function loadGame(saveString: string): boolean {
|
|||||||
createNewUpdateText();
|
createNewUpdateText();
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
console.error("Error upgrading versions:", e);
|
||||||
createNewUpdateText();
|
createNewUpdateText();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { SourceFile } from "./SourceFile";
|
import { SourceFile } from "./SourceFile";
|
||||||
import { initBitNodes, initBitNodeMultipliers } from "../BitNode/BitNode";
|
import { initBitNodes } from "../BitNode/BitNode";
|
||||||
|
|
||||||
export const SourceFiles: Record<string, SourceFile> = {};
|
export const SourceFiles: Record<string, SourceFile> = {};
|
||||||
/** Engine initializer for SourceFiles, BitNodes, and BitNodeMultipliers. Run once at engine load. */
|
/** Engine initializer for SourceFiles, BitNodes, and BitNodeMultipliers. Run once at engine load. */
|
||||||
export function initSourceFiles() {
|
export function initSourceFiles() {
|
||||||
initBitNodes();
|
initBitNodes();
|
||||||
initBitNodeMultipliers();
|
|
||||||
SourceFiles.SourceFile1 = new SourceFile(
|
SourceFiles.SourceFile1 = new SourceFile(
|
||||||
1,
|
1,
|
||||||
(
|
(
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { convertTimeMsToTimeElapsedString } from "./utils/StringHelperFunctions";
|
import { convertTimeMsToTimeElapsedString } from "./utils/StringHelperFunctions";
|
||||||
import { initAugmentations } from "./Augmentation/AugmentationHelpers";
|
import { initAugmentations } from "./Augmentation/AugmentationHelpers";
|
||||||
import { AugmentationNames } from "./Augmentation/data/AugmentationNames";
|
import { AugmentationNames } from "./Augmentation/data/AugmentationNames";
|
||||||
|
import { initBitNodeMultipliers } from "./BitNode/BitNode";
|
||||||
import { initSourceFiles } from "./SourceFile/SourceFiles";
|
import { initSourceFiles } from "./SourceFile/SourceFiles";
|
||||||
import { generateRandomContract } from "./CodingContractGenerator";
|
import { generateRandomContract } from "./CodingContractGenerator";
|
||||||
import { initCompanies } from "./Company/Companies";
|
import { initCompanies } from "./Company/Companies";
|
||||||
@ -229,11 +230,14 @@ const Engine: {
|
|||||||
load: function (saveString) {
|
load: function (saveString) {
|
||||||
startExploits();
|
startExploits();
|
||||||
setupUncaughtPromiseHandler();
|
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
|
// Load game from save or create new game
|
||||||
|
|
||||||
if (loadGame(saveString)) {
|
if (loadGame(saveString)) {
|
||||||
FormatsNeedToChange.emit();
|
FormatsNeedToChange.emit();
|
||||||
initSourceFiles();
|
initBitNodeMultipliers();
|
||||||
initAugmentations(); // Also calls Player.reapplyAllAugmentations()
|
initAugmentations(); // Also calls Player.reapplyAllAugmentations()
|
||||||
Player.reapplyAllSourceFiles();
|
Player.reapplyAllSourceFiles();
|
||||||
if (Player.hasWseAccount) {
|
if (Player.hasWseAccount) {
|
||||||
@ -374,7 +378,7 @@ const Engine: {
|
|||||||
} else {
|
} else {
|
||||||
// No save found, start new game
|
// No save found, start new game
|
||||||
FormatsNeedToChange.emit();
|
FormatsNeedToChange.emit();
|
||||||
initSourceFiles();
|
initBitNodeMultipliers();
|
||||||
Engine.start(); // Run main game loop and Scripts loop
|
Engine.start(); // Run main game loop and Scripts loop
|
||||||
Player.init();
|
Player.init();
|
||||||
initForeignServers(Player.getHomeComputer());
|
initForeignServers(Player.getHomeComputer());
|
||||||
|
@ -34,6 +34,9 @@ export function Reviver(_key: string, value: unknown): any {
|
|||||||
case "Industry":
|
case "Industry":
|
||||||
console.warn("Converting a corp from pre-2.3");
|
console.warn("Converting a corp from pre-2.3");
|
||||||
return value.data; // Will immediately be overwritten by v2.3 save migration code
|
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.
|
// 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.`);
|
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.
|
// 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);
|
processScript(rules, script);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user