diff --git a/electron/export.html b/electron/export.html index ff5191455..be56c061b 100644 --- a/electron/export.html +++ b/electron/export.html @@ -25,5 +25,77 @@

Close me when operation is completed.

+ + diff --git a/electron/main.js b/electron/main.js index 43b89d706..dbae58f2c 100644 --- a/electron/main.js +++ b/electron/main.js @@ -258,7 +258,6 @@ app.on("ready", async () => { await window.loadFile("export.html"); window.show(); setStopProcessHandler(window); - await utils.exportSave(window); } else { window = await startWindow(process.argv.includes("--no-scripts")); if (global.steamworksError) { diff --git a/electron/utils.js b/electron/utils.js index d317c475f..a35bdd5a4 100644 --- a/electron/utils.js +++ b/electron/utils.js @@ -90,36 +90,6 @@ function showErrorBox(title, error) { dialog.showErrorBox(title, `${error.name}\n\n${error.message}`); } -function exportSaveFromIndexedDb() { - return new Promise((resolve) => { - const dbRequest = indexedDB.open("bitburnerSave"); - dbRequest.onsuccess = () => { - const db = dbRequest.result; - const transaction = db.transaction(["savestring"], "readonly"); - const store = transaction.objectStore("savestring"); - const request = store.get("save"); - request.onsuccess = () => { - const file = new Blob([request.result], { type: "text/plain" }); - const a = document.createElement("a"); - const url = URL.createObjectURL(file); - a.href = url; - a.download = "save.json"; - document.body.appendChild(a); - a.click(); - setTimeout(function () { - document.body.removeChild(a); - window.URL.revokeObjectURL(url); - resolve(); - }, 0); - }; - }; - }); -} - -async function exportSave(window) { - await window.webContents.executeJavaScript(`${exportSaveFromIndexedDb.toString()}; exportSaveFromIndexedDb();`, true); -} - async function writeTerminal(window, message, type = null) { await window.webContents.executeJavaScript(`window.appNotifier.terminal("${message}", "${type}");`, true); } @@ -186,7 +156,6 @@ function initializeLogLevelConfig() { module.exports = { reloadAndKill, showErrorBox, - exportSave, attachUnresponsiveAppHandler, detachUnresponsiveAppHandler, writeTerminal, diff --git a/src/db.ts b/src/db.ts index aee9049d3..56c77e641 100644 --- a/src/db.ts +++ b/src/db.ts @@ -1,5 +1,12 @@ import type { SaveData } from "./types"; +export class IndexedDBVersionError extends Error { + constructor(message: string, options: ErrorOptions) { + super(message, options); + this.name = this.constructor.name; + } +} + function getDB(): Promise { return new Promise((resolve, reject) => { if (!window.indexedDB) { @@ -9,18 +16,29 @@ function getDB(): Promise { * DB is called bitburnerSave * Object store is called savestring * key for the Object store is called save - * Version `1` is important + * Version `2` is important. When increasing the version, remember to update the code in electron/export.html. + * + * Version 1 is the initial version. We found a bug that caused the database to be missing the expected object + * store. In order to add the missing object store, we need to either increase the database version or delete and + * recreate the database. Increasing the version number is simpler. For more information, please check + * https://github.com/bitburner-official/bitburner-src/pull/2590 */ - const indexedDbRequest: IDBOpenDBRequest = window.indexedDB.open("bitburnerSave", 1); + const indexedDbRequest: IDBOpenDBRequest = window.indexedDB.open("bitburnerSave", 2); // This is called when there's no db to begin with. It's important, don't remove it. indexedDbRequest.onupgradeneeded = function (this: IDBRequest) { const db = this.result; + if (db.objectStoreNames.contains("savestring")) { + return; + } db.createObjectStore("savestring"); }; indexedDbRequest.onerror = function (this: IDBRequest) { - reject(new Error("Failed to get IDB", { cause: this.error })); + if (this.error?.name === "VersionError") { + reject(new IndexedDBVersionError(this.error.message, { cause: this.error })); + } + reject(this.error ?? new Error("Failed to get IDB")); }; indexedDbRequest.onsuccess = function (this: IDBRequest) { diff --git a/src/ui/React/RecoveryRoot.tsx b/src/ui/React/RecoveryRoot.tsx index 623c36933..d0b33a144 100644 --- a/src/ui/React/RecoveryRoot.tsx +++ b/src/ui/React/RecoveryRoot.tsx @@ -2,7 +2,7 @@ import React, { useEffect } from "react"; import { Typography, Link, Button, ButtonGroup, Tooltip, Box, Paper, TextField } from "@mui/material"; import { Settings } from "../../Settings/Settings"; -import { load } from "../../db"; +import { IndexedDBVersionError, load } from "../../db"; import { Router } from "../GameRoot"; import { Page } from "../Router"; import { type CrashReport, newIssueUrl, getCrashReport, isSaveDataFromNewerVersions } from "../../utils/ErrorHelper"; @@ -112,14 +112,18 @@ export function RecoveryRoot({ softReset, crashReport, resetError }: IProps): Re ); } else if ( - sourceError instanceof JSONReviverError && - isSaveDataFromNewerVersions(loadedSaveObjectMiniDump.VersionSave) + (sourceError instanceof JSONReviverError && isSaveDataFromNewerVersions(loadedSaveObjectMiniDump.VersionSave)) || + sourceError instanceof IndexedDBVersionError ) { instructions = ( - Your save data is from a newer version (Version number: {loadedSaveObjectMiniDump.VersionSave}). The current - version number is {CONSTANTS.VersionNumber}. -
+ {loadedSaveObjectMiniDump.VersionSave !== undefined && ( + <> + Your save data is from a newer version (Version number: {loadedSaveObjectMiniDump.VersionSave}). The current + version number is {CONSTANTS.VersionNumber}. +
+ + )} Please check if you are using the correct build. This may happen when you load the save data of the dev build (Steam Beta or https://bitburner-official.github.io/bitburner-src) on the stable build.