mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-27 01:53:48 +01:00
add difficulty to bitnode screen
This commit is contained in:
parent
c3ac16f330
commit
57a5c8b0b4
@ -16,8 +16,11 @@ class BitNode {
|
|||||||
// BitNode number
|
// BitNode number
|
||||||
number: number;
|
number: number;
|
||||||
|
|
||||||
constructor(n: number, name: string, desc = "", info: JSX.Element = <></>) {
|
difficulty: 0 | 1 | 2;
|
||||||
|
|
||||||
|
constructor(n: number, difficulty: 0 | 1 | 2, name: string, desc = "", info: JSX.Element = <></>) {
|
||||||
this.number = n;
|
this.number = n;
|
||||||
|
this.difficulty = difficulty;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.desc = desc;
|
this.desc = desc;
|
||||||
this.info = info;
|
this.info = info;
|
||||||
@ -28,6 +31,7 @@ export const BitNodes: IMap<BitNode> = {};
|
|||||||
|
|
||||||
BitNodes["BitNode1"] = new BitNode(
|
BitNodes["BitNode1"] = new BitNode(
|
||||||
1,
|
1,
|
||||||
|
0,
|
||||||
"Source Genesis",
|
"Source Genesis",
|
||||||
"The original BitNode",
|
"The original BitNode",
|
||||||
(
|
(
|
||||||
@ -54,6 +58,7 @@ BitNodes["BitNode1"] = new BitNode(
|
|||||||
);
|
);
|
||||||
BitNodes["BitNode2"] = new BitNode(
|
BitNodes["BitNode2"] = new BitNode(
|
||||||
2,
|
2,
|
||||||
|
0,
|
||||||
"Rise of the Underworld",
|
"Rise of the Underworld",
|
||||||
"From the shadows, they rose", //Gangs
|
"From the shadows, they rose", //Gangs
|
||||||
(
|
(
|
||||||
@ -101,6 +106,7 @@ BitNodes["BitNode2"] = new BitNode(
|
|||||||
);
|
);
|
||||||
BitNodes["BitNode3"] = new BitNode(
|
BitNodes["BitNode3"] = new BitNode(
|
||||||
3,
|
3,
|
||||||
|
0,
|
||||||
"Corporatocracy",
|
"Corporatocracy",
|
||||||
"The Price of Civilization",
|
"The Price of Civilization",
|
||||||
(
|
(
|
||||||
@ -140,6 +146,7 @@ BitNodes["BitNode3"] = new BitNode(
|
|||||||
);
|
);
|
||||||
BitNodes["BitNode4"] = new BitNode(
|
BitNodes["BitNode4"] = new BitNode(
|
||||||
4,
|
4,
|
||||||
|
1,
|
||||||
"The Singularity",
|
"The Singularity",
|
||||||
"The Man and the Machine",
|
"The Man and the Machine",
|
||||||
(
|
(
|
||||||
@ -164,6 +171,7 @@ BitNodes["BitNode4"] = new BitNode(
|
|||||||
);
|
);
|
||||||
BitNodes["BitNode5"] = new BitNode(
|
BitNodes["BitNode5"] = new BitNode(
|
||||||
5,
|
5,
|
||||||
|
1,
|
||||||
"Artificial Intelligence",
|
"Artificial Intelligence",
|
||||||
"Posthuman",
|
"Posthuman",
|
||||||
(
|
(
|
||||||
@ -211,6 +219,7 @@ BitNodes["BitNode5"] = new BitNode(
|
|||||||
);
|
);
|
||||||
BitNodes["BitNode6"] = new BitNode(
|
BitNodes["BitNode6"] = new BitNode(
|
||||||
6,
|
6,
|
||||||
|
1,
|
||||||
"Bladeburners",
|
"Bladeburners",
|
||||||
"Like Tears in Rain",
|
"Like Tears in Rain",
|
||||||
(
|
(
|
||||||
@ -255,6 +264,7 @@ BitNodes["BitNode6"] = new BitNode(
|
|||||||
);
|
);
|
||||||
BitNodes["BitNode7"] = new BitNode(
|
BitNodes["BitNode7"] = new BitNode(
|
||||||
7,
|
7,
|
||||||
|
2,
|
||||||
"Bladeburners 2079",
|
"Bladeburners 2079",
|
||||||
"More human than humans",
|
"More human than humans",
|
||||||
(
|
(
|
||||||
@ -303,6 +313,7 @@ BitNodes["BitNode7"] = new BitNode(
|
|||||||
);
|
);
|
||||||
BitNodes["BitNode8"] = new BitNode(
|
BitNodes["BitNode8"] = new BitNode(
|
||||||
8,
|
8,
|
||||||
|
2,
|
||||||
"Ghost of Wall Street",
|
"Ghost of Wall Street",
|
||||||
"Money never sleeps",
|
"Money never sleeps",
|
||||||
(
|
(
|
||||||
@ -347,6 +358,7 @@ BitNodes["BitNode8"] = new BitNode(
|
|||||||
);
|
);
|
||||||
BitNodes["BitNode9"] = new BitNode(
|
BitNodes["BitNode9"] = new BitNode(
|
||||||
9,
|
9,
|
||||||
|
2,
|
||||||
"Hacktocracy",
|
"Hacktocracy",
|
||||||
"Hacknet Unleashed",
|
"Hacknet Unleashed",
|
||||||
(
|
(
|
||||||
@ -389,6 +401,7 @@ BitNodes["BitNode9"] = new BitNode(
|
|||||||
);
|
);
|
||||||
BitNodes["BitNode10"] = new BitNode(
|
BitNodes["BitNode10"] = new BitNode(
|
||||||
10,
|
10,
|
||||||
|
2,
|
||||||
"Digital Carbon",
|
"Digital Carbon",
|
||||||
"Your body is not who you are",
|
"Your body is not who you are",
|
||||||
(
|
(
|
||||||
@ -428,6 +441,7 @@ BitNodes["BitNode10"] = new BitNode(
|
|||||||
);
|
);
|
||||||
BitNodes["BitNode11"] = new BitNode(
|
BitNodes["BitNode11"] = new BitNode(
|
||||||
11,
|
11,
|
||||||
|
1,
|
||||||
"The Big Crash",
|
"The Big Crash",
|
||||||
"Okay. Sell it all.",
|
"Okay. Sell it all.",
|
||||||
(
|
(
|
||||||
@ -492,6 +506,7 @@ BitNodes["BitNode11"] = new BitNode(
|
|||||||
);
|
);
|
||||||
BitNodes["BitNode12"] = new BitNode(
|
BitNodes["BitNode12"] = new BitNode(
|
||||||
12,
|
12,
|
||||||
|
0,
|
||||||
"The Recursion",
|
"The Recursion",
|
||||||
"Repeat.",
|
"Repeat.",
|
||||||
(
|
(
|
||||||
@ -507,18 +522,18 @@ BitNodes["BitNode12"] = new BitNode(
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
// Books: Frontera, Shiner
|
// Books: Frontera, Shiner
|
||||||
BitNodes["BitNode13"] = new BitNode(13, "fOS", "COMING SOON"); //Unlocks the new game mode and the rest of the BitNodes
|
BitNodes["BitNode13"] = new BitNode(13, 2, "fOS", "COMING SOON"); //Unlocks the new game mode and the rest of the BitNodes
|
||||||
BitNodes["BitNode14"] = new BitNode(14, "", "COMING SOON");
|
BitNodes["BitNode14"] = new BitNode(14, 2, "", "COMING SOON");
|
||||||
BitNodes["BitNode15"] = new BitNode(15, "", "COMING SOON");
|
BitNodes["BitNode15"] = new BitNode(15, 2, "", "COMING SOON");
|
||||||
BitNodes["BitNode16"] = new BitNode(16, "", "COMING SOON");
|
BitNodes["BitNode16"] = new BitNode(16, 2, "", "COMING SOON");
|
||||||
BitNodes["BitNode17"] = new BitNode(17, "", "COMING SOON");
|
BitNodes["BitNode17"] = new BitNode(17, 2, "", "COMING SOON");
|
||||||
BitNodes["BitNode18"] = new BitNode(18, "", "COMING SOON");
|
BitNodes["BitNode18"] = new BitNode(18, 2, "", "COMING SOON");
|
||||||
BitNodes["BitNode19"] = new BitNode(19, "", "COMING SOON");
|
BitNodes["BitNode19"] = new BitNode(19, 2, "", "COMING SOON");
|
||||||
BitNodes["BitNode20"] = new BitNode(20, "", "COMING SOON");
|
BitNodes["BitNode20"] = new BitNode(20, 2, "", "COMING SOON");
|
||||||
BitNodes["BitNode21"] = new BitNode(21, "", "COMING SOON");
|
BitNodes["BitNode21"] = new BitNode(21, 2, "", "COMING SOON");
|
||||||
BitNodes["BitNode22"] = new BitNode(22, "", "COMING SOON");
|
BitNodes["BitNode22"] = new BitNode(22, 2, "", "COMING SOON");
|
||||||
BitNodes["BitNode23"] = new BitNode(23, "", "COMING SOON");
|
BitNodes["BitNode23"] = new BitNode(23, 2, "", "COMING SOON");
|
||||||
BitNodes["BitNode24"] = new BitNode(24, "", "COMING SOON");
|
BitNodes["BitNode24"] = new BitNode(24, 2, "", "COMING SOON");
|
||||||
|
|
||||||
export function initBitNodeMultipliers(p: IPlayer): void {
|
export function initBitNodeMultipliers(p: IPlayer): void {
|
||||||
if (p.bitNodeN == null) {
|
if (p.bitNodeN == null) {
|
||||||
|
@ -29,6 +29,9 @@ export function PortalPopup(props: IProps): React.ReactElement {
|
|||||||
Source-File Level: {props.level} / {maxSourceFileLevel}
|
Source-File Level: {props.level} / {maxSourceFileLevel}
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
|
Difficulty: {["easy", "normal", "hard"][bitNode.difficulty]}
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
{bitNode.info}
|
{bitNode.info}
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
|
@ -22,7 +22,7 @@ export function TimeSkip(props: IProps): React.ReactElement {
|
|||||||
return () => {
|
return () => {
|
||||||
props.player.lastUpdate -= time;
|
props.player.lastUpdate -= time;
|
||||||
props.engine._lastUpdate -= time;
|
props.engine._lastUpdate -= time;
|
||||||
saveObject.saveGame(props.engine.indexedDb);
|
saveObject.saveGame();
|
||||||
setTimeout(() => location.reload(), 1000);
|
setTimeout(() => location.reload(), 1000);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
8
src/SaveObject.d.ts
vendored
8
src/SaveObject.d.ts
vendored
@ -1,2 +1,6 @@
|
|||||||
export declare const saveObject: any;
|
export declare const saveObject: {
|
||||||
export declare function openImportFileHandler(evt: any): void;
|
getSaveString: () => string;
|
||||||
|
saveGame: () => void;
|
||||||
|
exportGame: () => void;
|
||||||
|
};
|
||||||
|
export declare function loadGame(s: string): boolean;
|
||||||
|
@ -22,6 +22,7 @@ import * as ExportBonus from "./ExportBonus";
|
|||||||
import { dialogBoxCreate } from "../utils/DialogBox";
|
import { dialogBoxCreate } from "../utils/DialogBox";
|
||||||
import { clearEventListeners } from "../utils/uiHelpers/clearEventListeners";
|
import { clearEventListeners } from "../utils/uiHelpers/clearEventListeners";
|
||||||
import { Reviver, Generic_toJSON, Generic_fromJSON } from "../utils/JSONReviver";
|
import { Reviver, Generic_toJSON, Generic_fromJSON } from "../utils/JSONReviver";
|
||||||
|
import { save } from "./db";
|
||||||
|
|
||||||
import Decimal from "decimal.js";
|
import Decimal from "decimal.js";
|
||||||
|
|
||||||
@ -84,33 +85,12 @@ BitburnerSaveObject.prototype.getSaveString = function () {
|
|||||||
return saveString;
|
return saveString;
|
||||||
};
|
};
|
||||||
|
|
||||||
BitburnerSaveObject.prototype.saveGame = function (db) {
|
BitburnerSaveObject.prototype.saveGame = function () {
|
||||||
var saveString = this.getSaveString();
|
const saveString = this.getSaveString();
|
||||||
|
|
||||||
// We'll save to both localstorage and indexedDb
|
save(saveString)
|
||||||
var objectStore = db.transaction(["savestring"], "readwrite").objectStore("savestring");
|
.then(() => createStatusText("Game saved!"))
|
||||||
var request = objectStore.put(saveString, "save");
|
.catch((err) => console.error(err));
|
||||||
|
|
||||||
request.onerror = function (e) {
|
|
||||||
console.error("Error saving game to IndexedDB: " + e);
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
|
||||||
window.localStorage.setItem("bitburnerSave", saveString);
|
|
||||||
} catch (e) {
|
|
||||||
if (e.code == 22) {
|
|
||||||
createStatusText("Save failed for localStorage! Check console(F12)");
|
|
||||||
console.error(
|
|
||||||
"Failed to save game to localStorage because the size of the save file " +
|
|
||||||
"is too large. However, the game will still be saved to IndexedDb if your browser " +
|
|
||||||
"supports it. If you would like to save to localStorage as well, then " +
|
|
||||||
"consider killing several of your scripts to " +
|
|
||||||
"fix this, or increasing the size of your browsers localStorage",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
createStatusText("Game saved!");
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Makes necessary changes to the loaded/imported data to ensure
|
// Makes necessary changes to the loaded/imported data to ensure
|
||||||
@ -155,16 +135,9 @@ function evaluateVersionCompatibility(ver) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function loadGame(saveString) {
|
function loadGame(saveString) {
|
||||||
if (saveString === "" || saveString == null || saveString === undefined) {
|
|
||||||
if (!window.localStorage.getItem("bitburnerSave")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
saveString = decodeURIComponent(escape(atob(window.localStorage.getItem("bitburnerSave"))));
|
|
||||||
} else {
|
|
||||||
saveString = decodeURIComponent(escape(atob(saveString)));
|
saveString = decodeURIComponent(escape(atob(saveString)));
|
||||||
}
|
|
||||||
|
|
||||||
var saveObj = JSON.parse(saveString, Reviver);
|
const saveObj = JSON.parse(saveString, Reviver);
|
||||||
|
|
||||||
loadPlayer(saveObj.PlayerSave);
|
loadPlayer(saveObj.PlayerSave);
|
||||||
loadAllServers(saveObj.AllServersSave);
|
loadAllServers(saveObj.AllServersSave);
|
||||||
@ -224,13 +197,6 @@ function loadGame(saveString) {
|
|||||||
} else {
|
} else {
|
||||||
Settings.init();
|
Settings.init();
|
||||||
}
|
}
|
||||||
// if (saveObj.hasOwnProperty("FconfSettingsSave")) {
|
|
||||||
// try {
|
|
||||||
// loadFconf(saveObj.FconfSettingsSave);
|
|
||||||
// } catch (e) {
|
|
||||||
// console.error("ERROR: Failed to parse .fconf Settings.");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
if (saveObj.hasOwnProperty("LastExportBonus")) {
|
if (saveObj.hasOwnProperty("LastExportBonus")) {
|
||||||
try {
|
try {
|
||||||
ExportBonus.setLastExportBonus(JSON.parse(saveObj.LastExportBonus));
|
ExportBonus.setLastExportBonus(JSON.parse(saveObj.LastExportBonus));
|
||||||
@ -267,173 +233,6 @@ function loadGame(saveString) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadImportedGame(saveObj, saveString) {
|
|
||||||
var tempSaveObj = null;
|
|
||||||
var tempPlayer = null;
|
|
||||||
|
|
||||||
// Check to see if the imported save file can be parsed. If any
|
|
||||||
// errors are caught it will fail
|
|
||||||
try {
|
|
||||||
var decodedSaveString = decodeURIComponent(escape(atob(saveString)));
|
|
||||||
tempSaveObj = JSON.parse(decodedSaveString, Reviver);
|
|
||||||
|
|
||||||
tempPlayer = JSON.parse(tempSaveObj.PlayerSave, Reviver);
|
|
||||||
|
|
||||||
// Parse Decimal.js objects
|
|
||||||
tempPlayer.money = new Decimal(tempPlayer.money);
|
|
||||||
|
|
||||||
JSON.parse(tempSaveObj.AllServersSave, Reviver);
|
|
||||||
JSON.parse(tempSaveObj.CompaniesSave, Reviver);
|
|
||||||
JSON.parse(tempSaveObj.FactionsSave, Reviver);
|
|
||||||
JSON.parse(tempSaveObj.SpecialServerIpsSave, Reviver);
|
|
||||||
if (tempSaveObj.hasOwnProperty("AliasesSave")) {
|
|
||||||
try {
|
|
||||||
JSON.parse(tempSaveObj.AliasesSave, Reviver);
|
|
||||||
} catch (e) {
|
|
||||||
console.error(`Parsing Aliases save failed: ${e}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (tempSaveObj.hasOwnProperty("GlobalAliases")) {
|
|
||||||
try {
|
|
||||||
JSON.parse(tempSaveObj.AliasesSave, Reviver);
|
|
||||||
} catch (e) {
|
|
||||||
console.error(`Parsing Global Aliases save failed: ${e}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (tempSaveObj.hasOwnProperty("MessagesSave")) {
|
|
||||||
try {
|
|
||||||
JSON.parse(tempSaveObj.MessagesSave, Reviver);
|
|
||||||
} catch (e) {
|
|
||||||
console.error(`Parsing Messages save failed: ${e}`);
|
|
||||||
initMessages();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
initMessages();
|
|
||||||
}
|
|
||||||
if (saveObj.hasOwnProperty("StockMarketSave")) {
|
|
||||||
try {
|
|
||||||
JSON.parse(tempSaveObj.StockMarketSave, Reviver);
|
|
||||||
} catch (e) {
|
|
||||||
console.error(`Parsing StockMarket save failed: ${e}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (saveObj.hasOwnProperty("LastExportBonus")) {
|
|
||||||
try {
|
|
||||||
if (saveObj.LastExportBonus) ExportBonus.setLastExportBonus(JSON.parse(saveObj.LastExportBonus));
|
|
||||||
} catch (err) {
|
|
||||||
ExportBonus.setLastExportBonus(new Date().getTime());
|
|
||||||
console.error("ERROR: Failed to parse last export bonus Settings " + err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (tempSaveObj.hasOwnProperty("VersionSave")) {
|
|
||||||
try {
|
|
||||||
var ver = JSON.parse(tempSaveObj.VersionSave, Reviver);
|
|
||||||
evaluateVersionCompatibility(ver);
|
|
||||||
} catch (e) {
|
|
||||||
console.error("Parsing Version save failed: " + e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (tempPlayer.inGang() && tempSaveObj.hasOwnProperty("AllGangsSave")) {
|
|
||||||
try {
|
|
||||||
loadAllGangs(tempSaveObj.AllGangsSave);
|
|
||||||
} catch (e) {
|
|
||||||
console.error(`Failed to parse AllGangsSave: {e}`);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
dialogBoxCreate("Error importing game: " + e.toString());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Since the save file is valid, load everything for real
|
|
||||||
saveString = decodeURIComponent(escape(atob(saveString)));
|
|
||||||
saveObj = JSON.parse(saveString, Reviver);
|
|
||||||
|
|
||||||
loadPlayer(saveObj.PlayerSave);
|
|
||||||
loadAllServers(saveObj.AllServersSave);
|
|
||||||
loadCompanies(saveObj.CompaniesSave);
|
|
||||||
loadFactions(saveObj.FactionsSave);
|
|
||||||
loadSpecialServerIps(saveObj.SpecialServerIpsSave);
|
|
||||||
|
|
||||||
if (saveObj.hasOwnProperty("AliasesSave")) {
|
|
||||||
try {
|
|
||||||
loadAliases(saveObj.AliasesSave);
|
|
||||||
} catch (e) {
|
|
||||||
loadAliases("");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
loadAliases("");
|
|
||||||
}
|
|
||||||
if (saveObj.hasOwnProperty("GlobalAliasesSave")) {
|
|
||||||
try {
|
|
||||||
loadGlobalAliases(saveObj.GlobalAliasesSave);
|
|
||||||
} catch (e) {
|
|
||||||
loadGlobalAliases("");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
loadGlobalAliases("");
|
|
||||||
}
|
|
||||||
if (saveObj.hasOwnProperty("MessagesSave")) {
|
|
||||||
try {
|
|
||||||
loadMessages(saveObj.MessagesSave);
|
|
||||||
} catch (e) {
|
|
||||||
initMessages();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
initMessages();
|
|
||||||
}
|
|
||||||
if (saveObj.hasOwnProperty("StockMarketSave")) {
|
|
||||||
try {
|
|
||||||
loadStockMarket(saveObj.StockMarketSave);
|
|
||||||
} catch (e) {
|
|
||||||
loadStockMarket("");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
loadStockMarket("");
|
|
||||||
}
|
|
||||||
if (saveObj.hasOwnProperty("SettingsSave")) {
|
|
||||||
try {
|
|
||||||
Settings.load(saveObj.SettingsSave);
|
|
||||||
} catch (e) {
|
|
||||||
Settings.init();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Settings.init();
|
|
||||||
}
|
|
||||||
// if (saveObj.hasOwnProperty("FconfSettingsSave")) {
|
|
||||||
// try {
|
|
||||||
// loadFconf(saveObj.FconfSettingsSave);
|
|
||||||
// } catch (e) {
|
|
||||||
// console.error("ERROR: Failed to load .fconf settings when importing");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
if (saveObj.hasOwnProperty("VersionSave")) {
|
|
||||||
try {
|
|
||||||
var ver = JSON.parse(saveObj.VersionSave, Reviver);
|
|
||||||
evaluateVersionCompatibility(ver);
|
|
||||||
|
|
||||||
if (ver != CONSTANTS.Version) {
|
|
||||||
createNewUpdateText();
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
createNewUpdateText();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
createNewUpdateText();
|
|
||||||
}
|
|
||||||
if (Player.inGang() && saveObj.hasOwnProperty("AllGangsSave")) {
|
|
||||||
try {
|
|
||||||
loadAllGangs(saveObj.AllGangsSave);
|
|
||||||
} catch (e) {
|
|
||||||
console.error("ERROR: Failed to parse AllGangsSave: " + e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
saveObject.saveGame(Engine.indexedDb);
|
|
||||||
setTimeout(() => location.reload(), 1000);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
BitburnerSaveObject.prototype.exportGame = function () {
|
BitburnerSaveObject.prototype.exportGame = function () {
|
||||||
const saveString = this.getSaveString();
|
const saveString = this.getSaveString();
|
||||||
|
|
||||||
@ -460,31 +259,6 @@ BitburnerSaveObject.prototype.exportGame = function () {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
BitburnerSaveObject.prototype.importGame = function () {
|
|
||||||
if (window.File && window.FileReader && window.FileList && window.Blob) {
|
|
||||||
var fileSelector = clearEventListeners("import-game-file-selector");
|
|
||||||
fileSelector.addEventListener("change", openImportFileHandler, false);
|
|
||||||
$("#import-game-file-selector").click();
|
|
||||||
} else {
|
|
||||||
dialogBoxCreate("ERR: Your browser does not support HTML5 File API. Cannot import.");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
BitburnerSaveObject.prototype.deleteGame = function (db) {
|
|
||||||
// Delete from local storage
|
|
||||||
if (window.localStorage.getItem("bitburnerSave")) {
|
|
||||||
window.localStorage.removeItem("bitburnerSave");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete from indexedDB
|
|
||||||
var request = db.transaction(["savestring"], "readwrite").objectStore("savestring").delete("save");
|
|
||||||
request.onsuccess = function () {};
|
|
||||||
request.onerror = function (e) {
|
|
||||||
console.error(`Failed to delete save from indexedDb: ${e}`);
|
|
||||||
};
|
|
||||||
createStatusText("Game deleted!");
|
|
||||||
};
|
|
||||||
|
|
||||||
function createNewUpdateText() {
|
function createNewUpdateText() {
|
||||||
dialogBoxCreate(
|
dialogBoxCreate(
|
||||||
"New update!<br>" +
|
"New update!<br>" +
|
||||||
@ -514,19 +288,4 @@ BitburnerSaveObject.fromJSON = function (value) {
|
|||||||
|
|
||||||
Reviver.constructors.BitburnerSaveObject = BitburnerSaveObject;
|
Reviver.constructors.BitburnerSaveObject = BitburnerSaveObject;
|
||||||
|
|
||||||
function openImportFileHandler(evt) {
|
export { saveObject, loadGame };
|
||||||
var file = evt.target.files[0];
|
|
||||||
if (!file) {
|
|
||||||
dialogBoxCreate("Invalid file selected");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var reader = new FileReader();
|
|
||||||
reader.onload = function (e) {
|
|
||||||
var contents = e.target.result;
|
|
||||||
loadImportedGame(saveObject, contents);
|
|
||||||
};
|
|
||||||
reader.readAsText(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
export { saveObject, loadGame, openImportFileHandler };
|
|
||||||
|
@ -61,7 +61,6 @@ import { scananalyze } from "./commands/scananalyze";
|
|||||||
import { scp } from "./commands/scp";
|
import { scp } from "./commands/scp";
|
||||||
import { sudov } from "./commands/sudov";
|
import { sudov } from "./commands/sudov";
|
||||||
import { tail } from "./commands/tail";
|
import { tail } from "./commands/tail";
|
||||||
import { theme } from "./commands/theme";
|
|
||||||
import { top } from "./commands/top";
|
import { top } from "./commands/top";
|
||||||
import { unalias } from "./commands/unalias";
|
import { unalias } from "./commands/unalias";
|
||||||
import { wget } from "./commands/wget";
|
import { wget } from "./commands/wget";
|
||||||
@ -683,7 +682,6 @@ export class Terminal implements ITerminal {
|
|||||||
scp: scp,
|
scp: scp,
|
||||||
sudov: sudov,
|
sudov: sudov,
|
||||||
tail: tail,
|
tail: tail,
|
||||||
theme: theme,
|
|
||||||
top: top,
|
top: top,
|
||||||
unalias: unalias,
|
unalias: unalias,
|
||||||
wget: wget,
|
wget: wget,
|
||||||
|
@ -1,60 +0,0 @@
|
|||||||
import { ITerminal } from "../ITerminal";
|
|
||||||
import { IRouter } from "../../ui/Router";
|
|
||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
|
||||||
import { BaseServer } from "../../Server/BaseServer";
|
|
||||||
import { FconfSettings } from "../../Fconf/FconfSettings";
|
|
||||||
|
|
||||||
export function theme(
|
|
||||||
terminal: ITerminal,
|
|
||||||
router: IRouter,
|
|
||||||
player: IPlayer,
|
|
||||||
server: BaseServer,
|
|
||||||
args: (string | number)[],
|
|
||||||
): void {
|
|
||||||
if (args.length !== 1 && args.length !== 3) {
|
|
||||||
terminal.error("Incorrect number of arguments.");
|
|
||||||
terminal.error(
|
|
||||||
"Usage: theme [default|muted|solarized] | #[background color hex] #[text color hex] #[highlight color hex]",
|
|
||||||
);
|
|
||||||
} else if (args.length === 1) {
|
|
||||||
const themeName = args[0];
|
|
||||||
if (themeName == "default") {
|
|
||||||
document.body.style.setProperty("--my-highlight-color", "#ffffff");
|
|
||||||
document.body.style.setProperty("--my-font-color", "#66ff33");
|
|
||||||
document.body.style.setProperty("--my-background-color", "#000000");
|
|
||||||
document.body.style.setProperty("--my-prompt-color", "#f92672");
|
|
||||||
} else if (themeName == "muted") {
|
|
||||||
document.body.style.setProperty("--my-highlight-color", "#ffffff");
|
|
||||||
document.body.style.setProperty("--my-font-color", "#66ff33");
|
|
||||||
document.body.style.setProperty("--my-background-color", "#252527");
|
|
||||||
} else if (themeName == "solarized") {
|
|
||||||
document.body.style.setProperty("--my-highlight-color", "#6c71c4");
|
|
||||||
document.body.style.setProperty("--my-font-color", "#839496");
|
|
||||||
document.body.style.setProperty("--my-background-color", "#002b36");
|
|
||||||
} else {
|
|
||||||
return terminal.error("Theme not found");
|
|
||||||
}
|
|
||||||
FconfSettings.THEME_HIGHLIGHT_COLOR = document.body.style.getPropertyValue("--my-highlight-color");
|
|
||||||
FconfSettings.THEME_FONT_COLOR = document.body.style.getPropertyValue("--my-font-color");
|
|
||||||
FconfSettings.THEME_BACKGROUND_COLOR = document.body.style.getPropertyValue("--my-background-color");
|
|
||||||
FconfSettings.THEME_PROMPT_COLOR = document.body.style.getPropertyValue("--my-prompt-color");
|
|
||||||
} else {
|
|
||||||
const inputBackgroundHex = args[0] + "";
|
|
||||||
const inputTextHex = args[1] + "";
|
|
||||||
const inputHighlightHex = args[2] + "";
|
|
||||||
if (
|
|
||||||
/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(inputBackgroundHex) &&
|
|
||||||
/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(inputTextHex) &&
|
|
||||||
/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(inputHighlightHex)
|
|
||||||
) {
|
|
||||||
document.body.style.setProperty("--my-highlight-color", inputHighlightHex);
|
|
||||||
document.body.style.setProperty("--my-font-color", inputTextHex);
|
|
||||||
document.body.style.setProperty("--my-background-color", inputBackgroundHex);
|
|
||||||
FconfSettings.THEME_HIGHLIGHT_COLOR = document.body.style.getPropertyValue("--my-highlight-color");
|
|
||||||
FconfSettings.THEME_FONT_COLOR = document.body.style.getPropertyValue("--my-font-color");
|
|
||||||
FconfSettings.THEME_BACKGROUND_COLOR = document.body.style.getPropertyValue("--my-background-color");
|
|
||||||
} else {
|
|
||||||
return terminal.error("Invalid Hex Input for theme");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
86
src/db.tsx
Normal file
86
src/db.tsx
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
import { Engine } from "./engine";
|
||||||
|
import { createStatusText } from "./ui/createStatusText";
|
||||||
|
|
||||||
|
function getDB(): Promise<IDBObjectStore> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (!window.indexedDB) {
|
||||||
|
reject("Indexed DB does not exists");
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* DB is called bitburnerSave
|
||||||
|
* Object store is called savestring
|
||||||
|
* key for the Object store is called save
|
||||||
|
* Version `1` is important
|
||||||
|
*/
|
||||||
|
const indexedDbRequest: IDBOpenDBRequest = window.indexedDB.open("bitburnerSave", 1);
|
||||||
|
|
||||||
|
// This is called when there's no db to begin with. It's important, don't remove it.
|
||||||
|
indexedDbRequest.onupgradeneeded = function (this: IDBRequest<IDBDatabase>) {
|
||||||
|
const db = this.result;
|
||||||
|
db.createObjectStore("savestring");
|
||||||
|
};
|
||||||
|
|
||||||
|
indexedDbRequest.onerror = function (this: IDBRequest<IDBDatabase>, ev: Event) {
|
||||||
|
reject(`Failed to get IDB ${ev}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
indexedDbRequest.onsuccess = function (this: IDBRequest<IDBDatabase>, ev: Event) {
|
||||||
|
const db = this.result;
|
||||||
|
if (!db) {
|
||||||
|
reject("database loadign result was undefined");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resolve(db.transaction(["savestring"], "readwrite").objectStore("savestring"));
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ILoadCallback {
|
||||||
|
success: (s: string) => void;
|
||||||
|
error?: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function load(): Promise<string> {
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
await getDB()
|
||||||
|
.then((db) => {
|
||||||
|
return new Promise<string>((resolve, reject) => {
|
||||||
|
const request: IDBRequest<string> = db.get("save");
|
||||||
|
request.onerror = function (this: IDBRequest<string>, ev: Event) {
|
||||||
|
reject("Error in Database request to get savestring: " + ev);
|
||||||
|
};
|
||||||
|
|
||||||
|
request.onsuccess = function (this: IDBRequest<string>) {
|
||||||
|
resolve(this.result);
|
||||||
|
};
|
||||||
|
}).then((saveString) => resolve(saveString));
|
||||||
|
})
|
||||||
|
.catch((r) => reject(r));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ISaveCallback {
|
||||||
|
success: () => void;
|
||||||
|
error?: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function save(saveString: string): Promise<void> {
|
||||||
|
return getDB().then((db) => {
|
||||||
|
return new Promise<void>((resolve, reject) => {
|
||||||
|
// We'll save to both localstorage and indexedDb
|
||||||
|
const request = db.put(saveString, "save");
|
||||||
|
|
||||||
|
request.onerror = function (e) {
|
||||||
|
reject("Error saving game to IndexedDB: " + e);
|
||||||
|
};
|
||||||
|
|
||||||
|
request.onsuccess = () => resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function deleteGame(): Promise<void> {
|
||||||
|
return getDB().then((db) => {
|
||||||
|
db.delete("save");
|
||||||
|
});
|
||||||
|
}
|
2
src/engine.d.ts
vendored
2
src/engine.d.ts
vendored
@ -1,3 +1 @@
|
|||||||
export declare function load(cb: () => void): void;
|
|
||||||
|
|
||||||
export declare const Engine: IEngine;
|
export declare const Engine: IEngine;
|
||||||
|
@ -50,8 +50,6 @@ import "./Exploits/unclickable";
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
const Engine = {
|
const Engine = {
|
||||||
indexedDb: undefined,
|
|
||||||
|
|
||||||
// Time variables (milliseconds unix epoch time)
|
// Time variables (milliseconds unix epoch time)
|
||||||
_lastUpdate: new Date().getTime(),
|
_lastUpdate: new Date().getTime(),
|
||||||
|
|
||||||
@ -196,7 +194,7 @@ const Engine = {
|
|||||||
Engine.Counters.autoSaveCounter = Infinity;
|
Engine.Counters.autoSaveCounter = Infinity;
|
||||||
} else {
|
} else {
|
||||||
Engine.Counters.autoSaveCounter = Settings.AutosaveInterval * 5;
|
Engine.Counters.autoSaveCounter = Settings.AutosaveInterval * 5;
|
||||||
saveObject.saveGame(Engine.indexedDb);
|
saveObject.saveGame();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -420,48 +418,4 @@ const Engine = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
function load(cb) {
|
export { Engine };
|
||||||
if (!window.indexedDB) {
|
|
||||||
return Engine.load(null); // Will try to load from localstorage
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DB is called bitburnerSave
|
|
||||||
* Object store is called savestring
|
|
||||||
* key for the Object store is called save
|
|
||||||
*/
|
|
||||||
indexedDbRequest = window.indexedDB.open("bitburnerSave", 1);
|
|
||||||
|
|
||||||
indexedDbRequest.onerror = function (e) {
|
|
||||||
console.error("Error opening indexedDB: ");
|
|
||||||
console.error(e);
|
|
||||||
Engine.load(null); // Try to load from localstorage
|
|
||||||
cb();
|
|
||||||
};
|
|
||||||
|
|
||||||
indexedDbRequest.onsuccess = function (e) {
|
|
||||||
Engine.indexedDb = e.target.result;
|
|
||||||
var transaction = Engine.indexedDb.transaction(["savestring"]);
|
|
||||||
var objectStore = transaction.objectStore("savestring");
|
|
||||||
var request = objectStore.get("save");
|
|
||||||
request.onerror = function (e) {
|
|
||||||
console.error("Error in Database request to get savestring: " + e);
|
|
||||||
Engine.load(null); // Try to load from localstorage
|
|
||||||
cb();
|
|
||||||
};
|
|
||||||
|
|
||||||
request.onsuccess = function () {
|
|
||||||
Engine.load(request.result);
|
|
||||||
cb();
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
indexedDbRequest.onupgradeneeded = function (e) {
|
|
||||||
const db = e.target.result;
|
|
||||||
db.createObjectStore("savestring");
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
var indexedDbRequest;
|
|
||||||
|
|
||||||
export { Engine, load };
|
|
||||||
|
@ -4,7 +4,7 @@ import { IPlayer } from "../PersonObjects/IPlayer";
|
|||||||
import { IEngine } from "../IEngine";
|
import { IEngine } from "../IEngine";
|
||||||
import { ITerminal } from "../Terminal/ITerminal";
|
import { ITerminal } from "../Terminal/ITerminal";
|
||||||
import { installAugmentations } from "../Augmentation/AugmentationHelpers";
|
import { installAugmentations } from "../Augmentation/AugmentationHelpers";
|
||||||
import { saveObject, openImportFileHandler } from "../SaveObject";
|
import { saveObject } from "../SaveObject";
|
||||||
import { onExport } from "../ExportBonus";
|
import { onExport } from "../ExportBonus";
|
||||||
import { LocationName } from "../Locations/data/LocationNames";
|
import { LocationName } from "../Locations/data/LocationNames";
|
||||||
import { Location } from "../Locations/Location";
|
import { Location } from "../Locations/Location";
|
||||||
@ -282,7 +282,7 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
|
|||||||
<Context.Router.Provider value={Router}>
|
<Context.Router.Provider value={Router}>
|
||||||
<Overview>
|
<Overview>
|
||||||
{!ITutorial.isRunning ? (
|
{!ITutorial.isRunning ? (
|
||||||
<CharacterOverview save={() => saveObject.saveGame(engine.indexedDb)} />
|
<CharacterOverview save={() => saveObject.saveGame()} />
|
||||||
) : (
|
) : (
|
||||||
<InteractiveTutorialRoot />
|
<InteractiveTutorialRoot />
|
||||||
)}
|
)}
|
||||||
@ -357,10 +357,8 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
|
|||||||
) : page === Page.Options ? (
|
) : page === Page.Options ? (
|
||||||
<GameOptionsRoot
|
<GameOptionsRoot
|
||||||
player={player}
|
player={player}
|
||||||
save={() => saveObject.saveGame(engine.indexedDb)}
|
save={() => saveObject.saveGame()}
|
||||||
delete={() => saveObject.deleteGame(engine.indexedDb)}
|
|
||||||
export={() => saveObject.exportGame()}
|
export={() => saveObject.exportGame()}
|
||||||
import={openImportFileHandler}
|
|
||||||
forceKill={() => {
|
forceKill={() => {
|
||||||
for (const hostname of Object.keys(AllServers)) {
|
for (const hostname of Object.keys(AllServers)) {
|
||||||
AllServers[hostname].runningScripts = [];
|
AllServers[hostname].runningScripts = [];
|
||||||
|
@ -4,56 +4,13 @@ import Typography from "@mui/material/Typography";
|
|||||||
import Grid from "@mui/material/Grid";
|
import Grid from "@mui/material/Grid";
|
||||||
|
|
||||||
import { Terminal } from "../Terminal";
|
import { Terminal } from "../Terminal";
|
||||||
import { Engine } from "../engine";
|
import { load } from "../db";
|
||||||
import { Player } from "../Player";
|
import { Player } from "../Player";
|
||||||
|
import { Engine } from "../engine";
|
||||||
import { GameRoot } from "./GameRoot";
|
import { GameRoot } from "./GameRoot";
|
||||||
|
|
||||||
import { CONSTANTS } from "../Constants";
|
import { CONSTANTS } from "../Constants";
|
||||||
|
|
||||||
function load(cb: () => void): void {
|
|
||||||
if (!window.indexedDB) {
|
|
||||||
return Engine.load(""); // Will try to load from localstorage
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DB is called bitburnerSave
|
|
||||||
* Object store is called savestring
|
|
||||||
* key for the Object store is called save
|
|
||||||
*/
|
|
||||||
// Version 1 is important
|
|
||||||
const indexedDbRequest: IDBOpenDBRequest = window.indexedDB.open("bitburnerSave", 1);
|
|
||||||
|
|
||||||
indexedDbRequest.onerror = function (this: IDBRequest<IDBDatabase>, ev: Event) {
|
|
||||||
console.error("Error opening indexedDB: ");
|
|
||||||
console.error(ev);
|
|
||||||
Engine.load(""); // Try to load from localstorage
|
|
||||||
cb();
|
|
||||||
};
|
|
||||||
|
|
||||||
indexedDbRequest.onsuccess = function (this: IDBRequest<IDBDatabase>) {
|
|
||||||
Engine.indexedDb = this.result;
|
|
||||||
const transaction = Engine.indexedDb.transaction(["savestring"]);
|
|
||||||
const objectStore = transaction.objectStore("savestring");
|
|
||||||
const request: IDBRequest<string> = objectStore.get("save");
|
|
||||||
request.onerror = function (this: IDBRequest<string>, ev: Event) {
|
|
||||||
console.error("Error in Database request to get savestring: " + ev);
|
|
||||||
Engine.load(""); // Try to load from localstorage
|
|
||||||
cb();
|
|
||||||
};
|
|
||||||
|
|
||||||
request.onsuccess = function (this: IDBRequest<string>) {
|
|
||||||
Engine.load(this.result);
|
|
||||||
cb();
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// This is called when there's no db to begin with. It's important.
|
|
||||||
indexedDbRequest.onupgradeneeded = function (this: IDBRequest<IDBDatabase>) {
|
|
||||||
const db = this.result;
|
|
||||||
db.createObjectStore("savestring");
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function LoadingScreen(): React.ReactElement {
|
export function LoadingScreen(): React.ReactElement {
|
||||||
const [show, setShow] = useState(false);
|
const [show, setShow] = useState(false);
|
||||||
const [loaded, setLoaded] = useState(false);
|
const [loaded, setLoaded] = useState(false);
|
||||||
@ -66,9 +23,19 @@ export function LoadingScreen(): React.ReactElement {
|
|||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
load(() => {
|
async function doLoad() {
|
||||||
|
await load()
|
||||||
|
.then((saveString) => {
|
||||||
|
Engine.load(saveString);
|
||||||
|
setLoaded(true);
|
||||||
|
})
|
||||||
|
.catch((reason) => {
|
||||||
|
console.error(reason);
|
||||||
|
Engine.load("");
|
||||||
setLoaded(true);
|
setLoaded(true);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
doLoad();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
if (loaded) {
|
if (loaded) {
|
||||||
|
@ -28,6 +28,7 @@ import { dialogBoxCreate } from "../../../utils/DialogBox";
|
|||||||
import { ConfirmationModal } from "./ConfirmationModal";
|
import { ConfirmationModal } from "./ConfirmationModal";
|
||||||
|
|
||||||
import { Settings } from "../../Settings/Settings";
|
import { Settings } from "../../Settings/Settings";
|
||||||
|
import { save, deleteGame } from "../../db";
|
||||||
|
|
||||||
const useStyles = makeStyles((theme: Theme) =>
|
const useStyles = makeStyles((theme: Theme) =>
|
||||||
createStyles({
|
createStyles({
|
||||||
@ -42,9 +43,7 @@ const useStyles = makeStyles((theme: Theme) =>
|
|||||||
interface IProps {
|
interface IProps {
|
||||||
player: IPlayer;
|
player: IPlayer;
|
||||||
save: () => void;
|
save: () => void;
|
||||||
delete: () => void;
|
|
||||||
export: () => void;
|
export: () => void;
|
||||||
import: (evt: any) => void;
|
|
||||||
forceKill: () => void;
|
forceKill: () => void;
|
||||||
softReset: () => void;
|
softReset: () => void;
|
||||||
}
|
}
|
||||||
@ -153,20 +152,38 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
|
|||||||
Settings.Locale = event.target.value as string;
|
Settings.Locale = event.target.value as string;
|
||||||
}
|
}
|
||||||
|
|
||||||
function importSave(): void {
|
function startImport(): void {
|
||||||
if (window.File && window.FileReader && window.FileList && window.Blob) {
|
if (!window.File || !window.FileReader || !window.FileList || !window.Blob) return;
|
||||||
// var fileSelector = clearEventListeners("import-game-file-selector");
|
|
||||||
// fileSelector.addEventListener("change", openImportFileHandler, false);
|
|
||||||
const ii = importInput.current;
|
const ii = importInput.current;
|
||||||
if (ii === null) throw new Error("import input should not be null");
|
if (ii === null) throw new Error("import input should not be null");
|
||||||
ii.click();
|
ii.click();
|
||||||
} else {
|
|
||||||
dialogBoxCreate("ERR: Your browser does not support HTML5 File API. Cannot import.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function onImport(event: React.ChangeEvent<HTMLInputElement>): void {
|
function onImport(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||||
props.import(event);
|
const files = event.target.files;
|
||||||
|
if (files === null) return;
|
||||||
|
const file = files[0];
|
||||||
|
if (!file) {
|
||||||
|
dialogBoxCreate("Invalid file selected");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = function (this: FileReader, e: ProgressEvent<FileReader>) {
|
||||||
|
const target = e.target;
|
||||||
|
if (target === null) {
|
||||||
|
console.error("error importing file");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const result = target.result;
|
||||||
|
if (typeof result !== "string" || result === null) {
|
||||||
|
console.error("FileReader event was not type string");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const contents = result;
|
||||||
|
save(contents).then(() => location.reload());
|
||||||
|
};
|
||||||
|
reader.readAsText(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -490,7 +507,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
|
|||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip title={<Typography>import</Typography>}>
|
<Tooltip title={<Typography>import</Typography>}>
|
||||||
<Button onClick={importSave}>
|
<Button onClick={startImport}>
|
||||||
<UploadIcon color="primary" />
|
<UploadIcon color="primary" />
|
||||||
Import
|
Import
|
||||||
<input ref={importInput} id="import-game-file-selector" type="file" hidden onChange={onImport} />
|
<input ref={importInput} id="import-game-file-selector" type="file" hidden onChange={onImport} />
|
||||||
@ -554,8 +571,10 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
|
|||||||
<FileDiagnosticModal open={diagnosticOpen} onClose={() => setDiagnosticOpen(false)} />
|
<FileDiagnosticModal open={diagnosticOpen} onClose={() => setDiagnosticOpen(false)} />
|
||||||
<ConfirmationModal
|
<ConfirmationModal
|
||||||
onConfirm={() => {
|
onConfirm={() => {
|
||||||
props.delete();
|
|
||||||
setDeleteOpen(false);
|
setDeleteOpen(false);
|
||||||
|
deleteGame()
|
||||||
|
.then(() => location.reload())
|
||||||
|
.catch((r) => console.error(`Could not delete game: ${r}`));
|
||||||
}}
|
}}
|
||||||
open={deleteGameOpen}
|
open={deleteGameOpen}
|
||||||
onClose={() => setDeleteOpen(false)}
|
onClose={() => setDeleteOpen(false)}
|
||||||
|
Loading…
Reference in New Issue
Block a user