2021-09-09 05:47:34 +02:00
|
|
|
import { loadAliases, loadGlobalAliases, Aliases, GlobalAliases } from "./Alias";
|
2019-04-11 10:37:40 +02:00
|
|
|
import { Companies, loadCompanies } from "./Company/Companies";
|
|
|
|
import { CONSTANTS } from "./Constants";
|
|
|
|
import { Factions, loadFactions } from "./Faction/Factions";
|
2021-06-16 06:28:20 +02:00
|
|
|
import { loadAllGangs, AllGangs } from "./Gang/AllGangs";
|
2019-03-05 02:40:28 +01:00
|
|
|
import { loadMessages, initMessages, Messages } from "./Message/MessageHelpers";
|
2019-04-11 10:37:40 +02:00
|
|
|
import { Player, loadPlayer } from "./Player";
|
2021-10-27 21:16:16 +02:00
|
|
|
import { saveAllServers, loadAllServers, GetAllServers } from "./Server/AllServers";
|
2019-04-11 10:37:40 +02:00
|
|
|
import { Settings } from "./Settings/Settings";
|
2019-05-14 10:35:37 +02:00
|
|
|
import { SourceFileFlags } from "./SourceFile/SourceFileFlags";
|
2019-04-11 10:37:40 +02:00
|
|
|
import { loadStockMarket, StockMarket } from "./StockMarket/StockMarket";
|
2019-02-20 09:42:27 +01:00
|
|
|
|
2021-10-13 23:25:58 +02:00
|
|
|
import { SnackbarEvents } from "./ui/React/Snackbar";
|
2017-08-30 19:44:29 +02:00
|
|
|
|
2021-05-18 05:59:45 +02:00
|
|
|
import * as ExportBonus from "./ExportBonus";
|
2019-04-11 10:37:40 +02:00
|
|
|
|
2021-09-25 20:42:57 +02:00
|
|
|
import { dialogBoxCreate } from "./ui/React/DialogBox";
|
|
|
|
import { Reviver, Generic_toJSON, Generic_fromJSON } from "./utils/JSONReviver";
|
2021-09-21 22:49:38 +02:00
|
|
|
import { save } from "./db";
|
2019-04-11 10:37:40 +02:00
|
|
|
|
2017-07-25 16:39:56 +02:00
|
|
|
/* SaveObject.js
|
|
|
|
* Defines the object used to save/load games
|
2017-05-05 03:08:44 +02:00
|
|
|
*/
|
|
|
|
|
2021-09-25 00:40:17 +02:00
|
|
|
class BitburnerSaveObject {
|
|
|
|
PlayerSave = "";
|
|
|
|
AllServersSave = "";
|
|
|
|
CompaniesSave = "";
|
|
|
|
FactionsSave = "";
|
|
|
|
AliasesSave = "";
|
|
|
|
GlobalAliasesSave = "";
|
|
|
|
MessagesSave = "";
|
|
|
|
StockMarketSave = "";
|
|
|
|
SettingsSave = "";
|
|
|
|
VersionSave = "";
|
|
|
|
AllGangsSave = "";
|
|
|
|
LastExportBonus = "";
|
|
|
|
|
|
|
|
getSaveString(): string {
|
|
|
|
this.PlayerSave = JSON.stringify(Player);
|
|
|
|
|
2021-10-07 22:04:04 +02:00
|
|
|
this.AllServersSave = saveAllServers();
|
2021-09-25 00:40:17 +02:00
|
|
|
this.CompaniesSave = JSON.stringify(Companies);
|
|
|
|
this.FactionsSave = JSON.stringify(Factions);
|
|
|
|
this.AliasesSave = JSON.stringify(Aliases);
|
|
|
|
this.GlobalAliasesSave = JSON.stringify(GlobalAliases);
|
|
|
|
this.MessagesSave = JSON.stringify(Messages);
|
|
|
|
this.StockMarketSave = JSON.stringify(StockMarket);
|
|
|
|
this.SettingsSave = JSON.stringify(Settings);
|
|
|
|
this.VersionSave = JSON.stringify(CONSTANTS.Version);
|
|
|
|
this.LastExportBonus = JSON.stringify(ExportBonus.LastExportBonus);
|
|
|
|
if (Player.inGang()) {
|
|
|
|
this.AllGangsSave = JSON.stringify(AllGangs);
|
2017-10-12 04:00:22 +02:00
|
|
|
}
|
2021-09-25 07:26:03 +02:00
|
|
|
const saveString = btoa(unescape(encodeURIComponent(JSON.stringify(this))));
|
2021-09-25 00:40:17 +02:00
|
|
|
|
|
|
|
return saveString;
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
|
2021-09-25 00:40:17 +02:00
|
|
|
saveGame(): void {
|
|
|
|
const saveString = this.getSaveString();
|
|
|
|
|
|
|
|
save(saveString)
|
2021-10-13 23:25:58 +02:00
|
|
|
.then(() => SnackbarEvents.emit("Game Saved!", "info"))
|
2021-09-25 00:40:17 +02:00
|
|
|
.catch((err) => console.error(err));
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
|
2021-09-25 00:40:17 +02:00
|
|
|
exportGame(): void {
|
|
|
|
const saveString = this.getSaveString();
|
|
|
|
|
|
|
|
// Save file name is based on current timestamp and BitNode
|
|
|
|
const epochTime = Math.round(Date.now() / 1000);
|
|
|
|
const bn = Player.bitNodeN;
|
|
|
|
const filename = `bitburnerSave_BN${bn}x${SourceFileFlags[bn]}_${epochTime}.json`;
|
2021-09-25 07:26:03 +02:00
|
|
|
const file = new Blob([saveString], { type: "text/plain" });
|
2021-10-13 08:27:55 +02:00
|
|
|
const navigator = window.navigator as any;
|
|
|
|
if (navigator.msSaveOrOpenBlob) {
|
2021-09-25 00:40:17 +02:00
|
|
|
// IE10+
|
2021-10-13 08:27:55 +02:00
|
|
|
navigator.msSaveOrOpenBlob(file, filename);
|
2021-09-25 00:40:17 +02:00
|
|
|
} else {
|
|
|
|
// Others
|
2021-09-25 07:26:03 +02:00
|
|
|
const a = document.createElement("a"),
|
2021-09-25 00:40:17 +02:00
|
|
|
url = URL.createObjectURL(file);
|
|
|
|
a.href = url;
|
|
|
|
a.download = filename;
|
|
|
|
document.body.appendChild(a);
|
|
|
|
a.click();
|
2021-10-05 01:58:34 +02:00
|
|
|
setTimeout(function () {
|
2021-09-25 00:40:17 +02:00
|
|
|
document.body.removeChild(a);
|
|
|
|
window.URL.revokeObjectURL(url);
|
|
|
|
}, 0);
|
|
|
|
}
|
|
|
|
}
|
2021-09-05 01:09:30 +02:00
|
|
|
|
2021-09-25 00:40:17 +02:00
|
|
|
toJSON(): any {
|
|
|
|
return Generic_toJSON("BitburnerSaveObject", this);
|
|
|
|
}
|
2017-09-19 20:38:03 +02:00
|
|
|
|
2021-09-25 00:40:17 +02:00
|
|
|
static fromJSON(value: { data: any }): BitburnerSaveObject {
|
|
|
|
return Generic_fromJSON(BitburnerSaveObject, value.data);
|
|
|
|
}
|
|
|
|
}
|
2017-05-05 03:08:44 +02:00
|
|
|
|
2018-11-16 04:45:03 +01:00
|
|
|
// Makes necessary changes to the loaded/imported data to ensure
|
|
|
|
// the game stills works with new versions
|
2021-09-25 07:26:03 +02:00
|
|
|
function evaluateVersionCompatibility(ver: string): void {
|
2021-09-25 00:40:17 +02:00
|
|
|
// We have to do this because ts won't let us otherwise
|
|
|
|
const anyPlayer = Player as any;
|
2021-09-05 01:09:30 +02:00
|
|
|
// This version refactored the Company/job-related code
|
|
|
|
if (ver <= "0.41.2") {
|
|
|
|
// Player's company position is now a string
|
2021-09-25 00:40:17 +02:00
|
|
|
if (anyPlayer.companyPosition != null && typeof anyPlayer.companyPosition !== "string") {
|
|
|
|
anyPlayer.companyPosition = anyPlayer.companyPosition.data.positionName;
|
|
|
|
if (anyPlayer.companyPosition == null) {
|
|
|
|
anyPlayer.companyPosition = "";
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2018-11-16 04:45:03 +01:00
|
|
|
}
|
2019-01-15 04:34:04 +01:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
// The "companyName" property of all Companies is renamed to "name"
|
2021-09-25 00:40:17 +02:00
|
|
|
for (const companyName in Companies) {
|
|
|
|
const company: any = Companies[companyName];
|
|
|
|
if (company.name == 0 && company.companyName != null) {
|
2021-09-05 01:09:30 +02:00
|
|
|
company.name = company.companyName;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (company.companyPositions instanceof Array) {
|
2021-09-25 00:40:17 +02:00
|
|
|
const pos: any = {};
|
2021-09-05 01:09:30 +02:00
|
|
|
|
|
|
|
for (let i = 0; i < company.companyPositions.length; ++i) {
|
|
|
|
pos[company.companyPositions[i]] = true;
|
2019-01-15 04:34:04 +01:00
|
|
|
}
|
2021-09-05 01:09:30 +02:00
|
|
|
company.companyPositions = pos;
|
|
|
|
}
|
2019-01-15 04:34:04 +01:00
|
|
|
}
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// This version allowed players to hold multiple jobs
|
|
|
|
if (ver < "0.43.0") {
|
2021-09-25 00:40:17 +02:00
|
|
|
if (anyPlayer.companyName !== "" && anyPlayer.companyPosition != null && anyPlayer.companyPosition !== "") {
|
|
|
|
anyPlayer.jobs[anyPlayer.companyName] = anyPlayer.companyPosition;
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
|
2021-09-25 00:40:17 +02:00
|
|
|
delete anyPlayer.companyPosition;
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2021-10-12 06:29:16 +02:00
|
|
|
if (ver < "0.56.0") {
|
|
|
|
for (const q of anyPlayer.queuedAugmentations) {
|
|
|
|
if (q.name === "Graphene BranchiBlades Upgrade") {
|
|
|
|
q.name = "Graphene BrachiBlades Upgrade";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (const q of anyPlayer.augmentations) {
|
|
|
|
if (q.name === "Graphene BranchiBlades Upgrade") {
|
|
|
|
q.name = "Graphene BrachiBlades Upgrade";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-10-13 01:23:36 +02:00
|
|
|
if (ver < "0.56.1") {
|
|
|
|
if (anyPlayer.bladeburner === 0) {
|
|
|
|
anyPlayer.bladeburner = null;
|
|
|
|
}
|
|
|
|
if (anyPlayer.gang === 0) {
|
|
|
|
anyPlayer.gang = null;
|
|
|
|
}
|
|
|
|
if (anyPlayer.corporation === 0) {
|
|
|
|
anyPlayer.corporation = null;
|
|
|
|
}
|
2021-10-14 08:07:05 +02:00
|
|
|
// convert all Messages to just filename to save space.
|
|
|
|
const home = anyPlayer.getHomeComputer();
|
|
|
|
for (let i = 0; i < home.messages.length; i++) {
|
|
|
|
if (home.messages[i].filename) {
|
|
|
|
home.messages[i] = home.messages[i].filename;
|
|
|
|
}
|
|
|
|
}
|
2021-10-13 01:23:36 +02:00
|
|
|
}
|
2021-10-27 21:16:16 +02:00
|
|
|
if (ver < "0.58.0") {
|
|
|
|
const changes: [RegExp, string][] = [
|
|
|
|
[/getStockSymbols/g, "stock.getSymbols"],
|
|
|
|
[/getStockPrice/g, "stock.getPrice"],
|
|
|
|
[/getStockAskPrice/g, "stock.getAskPrice"],
|
|
|
|
[/getStockBidPrice/g, "stock.getBidPrice"],
|
|
|
|
[/getStockPosition/g, "stock.getPosition"],
|
|
|
|
[/getStockMaxShares/g, "stock.getMaxShares"],
|
|
|
|
[/getStockPurchaseCost/g, "stock.getPurchaseCost"],
|
|
|
|
[/getStockSaleGain/g, "stock.getSaleGain"],
|
|
|
|
[/buyStock/g, "stock.buy"],
|
|
|
|
[/sellStock/g, "stock.sell"],
|
|
|
|
[/shortStock/g, "stock.short"],
|
|
|
|
[/sellShort/g, "stock.sellShort"],
|
|
|
|
[/placeOrder/g, "stock.placeOrder"],
|
|
|
|
[/cancelOrder/g, "stock.cancelOrder"],
|
|
|
|
[/getOrders/g, "stock.getOrders"],
|
|
|
|
[/getStockVolatility/g, "stock.getVolatility"],
|
|
|
|
[/getStockForecast/g, "stock.getForecast"],
|
|
|
|
[/purchase4SMarketData/g, "stock.purchase4SMarketData"],
|
|
|
|
[/purchase4SMarketDataTixApi/g, "stock.purchase4SMarketDataTixApi"],
|
|
|
|
];
|
|
|
|
function convert(code: string): string {
|
|
|
|
for (const change of changes) {
|
|
|
|
code = code.replace(change[0], change[1]);
|
|
|
|
}
|
|
|
|
return code;
|
|
|
|
}
|
|
|
|
for (const server of GetAllServers()) {
|
|
|
|
for (const script of server.scripts) {
|
|
|
|
script.code = convert(script.code);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-11-16 04:45:03 +01:00
|
|
|
}
|
|
|
|
|
2021-09-25 00:40:17 +02:00
|
|
|
function loadGame(saveString: string): boolean {
|
2021-09-21 23:36:42 +02:00
|
|
|
if (!saveString) return false;
|
2021-09-21 22:49:38 +02:00
|
|
|
saveString = decodeURIComponent(escape(atob(saveString)));
|
2017-10-12 04:00:22 +02:00
|
|
|
|
2021-09-21 22:49:38 +02:00
|
|
|
const saveObj = JSON.parse(saveString, Reviver);
|
2017-07-25 16:39:56 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
loadPlayer(saveObj.PlayerSave);
|
|
|
|
loadAllServers(saveObj.AllServersSave);
|
|
|
|
loadCompanies(saveObj.CompaniesSave);
|
|
|
|
loadFactions(saveObj.FactionsSave);
|
2017-07-25 16:39:56 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
if (saveObj.hasOwnProperty("AliasesSave")) {
|
|
|
|
try {
|
|
|
|
loadAliases(saveObj.AliasesSave);
|
|
|
|
} catch (e) {
|
|
|
|
console.warn(`Could not load Aliases from save`);
|
|
|
|
loadAliases("");
|
2017-05-23 18:15:17 +02:00
|
|
|
}
|
2021-09-05 01:09:30 +02:00
|
|
|
} else {
|
|
|
|
console.warn(`Save file did not contain an Aliases property`);
|
|
|
|
loadAliases("");
|
|
|
|
}
|
|
|
|
if (saveObj.hasOwnProperty("GlobalAliasesSave")) {
|
|
|
|
try {
|
|
|
|
loadGlobalAliases(saveObj.GlobalAliasesSave);
|
|
|
|
} catch (e) {
|
|
|
|
console.warn(`Could not load GlobalAliases from save`);
|
|
|
|
loadGlobalAliases("");
|
2017-06-30 18:44:03 +02:00
|
|
|
}
|
2021-09-05 01:09:30 +02:00
|
|
|
} else {
|
|
|
|
console.warn(`Save file did not contain a GlobalAliases property`);
|
|
|
|
loadGlobalAliases("");
|
|
|
|
}
|
|
|
|
if (saveObj.hasOwnProperty("MessagesSave")) {
|
|
|
|
try {
|
|
|
|
loadMessages(saveObj.MessagesSave);
|
|
|
|
} catch (e) {
|
|
|
|
console.warn(`Could not load Messages from save`);
|
|
|
|
initMessages();
|
2017-06-02 06:15:45 +02:00
|
|
|
}
|
2021-09-05 01:09:30 +02:00
|
|
|
} else {
|
|
|
|
console.warn(`Save file did not contain a Messages property`);
|
|
|
|
initMessages();
|
|
|
|
}
|
|
|
|
if (saveObj.hasOwnProperty("StockMarketSave")) {
|
|
|
|
try {
|
|
|
|
loadStockMarket(saveObj.StockMarketSave);
|
|
|
|
} catch (e) {
|
|
|
|
loadStockMarket("");
|
2017-07-03 21:42:11 +02:00
|
|
|
}
|
2021-09-05 01:09:30 +02:00
|
|
|
} else {
|
|
|
|
loadStockMarket("");
|
|
|
|
}
|
|
|
|
if (saveObj.hasOwnProperty("SettingsSave")) {
|
|
|
|
try {
|
|
|
|
Settings.load(saveObj.SettingsSave);
|
|
|
|
} catch (e) {
|
2021-09-09 05:47:34 +02:00
|
|
|
console.error("ERROR: Failed to parse Settings. Re-initing default values");
|
2021-09-05 01:09:30 +02:00
|
|
|
Settings.init();
|
2017-07-25 16:39:56 +02:00
|
|
|
}
|
2021-09-05 01:09:30 +02:00
|
|
|
} else {
|
|
|
|
Settings.init();
|
|
|
|
}
|
|
|
|
if (saveObj.hasOwnProperty("LastExportBonus")) {
|
|
|
|
try {
|
|
|
|
ExportBonus.setLastExportBonus(JSON.parse(saveObj.LastExportBonus));
|
|
|
|
} catch (err) {
|
|
|
|
ExportBonus.setLastExportBonus(new Date().getTime());
|
2021-09-21 04:30:11 +02:00
|
|
|
console.error("ERROR: Failed to parse last export bonus Settings " + err);
|
2021-05-18 05:59:45 +02:00
|
|
|
}
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2021-10-07 22:56:01 +02:00
|
|
|
if (Player.inGang() && saveObj.hasOwnProperty("AllGangsSave")) {
|
|
|
|
try {
|
|
|
|
loadAllGangs(saveObj.AllGangsSave);
|
|
|
|
} catch (e) {
|
|
|
|
console.error("ERROR: Failed to parse AllGangsSave: " + e);
|
|
|
|
}
|
|
|
|
}
|
2021-09-05 01:09:30 +02:00
|
|
|
if (saveObj.hasOwnProperty("VersionSave")) {
|
|
|
|
try {
|
2021-09-25 07:26:03 +02:00
|
|
|
const ver = JSON.parse(saveObj.VersionSave, Reviver);
|
2021-09-05 01:09:30 +02:00
|
|
|
evaluateVersionCompatibility(ver);
|
|
|
|
|
|
|
|
if (window.location.href.toLowerCase().includes("bitburner-beta")) {
|
|
|
|
// Beta branch, always show changes
|
|
|
|
createBetaUpdateText();
|
|
|
|
} else if (ver != CONSTANTS.Version) {
|
2017-06-07 02:28:20 +02:00
|
|
|
createNewUpdateText();
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
createNewUpdateText();
|
2017-06-07 02:04:18 +02:00
|
|
|
}
|
2021-09-05 01:09:30 +02:00
|
|
|
} else {
|
|
|
|
createNewUpdateText();
|
|
|
|
}
|
2017-07-25 16:39:56 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
return true;
|
2017-05-05 03:08:44 +02:00
|
|
|
}
|
|
|
|
|
2021-09-25 07:26:03 +02:00
|
|
|
function createNewUpdateText(): void {
|
2021-09-05 01:09:30 +02:00
|
|
|
dialogBoxCreate(
|
|
|
|
"New update!<br>" +
|
|
|
|
"Please report any bugs/issues through the github repository " +
|
|
|
|
"or the Bitburner subreddit (reddit.com/r/bitburner).<br><br>" +
|
|
|
|
CONSTANTS.LatestUpdate,
|
|
|
|
);
|
2017-06-07 02:28:20 +02:00
|
|
|
}
|
|
|
|
|
2021-09-25 07:26:03 +02:00
|
|
|
function createBetaUpdateText(): void {
|
2021-09-05 01:09:30 +02:00
|
|
|
dialogBoxCreate(
|
|
|
|
"You are playing on the beta environment! This branch of the game " +
|
|
|
|
"features the latest developments in the game. This version may be unstable.<br>" +
|
|
|
|
"Please report any bugs/issues through the github repository (https://github.com/danielyxie/bitburner/issues) " +
|
|
|
|
"or the Bitburner subreddit (reddit.com/r/bitburner).<br><br>" +
|
|
|
|
CONSTANTS.LatestUpdate,
|
|
|
|
);
|
2018-07-19 04:23:49 +02:00
|
|
|
}
|
|
|
|
|
2017-06-08 06:57:40 +02:00
|
|
|
Reviver.constructors.BitburnerSaveObject = BitburnerSaveObject;
|
|
|
|
|
2021-09-21 22:49:38 +02:00
|
|
|
export { saveObject, loadGame };
|
2021-09-25 00:40:17 +02:00
|
|
|
|
2021-09-25 07:26:03 +02:00
|
|
|
const saveObject = new BitburnerSaveObject();
|