merge dev

This commit is contained in:
Olivier Gagnon 2021-10-14 02:12:15 -04:00
commit eb846c1318
39 changed files with 16511 additions and 16285 deletions

138
dist/vendor.bundle.js vendored

File diff suppressed because one or more lines are too long

@ -0,0 +1,15 @@
alert() Netscript Function
============================
.. js:function:: alert(message)
:RAM cost: 0 GB
:param string message: message to display
Spawns an alert box.
Example:
.. code-block:: javascript
alert("Reached $1b");

@ -0,0 +1,17 @@
toast() Netscript Function
============================
.. js:function:: toast(message[, variant])
:RAM cost: 0 GB
:param string message: message to display
:param success|info|warning|error variant: color of the toast
Spawns a toast (those bottom left notifications).
Example:
.. code-block:: javascript
toast("Reached $1b");
toast("Failed to hack home", "error");

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

32056
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -13,10 +13,10 @@
"@emotion/react": "^11.4.1", "@emotion/react": "^11.4.1",
"@emotion/styled": "^11.3.0", "@emotion/styled": "^11.3.0",
"@monaco-editor/react": "^4.2.2", "@monaco-editor/react": "^4.2.2",
"@mui/icons-material": "^5.0.0-rc.1", "@mui/icons-material": "^5.0.3",
"@mui/lab": "^5.0.0-alpha.46", "@mui/lab": "^5.0.0-alpha.46",
"@mui/material": "^5.0.0-rc.1", "@mui/material": "^5.0.3",
"@mui/styles": "^5.0.0-rc.1", "@mui/styles": "^5.0.1",
"@types/escodegen": "^0.0.7", "@types/escodegen": "^0.0.7",
"@types/js-beautify": "^1.13.2", "@types/js-beautify": "^1.13.2",
"@types/numeral": "0.0.25", "@types/numeral": "0.0.25",
@ -30,6 +30,7 @@
"arg": "^5.0.0", "arg": "^5.0.0",
"async": "^2.6.1", "async": "^2.6.1",
"autosize": "^4.0.2", "autosize": "^4.0.2",
"better-react-mathjax": "^1.0.3",
"brace": "^0.11.1", "brace": "^0.11.1",
"codemirror": "^5.58.2", "codemirror": "^5.58.2",
"decimal.js": "7.2.3", "decimal.js": "7.2.3",
@ -47,11 +48,11 @@
"loader-utils": "^1.1.0", "loader-utils": "^1.1.0",
"material-ui-color": "^1.2.0", "material-ui-color": "^1.2.0",
"mathjax-full": "^3.2.0", "mathjax-full": "^3.2.0",
"mathjax-react": "^1.0.6",
"memory-fs": "~0.4.1", "memory-fs": "~0.4.1",
"monaco-editor": "^0.27.0", "monaco-editor": "^0.27.0",
"node-sass": "^6.0.1", "node-sass": "^6.0.1",
"normalize.css": "^8.0.0", "normalize.css": "^8.0.0",
"notistack": "^2.0.2",
"numeral": "2.0.6", "numeral": "2.0.6",
"react": "^17.0.2", "react": "^17.0.2",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
@ -122,7 +123,6 @@
"start-server-and-test": "^1.14.0", "start-server-and-test": "^1.14.0",
"style-loader": "^0.21.0", "style-loader": "^0.21.0",
"stylelint": "^9.2.1", "stylelint": "^9.2.1",
"stylelint-declaration-use-variable": "^1.6.1",
"stylelint-order": "^0.8.1", "stylelint-order": "^0.8.1",
"typescript": "^4.2.4", "typescript": "^4.2.4",
"uglify-es": "^3.3.9", "uglify-es": "^3.3.9",

@ -735,7 +735,7 @@ function initAugmentations(): void {
const ENMCore = new Augmentation({ const ENMCore = new Augmentation({
name: AugmentationNames.ENMCore, name: AugmentationNames.ENMCore,
repCost: 2.5e5, repCost: 175e3,
moneyCost: 2.5e9, moneyCost: 2.5e9,
info: info:
"The Core library is an implant that upgrades the firmware of the Embedded Netburner Module. " + "The Core library is an implant that upgrades the firmware of the Embedded Netburner Module. " +

@ -132,7 +132,7 @@ export class Bladeburner implements IBladeburner {
return this.resetAction(); return this.resetAction();
} }
this.actionTimeToComplete = action.getActionTime(this); this.actionTimeToComplete = action.getActionTime(this);
} catch (e) { } catch (e: any) {
exceptionAlert(e); exceptionAlert(e);
} }
break; break;
@ -149,7 +149,7 @@ export class Bladeburner implements IBladeburner {
return this.resetAction(); return this.resetAction();
} }
this.actionTimeToComplete = action.getActionTime(this); this.actionTimeToComplete = action.getActionTime(this);
} catch (e) { } catch (e: any) {
exceptionAlert(e); exceptionAlert(e);
} }
break; break;
@ -169,7 +169,7 @@ export class Bladeburner implements IBladeburner {
throw new Error("Failed to get BlackOperation object for: " + actionId.name); throw new Error("Failed to get BlackOperation object for: " + actionId.name);
} }
this.actionTimeToComplete = action.getActionTime(this); this.actionTimeToComplete = action.getActionTime(this);
} catch (e) { } catch (e: any) {
exceptionAlert(e); exceptionAlert(e);
} }
break; break;
@ -220,7 +220,7 @@ export class Bladeburner implements IBladeburner {
for (let i = 0; i < arrayOfCommands.length; ++i) { for (let i = 0; i < arrayOfCommands.length; ++i) {
this.executeConsoleCommand(player, arrayOfCommands[i]); this.executeConsoleCommand(player, arrayOfCommands[i]);
} }
} catch (e) { } catch (e: any) {
exceptionAlert(e); exceptionAlert(e);
} }
} }
@ -1298,7 +1298,7 @@ export class Bladeburner implements IBladeburner {
action.level = action.maxLevel; action.level = action.maxLevel;
} // Autolevel } // Autolevel
this.startAction(player, this.action); // Repeat action this.startAction(player, this.action); // Repeat action
} catch (e) { } catch (e: any) {
exceptionAlert(e); exceptionAlert(e);
} }
break; break;
@ -1387,7 +1387,7 @@ export class Bladeburner implements IBladeburner {
this.log("You lost " + formatNumber(losses, 0) + " team members during " + action.name); this.log("You lost " + formatNumber(losses, 0) + " team members during " + action.name);
} }
} }
} catch (e) { } catch (e: any) {
exceptionAlert(e); exceptionAlert(e);
} }
break; break;
@ -2056,7 +2056,7 @@ export class Bladeburner implements IBladeburner {
this.startAction(player, actionId); this.startAction(player, actionId);
workerScript.log("bladeburner.startAction", `Starting bladeburner action with type '${type}' and name ${name}"`); workerScript.log("bladeburner.startAction", `Starting bladeburner action with type '${type}' and name ${name}"`);
return true; return true;
} catch (e) { } catch (e: any) {
this.resetAction(); this.resetAction();
workerScript.log("bladeburner.startAction", errorLogText); workerScript.log("bladeburner.startAction", errorLogText);
return false; return false;

@ -99,7 +99,7 @@ export class Warehouse {
updateSize(corporation: ICorporation, industry: IIndustry): void { updateSize(corporation: ICorporation, industry: IIndustry): void {
try { try {
this.size = this.level * 100 * corporation.getStorageMultiplier() * industry.getStorageMultiplier(); this.size = this.level * 100 * corporation.getStorageMultiplier() * industry.getStorageMultiplier();
} catch (e) { } catch (e: any) {
exceptionAlert(e); exceptionAlert(e);
} }
} }

@ -1,6 +1,6 @@
import React from "react"; import React from "react";
import { IIndustry } from "../IIndustry"; import { IIndustry } from "../IIndustry";
import { MathComponent } from "mathjax-react"; import { MathJax, MathJaxContext } from "better-react-mathjax";
interface IProps { interface IProps {
division: IIndustry; division: IIndustry;
@ -19,9 +19,8 @@ export function IndustryProductEquation(props: IProps): React.ReactElement {
} }
return ( return (
<MathComponent <MathJaxContext>
display={false} <MathJax>{"\\(" + reqs.join("+") + `\\Rightarrow` + prod.map((p) => `1\\text{ }${p}`).join("+") + "\\)"}</MathJax>
tex={reqs.join("+") + String.raw`\Rightarrow` + prod.map((p) => String.raw`1\text{ }${p}`).join("+")} </MathJaxContext>
/>
); );
} }

@ -15,7 +15,7 @@ import { Reputation } from "../../ui/React/Reputation";
import { numeralWrapper } from "../../ui/numeralFormat"; import { numeralWrapper } from "../../ui/numeralFormat";
import { dialogBoxCreate } from "../../ui/React/DialogBox"; import { dialogBoxCreate } from "../../ui/React/DialogBox";
import { MathComponent } from "mathjax-react"; import { MathJax, MathJaxContext } from "better-react-mathjax";
import Typography from "@mui/material/Typography"; import Typography from "@mui/material/Typography";
import Paper from "@mui/material/Paper"; import Paper from "@mui/material/Paper";
@ -98,9 +98,9 @@ export function DonateOption(props: IProps): React.ReactElement {
}} }}
/> />
<Typography> <Typography>
<MathComponent <MathJaxContext>
tex={String.raw`reputation = \frac{\text{donation amount} \times \text{reputation multiplier}}{10^{${digits}}}`} <MathJax>{`\\(reputation = \\frac{\\text{donation amount} \\cdot \\text{reputation multiplier}}{10^{${digits}}}\\)`}</MathJax>
/> </MathJaxContext>
</Typography> </Typography>
</> </>
)} )}

@ -9,7 +9,7 @@ import { FactionInfo } from "../../Faction/FactionInfo";
import { Reputation } from "../../ui/React/Reputation"; import { Reputation } from "../../ui/React/Reputation";
import { Favor } from "../../ui/React/Favor"; import { Favor } from "../../ui/React/Favor";
import { MathComponent } from "mathjax-react"; import { MathJax, MathJaxContext } from "better-react-mathjax";
import makeStyles from "@mui/styles/makeStyles"; import makeStyles from "@mui/styles/makeStyles";
import createStyles from "@mui/styles/createStyles"; import createStyles from "@mui/styles/createStyles";
@ -57,10 +57,14 @@ export function Info(props: IProps): React.ReactElement {
You will have <Favor favor={props.faction.favor + favorGain} /> faction favor after installing an You will have <Favor favor={props.faction.favor + favorGain} /> faction favor after installing an
Augmentation. Augmentation.
</Typography> </Typography>
<MathComponent tex={String.raw`\large{r = \text{total faction reputation}}`} /> <MathJaxContext>
<MathComponent <MathJax>{"\\(\\huge{r = \\text{total faction reputation}}\\)"}</MathJax>
tex={String.raw`\large{favor=\left\lfloor\log_{1.02}\left(\frac{r+25000}{25500}\right)\right\rfloor}`} </MathJaxContext>
/> <MathJaxContext>
<MathJax>
{"\\(\\huge{favor=\\left\\lfloor\\log_{1.02}\\left(\\frac{r+25000}{25500}\\right)\\right\\rfloor}\\)"}
</MathJax>
</MathJaxContext>
</> </>
} }
> >
@ -81,8 +85,13 @@ export function Info(props: IProps): React.ReactElement {
favor is gained whenever you install an Augmentation. The amount of favor you gain depends on the total favor is gained whenever you install an Augmentation. The amount of favor you gain depends on the total
amount of reputation you earned with this faction. Across all resets. amount of reputation you earned with this faction. Across all resets.
</Typography> </Typography>
<MathComponent tex={String.raw`\large{r = reputation}`} />
<MathComponent tex={String.raw`\large{\Delta r = \Delta r \times \frac{100+favor}{100}}`} /> <MathJaxContext>
<MathJax>{"\\(\\huge{r = reputation}\\)"}</MathJax>
</MathJaxContext>
<MathJaxContext>
<MathJax>{"\\(\\huge{\\Delta r = \\Delta r \\times \\frac{100+favor}{100}}\\)"}</MathJax>
</MathJaxContext>
</> </>
} }
> >

@ -97,7 +97,7 @@ export class Gang {
this.processExperienceGains(cycles); this.processExperienceGains(cycles);
this.processTerritoryAndPowerGains(cycles); this.processTerritoryAndPowerGains(cycles);
this.storedCycles -= cycles; this.storedCycles -= cycles;
} catch (e) { } catch (e: any) {
console.error(`Exception caught when processing Gang: ${e}`); console.error(`Exception caught when processing Gang: ${e}`);
} }
} }
@ -344,7 +344,7 @@ export class Gang {
workerScript.log("ascend", `Ascended Gang member ${member.name}`); workerScript.log("ascend", `Ascended Gang member ${member.name}`);
} }
return res; return res;
} catch (e) { } catch (e: any) {
if (workerScript == null) { if (workerScript == null) {
exceptionAlert(e); exceptionAlert(e);
} }

@ -5,7 +5,7 @@ import Tooltip from "@mui/material/Tooltip";
import { IPlayer } from "../../PersonObjects/IPlayer"; import { IPlayer } from "../../PersonObjects/IPlayer";
import { Money } from "../../ui/React/Money"; import { Money } from "../../ui/React/Money";
import { MathComponent } from "mathjax-react"; import { MathJax, MathJaxContext } from "better-react-mathjax";
type IProps = { type IProps = {
p: IPlayer; p: IPlayer;
@ -19,7 +19,7 @@ export function CoresButton(props: IProps): React.ReactElement {
return <Button>Upgrade 'home' cores - MAX</Button>; return <Button>Upgrade 'home' cores - MAX</Button>;
} }
const cost = 1e9 * Math.pow(7.5, homeComputer.cpuCores); const cost = props.p.getUpgradeHomeCoresCost();
function buy(): void { function buy(): void {
if (maxCores) return; if (maxCores) return;
@ -30,7 +30,13 @@ export function CoresButton(props: IProps): React.ReactElement {
} }
return ( return (
<Tooltip title={<MathComponent tex={String.raw`\large{cost = 10^9 \times 7.5 ^{\text{cores}}}`} />}> <Tooltip
title={
<MathJaxContext>
<MathJax>{`\\(\\large{cost = 10^9 \\cdot 7.5 ^{\\text{cores}}}\\)`}</MathJax>
</MathJaxContext>
}
>
<span> <span>
<Button disabled={!props.p.canAfford(cost)} onClick={buy}> <Button disabled={!props.p.canAfford(cost)} onClick={buy}>
Upgrade 'home' cores ({homeComputer.cpuCores} -&gt; {homeComputer.cpuCores + 1}) -&nbsp; Upgrade 'home' cores ({homeComputer.cpuCores} -&gt; {homeComputer.cpuCores + 1}) -&nbsp;

@ -7,8 +7,8 @@ import { IPlayer } from "../../PersonObjects/IPlayer";
import { purchaseRamForHomeComputer } from "../../Server/ServerPurchases"; import { purchaseRamForHomeComputer } from "../../Server/ServerPurchases";
import { Money } from "../../ui/React/Money"; import { Money } from "../../ui/React/Money";
import { MathComponent } from "mathjax-react";
import { numeralWrapper } from "../../ui/numeralFormat"; import { numeralWrapper } from "../../ui/numeralFormat";
import { MathJax, MathJaxContext } from "better-react-mathjax";
type IProps = { type IProps = {
p: IPlayer; p: IPlayer;
@ -29,7 +29,13 @@ export function RamButton(props: IProps): React.ReactElement {
} }
return ( return (
<Tooltip title={<MathComponent tex={String.raw`\large{cost = 3.2 \times 10^3 \times 1.58^{log_2{(ram)}}}`} />}> <Tooltip
title={
<MathJaxContext>
<MathJax>{`\\(\\large{cost = 3.2 \\cdot 10^3 \\cdot 1.58^{log_2{(ram)}}}\\)`}</MathJax>
</MathJaxContext>
}
>
<span> <span>
<Button disabled={!props.p.canAfford(cost)} onClick={buy}> <Button disabled={!props.p.canAfford(cost)} onClick={buy}>
Upgrade 'home' RAM ({numeralWrapper.formatRAM(homeComputer.maxRam)} -&gt;&nbsp; Upgrade 'home' RAM ({numeralWrapper.formatRAM(homeComputer.maxRam)} -&gt;&nbsp;

@ -13,12 +13,14 @@ import { Reviver } from "../utils/JSONReviver";
function sendMessage(msg: Message, forced = false): void { function sendMessage(msg: Message, forced = false): void {
msg.recvd = true; msg.recvd = true;
if (forced || !Settings.SuppressMessages) { if (forced || !Settings.SuppressMessages) {
showMessage(msg); showMessage(msg.filename);
} }
addMessageToServer(msg, "home"); addMessageToServer(msg, "home");
} }
function showMessage(msg: Message): void { function showMessage(name: string): void {
const msg = Messages[name];
if (!msg) throw new Error("trying to display unexistent message");
const txt = const txt =
"Message received from unknown sender: <br><br>" + "Message received from unknown sender: <br><br>" +
"<i>" + "<i>" +
@ -39,12 +41,11 @@ function addMessageToServer(msg: Message, serverHostname: string): void {
} }
for (let i = 0; i < server.messages.length; ++i) { for (let i = 0; i < server.messages.length; ++i) {
const other = server.messages[i]; const other = server.messages[i];
if (typeof other === "string") continue; if (msg.filename === other) {
if (msg.filename === other.filename) {
return; //Already exists return; //Already exists
} }
} }
server.messages.push(msg); server.messages.push(msg.filename);
} }
//Checks if any of the 'timed' messages should be sent //Checks if any of the 'timed' messages should be sent

@ -81,7 +81,6 @@ import { LocationName } from "./Locations/data/LocationNames";
import { Terminal } from "./Terminal"; import { Terminal } from "./Terminal";
import { calculateSkill, calculateExp } from "./PersonObjects/formulas/skill"; import { calculateSkill, calculateExp } from "./PersonObjects/formulas/skill";
import { Message } from "./Message/Message";
import { Player } from "./Player"; import { Player } from "./Player";
import { Programs } from "./Programs/Programs"; import { Programs } from "./Programs/Programs";
import { Script } from "./Script/Script"; import { Script } from "./Script/Script";
@ -147,6 +146,8 @@ import { INetscriptSleeve, NetscriptSleeve } from "./NetscriptFunctions/Sleeve";
import { INetscriptExtra, NetscriptExtra } from "./NetscriptFunctions/Extra"; import { INetscriptExtra, NetscriptExtra } from "./NetscriptFunctions/Extra";
import { INetscriptHacknet, NetscriptHacknet } from "./NetscriptFunctions/Hacknet"; import { INetscriptHacknet, NetscriptHacknet } from "./NetscriptFunctions/Hacknet";
import { INetscriptStanek, NetscriptStanek } from "./NetscriptFunctions/Stanek"; import { INetscriptStanek, NetscriptStanek } from "./NetscriptFunctions/Stanek";
import { dialogBoxCreate } from "./ui/React/DialogBox";
import { SnackbarEvents } from "./ui/React/Snackbar";
const defaultInterpreter = new Interpreter("", () => undefined); const defaultInterpreter = new Interpreter("", () => undefined);
@ -479,15 +480,6 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
return contract; return contract;
}; };
const checkStanekAPIAccess = function (func: string): void {
if (Player.bitNodeN !== 13 && !SourceFileFlags[13]) {
throw makeRuntimeErrorMsg(
`stanek.${func}`,
"You do not currently have access to the Stanek API. This is either because you are not in BitNode-13 or because you do not have Source-File 13",
);
}
};
const getBladeburnerActionObject = function (func: any, type: any, name: any): any { const getBladeburnerActionObject = function (func: any, type: any, name: any): any {
const bladeburner = Player.bladeburner; const bladeburner = Player.bladeburner;
if (bladeburner === null) throw new Error("Must have joined bladeburner"); if (bladeburner === null) throw new Error("Must have joined bladeburner");
@ -1346,7 +1338,7 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
if (scriptname.endsWith(".lit")) { if (scriptname.endsWith(".lit")) {
let found = false; let found = false;
for (let i = 0; i < currServ.messages.length; ++i) { for (let i = 0; i < currServ.messages.length; ++i) {
if (!(currServ.messages[i] instanceof Message) && currServ.messages[i] == scriptname) { if (currServ.messages[i] == scriptname) {
found = true; found = true;
break; break;
} }
@ -1472,20 +1464,11 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
for (let i = 0; i < server.messages.length; i++) { for (let i = 0; i < server.messages.length; i++) {
if (filter) { if (filter) {
const msg = server.messages[i]; const msg = server.messages[i];
if (msg instanceof Message) { if (msg.includes(filter)) {
if (msg.filename.includes(filter)) {
allFiles.push(msg.filename);
}
} else if (msg.includes(filter)) {
allFiles.push(msg); allFiles.push(msg);
} }
} else { } else {
const msg = server.messages[i]; allFiles.push(server.messages[i]);
if (msg instanceof Message) {
allFiles.push(msg.filename);
} else {
allFiles.push(msg);
}
} }
} }
@ -1780,7 +1763,7 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
} }
} }
for (let i = 0; i < server.messages.length; ++i) { for (let i = 0; i < server.messages.length; ++i) {
if (!(server.messages[i] instanceof Message) && filename.toLowerCase() === server.messages[i]) { if (filename.toLowerCase() === server.messages[i]) {
return true; return true;
} }
} }
@ -2312,7 +2295,7 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
// Coerce 'data' to be a string // Coerce 'data' to be a string
try { try {
data = String(data); data = String(data);
} catch (e) { } catch (e: any) {
throw makeRuntimeErrorMsg("write", `Invalid data (${e}). Data being written must be convertible to a string`); throw makeRuntimeErrorMsg("write", `Invalid data (${e}). Data being written must be convertible to a string`);
} }
@ -2691,6 +2674,14 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
updateDynamicRam("getTimeSinceLastAug", getRamCost("getTimeSinceLastAug")); updateDynamicRam("getTimeSinceLastAug", getRamCost("getTimeSinceLastAug"));
return Player.playtimeSinceLastAug; return Player.playtimeSinceLastAug;
}, },
alert: function (message: any): void {
dialogBoxCreate(message);
},
toast: function (message: any, variant: any = "success"): void {
if (!["success", "info", "warning", "error"].includes(variant))
throw new Error(`variant must be one of "success", "info", "warning", or "error"`);
SnackbarEvents.emit(message, variant);
},
prompt: function (txt: any): any { prompt: function (txt: any): any {
if (!isString(txt)) { if (!isString(txt)) {
txt = JSON.stringify(txt); txt = JSON.stringify(txt);
@ -3967,7 +3958,7 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
if (bladeburner === null) throw new Error("Should not be called without Bladeburner"); if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
try { try {
return bladeburner.startActionNetscriptFn(Player, type, name, workerScript); return bladeburner.startActionNetscriptFn(Player, type, name, workerScript);
} catch (e) { } catch (e: any) {
throw makeRuntimeErrorMsg("bladeburner.startAction", e); throw makeRuntimeErrorMsg("bladeburner.startAction", e);
} }
}, },
@ -3992,7 +3983,7 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
if (bladeburner === null) throw new Error("Should not be called without Bladeburner"); if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
try { try {
return bladeburner.getActionTimeNetscriptFn(Player, type, name, workerScript); return bladeburner.getActionTimeNetscriptFn(Player, type, name, workerScript);
} catch (e) { } catch (e: any) {
throw makeRuntimeErrorMsg("bladeburner.getActionTime", e); throw makeRuntimeErrorMsg("bladeburner.getActionTime", e);
} }
}, },
@ -4006,7 +3997,7 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
if (bladeburner === null) throw new Error("Should not be called without Bladeburner"); if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
try { try {
return bladeburner.getActionEstimatedSuccessChanceNetscriptFn(Player, type, name, workerScript); return bladeburner.getActionEstimatedSuccessChanceNetscriptFn(Player, type, name, workerScript);
} catch (e) { } catch (e: any) {
throw makeRuntimeErrorMsg("bladeburner.getActionEstimatedSuccessChance", e); throw makeRuntimeErrorMsg("bladeburner.getActionEstimatedSuccessChance", e);
} }
}, },
@ -4030,7 +4021,7 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
if (bladeburner === null) throw new Error("Should not be called without Bladeburner"); if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
try { try {
return bladeburner.getActionCountRemainingNetscriptFn(type, name, workerScript); return bladeburner.getActionCountRemainingNetscriptFn(type, name, workerScript);
} catch (e) { } catch (e: any) {
throw makeRuntimeErrorMsg("bladeburner.getActionCountRemaining", e); throw makeRuntimeErrorMsg("bladeburner.getActionCountRemaining", e);
} }
}, },
@ -4091,7 +4082,7 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
if (bladeburner === null) throw new Error("Should not be called without Bladeburner"); if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
try { try {
return bladeburner.getSkillLevelNetscriptFn(skillName, workerScript); return bladeburner.getSkillLevelNetscriptFn(skillName, workerScript);
} catch (e) { } catch (e: any) {
throw makeRuntimeErrorMsg("bladeburner.getSkillLevel", e); throw makeRuntimeErrorMsg("bladeburner.getSkillLevel", e);
} }
}, },
@ -4102,7 +4093,7 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
if (bladeburner === null) throw new Error("Should not be called without Bladeburner"); if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
try { try {
return bladeburner.getSkillUpgradeCostNetscriptFn(skillName, workerScript); return bladeburner.getSkillUpgradeCostNetscriptFn(skillName, workerScript);
} catch (e) { } catch (e: any) {
throw makeRuntimeErrorMsg("bladeburner.getSkillUpgradeCost", e); throw makeRuntimeErrorMsg("bladeburner.getSkillUpgradeCost", e);
} }
}, },
@ -4113,7 +4104,7 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
if (bladeburner === null) throw new Error("Should not be called without Bladeburner"); if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
try { try {
return bladeburner.upgradeSkillNetscriptFn(skillName, workerScript); return bladeburner.upgradeSkillNetscriptFn(skillName, workerScript);
} catch (e) { } catch (e: any) {
throw makeRuntimeErrorMsg("bladeburner.upgradeSkill", e); throw makeRuntimeErrorMsg("bladeburner.upgradeSkill", e);
} }
}, },
@ -4124,7 +4115,7 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
if (bladeburner === null) throw new Error("Should not be called without Bladeburner"); if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
try { try {
return bladeburner.getTeamSizeNetscriptFn(type, name, workerScript); return bladeburner.getTeamSizeNetscriptFn(type, name, workerScript);
} catch (e) { } catch (e: any) {
throw makeRuntimeErrorMsg("bladeburner.getTeamSize", e); throw makeRuntimeErrorMsg("bladeburner.getTeamSize", e);
} }
}, },
@ -4135,7 +4126,7 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
if (bladeburner === null) throw new Error("Should not be called without Bladeburner"); if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
try { try {
return bladeburner.setTeamSizeNetscriptFn(type, name, size, workerScript); return bladeburner.setTeamSizeNetscriptFn(type, name, size, workerScript);
} catch (e) { } catch (e: any) {
throw makeRuntimeErrorMsg("bladeburner.setTeamSize", e); throw makeRuntimeErrorMsg("bladeburner.setTeamSize", e);
} }
}, },

@ -93,7 +93,7 @@ function startNetscript2Script(workerScript: WorkerScript): Promise<WorkerScript
let result; let result;
try { try {
result = f(...args); result = f(...args);
} catch (e) { } catch (e: any) {
runningFn = null; runningFn = null;
throw e; throw e;
} }
@ -152,7 +152,7 @@ function startNetscript1Script(workerScript: WorkerScript): Promise<WorkerScript
const importProcessingRes = processNetscript1Imports(code, workerScript); const importProcessingRes = processNetscript1Imports(code, workerScript);
codeWithImports = importProcessingRes.code; codeWithImports = importProcessingRes.code;
codeLineOffset = importProcessingRes.lineOffset; codeLineOffset = importProcessingRes.lineOffset;
} catch (e) { } catch (e: any) {
dialogBoxCreate("Error processing Imports in " + workerScript.name + ":<br>" + e); dialogBoxCreate("Error processing Imports in " + workerScript.name + ":<br>" + e);
workerScript.env.stopFlag = true; workerScript.env.stopFlag = true;
workerScript.running = false; workerScript.running = false;
@ -252,7 +252,7 @@ function startNetscript1Script(workerScript: WorkerScript): Promise<WorkerScript
let interpreter: any; let interpreter: any;
try { try {
interpreter = new Interpreter(codeWithImports, interpreterInitialization, codeLineOffset); interpreter = new Interpreter(codeWithImports, interpreterInitialization, codeLineOffset);
} catch (e) { } catch (e: any) {
dialogBoxCreate("Syntax ERROR in " + workerScript.name + ":<br>" + e); dialogBoxCreate("Syntax ERROR in " + workerScript.name + ":<br>" + e);
workerScript.env.stopFlag = true; workerScript.env.stopFlag = true;
workerScript.running = false; workerScript.running = false;
@ -272,7 +272,7 @@ function startNetscript1Script(workerScript: WorkerScript): Promise<WorkerScript
} else { } else {
resolve(workerScript); resolve(workerScript);
} }
} catch (e) { } catch (e: any) {
e = e.toString(); e = e.toString();
if (!isScriptErrorMessage(e)) { if (!isScriptErrorMessage(e)) {
e = makeRuntimeRejectMsg(workerScript, e); e = makeRuntimeRejectMsg(workerScript, e);
@ -284,7 +284,7 @@ function startNetscript1Script(workerScript: WorkerScript): Promise<WorkerScript
try { try {
runInterpreter(); runInterpreter();
} catch (e) { } catch (e: any) {
if (isString(e)) { if (isString(e)) {
workerScript.errorMessage = e; workerScript.errorMessage = e;
return reject(workerScript); return reject(workerScript);

@ -191,6 +191,7 @@ export interface IPlayer {
getHomeComputer(): Server; getHomeComputer(): Server;
getNextCompanyPosition(company: Company, entryPosType: CompanyPosition): CompanyPosition | null; getNextCompanyPosition(company: Company, entryPosType: CompanyPosition): CompanyPosition | null;
getUpgradeHomeRamCost(): number; getUpgradeHomeRamCost(): number;
getUpgradeHomeCoresCost(): number;
gotoLocation(to: LocationName): boolean; gotoLocation(to: LocationName): boolean;
hasAugmentation(aug: string | Augmentation): boolean; hasAugmentation(aug: string | Augmentation): boolean;
hasCorporation(): boolean; hasCorporation(): boolean;

@ -198,6 +198,7 @@ export class PlayerObject implements IPlayer {
getHomeComputer: () => Server; getHomeComputer: () => Server;
getNextCompanyPosition: (company: Company, entryPosType: CompanyPosition) => CompanyPosition | null; getNextCompanyPosition: (company: Company, entryPosType: CompanyPosition) => CompanyPosition | null;
getUpgradeHomeRamCost: () => number; getUpgradeHomeRamCost: () => number;
getUpgradeHomeCoresCost: () => number;
gotoLocation: (to: LocationName) => boolean; gotoLocation: (to: LocationName) => boolean;
hasAugmentation: (aug: string | Augmentation) => boolean; hasAugmentation: (aug: string | Augmentation) => boolean;
hasCorporation: () => boolean; hasCorporation: () => boolean;
@ -569,6 +570,7 @@ export class PlayerObject implements IPlayer {
this.getCurrentServer = serverMethods.getCurrentServer; this.getCurrentServer = serverMethods.getCurrentServer;
this.getHomeComputer = serverMethods.getHomeComputer; this.getHomeComputer = serverMethods.getHomeComputer;
this.getUpgradeHomeRamCost = serverMethods.getUpgradeHomeRamCost; this.getUpgradeHomeRamCost = serverMethods.getUpgradeHomeRamCost;
this.getUpgradeHomeCoresCost = serverMethods.getUpgradeHomeCoresCost;
this.createHacknetServer = serverMethods.createHacknetServer; this.createHacknetServer = serverMethods.createHacknetServer;
this.factionWorkType = ""; this.factionWorkType = "";
this.committingCrimeThruSingFn = false; this.committingCrimeThruSingFn = false;

@ -451,9 +451,8 @@ export function gainIntelligenceExp(this: IPlayer, exp: number): void {
} }
if (SourceFileFlags[5] > 0 || this.intelligence > 0) { if (SourceFileFlags[5] > 0 || this.intelligence > 0) {
this.intelligence_exp += exp; this.intelligence_exp += exp;
this.intelligence = Math.floor(this.calculateSkill(this.intelligence_exp));
} }
this.intelligence = Math.floor(this.calculateSkill(this.intelligence_exp));
} }
//Given a string expression like "str" or "strength", returns the given stat //Given a string expression like "str" or "strength", returns the given stat

@ -40,6 +40,10 @@ export function getUpgradeHomeRamCost(this: IPlayer): number {
return cost; return cost;
} }
export function getUpgradeHomeCoresCost(this: IPlayer): number {
return 1e9 * Math.pow(7.5, this.getHomeComputer().cpuCores);
}
export function createHacknetServer(this: IPlayer): HacknetServer { export function createHacknetServer(this: IPlayer): HacknetServer {
const numOwned = this.hacknetNodes.length; const numOwned = this.hacknetNodes.length;
const name = `hacknet-node-${numOwned}`; const name = `hacknet-node-${numOwned}`;

@ -29,5 +29,4 @@ export function loadPlayer(saveString: string): void {
} }
Player.exploits = sanitizeExploits(Player.exploits); Player.exploits = sanitizeExploits(Player.exploits);
console.log(Player.bladeburner);
} }

@ -11,7 +11,7 @@ import { SourceFileFlags } from "./SourceFile/SourceFileFlags";
import { loadStockMarket, StockMarket } from "./StockMarket/StockMarket"; import { loadStockMarket, StockMarket } from "./StockMarket/StockMarket";
import { staneksGift, loadStaneksGift } from "./CotMG/Helper"; import { staneksGift, loadStaneksGift } from "./CotMG/Helper";
import { GameSavedEvents } from "./ui/React/Snackbar"; import { SnackbarEvents } from "./ui/React/Snackbar";
import * as ExportBonus from "./ExportBonus"; import * as ExportBonus from "./ExportBonus";
@ -64,7 +64,7 @@ class BitburnerSaveObject {
const saveString = this.getSaveString(); const saveString = this.getSaveString();
save(saveString) save(saveString)
.then(() => GameSavedEvents.emit()) .then(() => SnackbarEvents.emit("Game Saved!", "info"))
.catch((err) => console.error(err)); .catch((err) => console.error(err));
} }
@ -76,9 +76,10 @@ class BitburnerSaveObject {
const bn = Player.bitNodeN; const bn = Player.bitNodeN;
const filename = `bitburnerSave_BN${bn}x${SourceFileFlags[bn]}_${epochTime}.json`; const filename = `bitburnerSave_BN${bn}x${SourceFileFlags[bn]}_${epochTime}.json`;
const file = new Blob([saveString], { type: "text/plain" }); const file = new Blob([saveString], { type: "text/plain" });
if (window.navigator.msSaveOrOpenBlob) { const navigator = window.navigator as any;
if (navigator.msSaveOrOpenBlob) {
// IE10+ // IE10+
window.navigator.msSaveOrOpenBlob(file, filename); navigator.msSaveOrOpenBlob(file, filename);
} else { } else {
// Others // Others
const a = document.createElement("a"), const a = document.createElement("a"),
@ -156,6 +157,24 @@ function evaluateVersionCompatibility(ver: string): void {
} }
} }
} }
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;
}
// 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;
}
}
}
} }
function loadGame(saveString: string): boolean { function loadGame(saveString: string): boolean {

@ -58,9 +58,10 @@ export class Script {
download(): void { download(): void {
const filename = this.filename + ".js"; const filename = this.filename + ".js";
const file = new Blob([this.code], { type: "text/plain" }); const file = new Blob([this.code], { type: "text/plain" });
if (window.navigator.msSaveOrOpenBlob) { const navigator = window.navigator as any;
if (navigator.msSaveOrOpenBlob) {
// IE10+ // IE10+
window.navigator.msSaveOrOpenBlob(file, filename); navigator.msSaveOrOpenBlob(file, filename);
} else { } else {
// Others // Others
const a = document.createElement("a"), const a = document.createElement("a"),
@ -112,6 +113,10 @@ export class Script {
this.markUpdated(); this.markUpdated();
} }
imports(): string[] {
return [];
}
// Serialize the current object to a JSON save state // Serialize the current object to a JSON save state
toJSON(): any { toJSON(): any {
return Generic_toJSON("Script", this); return Generic_toJSON("Script", this);

@ -23,6 +23,7 @@ import { Settings } from "../../Settings/Settings";
import { iTutorialNextStep, ITutorial, iTutorialSteps } from "../../InteractiveTutorial"; import { iTutorialNextStep, ITutorial, iTutorialSteps } from "../../InteractiveTutorial";
import { debounce } from "lodash"; import { debounce } from "lodash";
import { saveObject } from "../../SaveObject"; import { saveObject } from "../../SaveObject";
import { loadThemes } from "./themes";
import Button from "@mui/material/Button"; import Button from "@mui/material/Button";
import Typography from "@mui/material/Typography"; import Typography from "@mui/material/Typography";
@ -312,6 +313,7 @@ export function Root(props: IProps): React.ReactElement {
}); });
monaco.languages.typescript.javascriptDefaults.addExtraLib(libSource, "netscript.d.ts"); monaco.languages.typescript.javascriptDefaults.addExtraLib(libSource, "netscript.d.ts");
monaco.languages.typescript.typescriptDefaults.addExtraLib(libSource, "netscript.d.ts"); monaco.languages.typescript.typescriptDefaults.addExtraLib(libSource, "netscript.d.ts");
loadThemes(monaco);
} }
return ( return (

@ -61,7 +61,7 @@ export class BaseServer {
// For Literature files, this array contains only the filename (string) // For Literature files, this array contains only the filename (string)
// For Messages, it contains the actual Message object // For Messages, it contains the actual Message object
// TODO Separate literature files into its own property // TODO Separate literature files into its own property
messages: (Message | string)[] = []; messages: string[] = [];
// Name of company/faction/etc. that this server belongs to. // Name of company/faction/etc. that this server belongs to.
// Optional, not applicable to all Servers // Optional, not applicable to all Servers

@ -3,7 +3,6 @@ import { IRouter } from "../../ui/Router";
import { IPlayer } from "../../PersonObjects/IPlayer"; import { IPlayer } from "../../PersonObjects/IPlayer";
import { BaseServer } from "../../Server/BaseServer"; import { BaseServer } from "../../Server/BaseServer";
import { showMessage } from "../../Message/MessageHelpers"; import { showMessage } from "../../Message/MessageHelpers";
import { Message } from "../../Message/Message";
import { showLiterature } from "../../Literature/LiteratureHelpers"; import { showLiterature } from "../../Literature/LiteratureHelpers";
export function cat( export function cat(
@ -29,12 +28,12 @@ export function cat(
for (let i = 0; i < server.messages.length; ++i) { for (let i = 0; i < server.messages.length; ++i) {
if (filename.endsWith(".lit") && server.messages[i] === filename) { if (filename.endsWith(".lit") && server.messages[i] === filename) {
const file = server.messages[i]; const file = server.messages[i];
if (file instanceof Message) throw new Error(".lit file should not be a .msg"); if (file.endsWith(".msg")) throw new Error(".lit file should not be a .msg");
showLiterature(file); showLiterature(file);
return; return;
} else if (filename.endsWith(".msg")) { } else if (filename.endsWith(".msg")) {
const file = server.messages[i] as Message; const file = server.messages[i];
if (file.filename !== filename) continue; if (file !== filename) continue;
showMessage(file); showMessage(file);
return; return;
} }

@ -2,7 +2,6 @@ import { ITerminal } from "../ITerminal";
import { IRouter } from "../../ui/Router"; import { IRouter } from "../../ui/Router";
import { IPlayer } from "../../PersonObjects/IPlayer"; import { IPlayer } from "../../PersonObjects/IPlayer";
import { BaseServer } from "../../Server/BaseServer"; import { BaseServer } from "../../Server/BaseServer";
import { Message } from "../../Message/Message";
import { getFirstParentDirectory, isValidDirectoryPath, evaluateDirectoryPath } from "../../Terminal/DirectoryHelpers"; import { getFirstParentDirectory, isValidDirectoryPath, evaluateDirectoryPath } from "../../Terminal/DirectoryHelpers";
export function ls( export function ls(
@ -103,8 +102,7 @@ export function ls(
for (const script of s.scripts) handleFn(script.filename, allScripts); for (const script of s.scripts) handleFn(script.filename, allScripts);
for (const txt of s.textFiles) handleFn(txt.fn, allTextFiles); for (const txt of s.textFiles) handleFn(txt.fn, allTextFiles);
for (const contract of s.contracts) handleFn(contract.fn, allContracts); for (const contract of s.contracts) handleFn(contract.fn, allContracts);
for (const msgOrLit of s.messages) for (const msgOrLit of s.messages) handleFn(msgOrLit, allMessages);
msgOrLit instanceof Message ? handleFn(msgOrLit.filename, allMessages) : handleFn(msgOrLit, allMessages);
// Sort the files/folders alphabetically then print each // Sort the files/folders alphabetically then print each
allPrograms.sort(); allPrograms.sort();

@ -34,7 +34,7 @@ export function scp(
if (scriptname.endsWith(".lit")) { if (scriptname.endsWith(".lit")) {
let found = false; let found = false;
for (let i = 0; i < server.messages.length; ++i) { for (let i = 0; i < server.messages.length; ++i) {
if (!(server.messages[i] instanceof Message) && server.messages[i] == scriptname) { if (server.messages[i] == scriptname) {
found = true; found = true;
break; break;
} }

@ -71,7 +71,7 @@ export function determineAllPossibilitiesForTabCompletion(
function addAllLitFiles(): void { function addAllLitFiles(): void {
for (const file of currServ.messages) { for (const file of currServ.messages) {
if (!(file instanceof Message)) { if (!file.endsWith(".msg")) {
allPos.push(file); allPos.push(file);
} }
} }
@ -79,8 +79,8 @@ export function determineAllPossibilitiesForTabCompletion(
function addAllMessages(): void { function addAllMessages(): void {
for (const file of currServ.messages) { for (const file of currServ.messages) {
if (file instanceof Message) { if (file.endsWith(".msg")) {
allPos.push(file.filename); allPos.push(file);
} }
} }
} }

@ -35,9 +35,10 @@ export class TextFile {
const filename: string = this.fn; const filename: string = this.fn;
const file: Blob = new Blob([this.text], { type: "text/plain" }); const file: Blob = new Blob([this.text], { type: "text/plain" });
/* tslint:disable-next-line:strict-boolean-expressions */ /* tslint:disable-next-line:strict-boolean-expressions */
if (window.navigator.msSaveOrOpenBlob) { const navigator = window.navigator as any;
if (navigator.msSaveOrOpenBlob) {
// IE10+ // IE10+
window.navigator.msSaveOrOpenBlob(file, filename); navigator.msSaveOrOpenBlob(file, filename);
} else { } else {
// Others // Others
const a: HTMLAnchorElement = document.createElement("a"); const a: HTMLAnchorElement = document.createElement("a");

@ -67,7 +67,7 @@ import { CharacterOverview } from "./React/CharacterOverview";
import { BladeburnerCinematic } from "../Bladeburner/ui/BladeburnerCinematic"; import { BladeburnerCinematic } from "../Bladeburner/ui/BladeburnerCinematic";
import { workerScripts } from "../Netscript/WorkerScripts"; import { workerScripts } from "../Netscript/WorkerScripts";
import { Unclickable } from "../Exploits/Unclickable"; import { Unclickable } from "../Exploits/Unclickable";
import { Snackbar } from "./React/Snackbar"; import { Snackbar, SnackbarProvider } from "./React/Snackbar";
import { LogBoxManager } from "./React/LogBoxManager"; import { LogBoxManager } from "./React/LogBoxManager";
import { AlertManager } from "./React/AlertManager"; import { AlertManager } from "./React/AlertManager";
import { PromptManager } from "./React/PromptManager"; import { PromptManager } from "./React/PromptManager";
@ -302,102 +302,104 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
) : page === Page.Work ? ( ) : page === Page.Work ? (
<WorkInProgressRoot /> <WorkInProgressRoot />
) : ( ) : (
<Box display="flex" flexDirection="row" width="100%"> <SnackbarProvider>
<SidebarRoot player={player} router={Router} page={page} /> <Box display="flex" flexDirection="row" width="100%">
<Box className={classes.root} flexGrow={1} display="block" px={1} height="100vh"> <SidebarRoot player={player} router={Router} page={page} />
{page === Page.Terminal ? ( <Box className={classes.root} flexGrow={1} display="block" px={1} height="100vh">
<TerminalRoot terminal={terminal} router={Router} player={player} /> {page === Page.Terminal ? (
) : page === Page.Sleeves ? ( <TerminalRoot terminal={terminal} router={Router} player={player} />
<SleeveRoot /> ) : page === Page.Sleeves ? (
) : page === Page.Stats ? ( <SleeveRoot />
<CharacterStats /> ) : page === Page.StaneksGift ? (
) : page === Page.StaneksGift ? ( <StaneksGiftRoot staneksGift={staneksGift} />
<StaneksGiftRoot staneksGift={staneksGift} /> ) : page === Page.Stats ? (
) : page === Page.ScriptEditor ? ( <CharacterStats />
<ScriptEditorRoot filename={filename} code={code} player={player} router={Router} /> ) : page === Page.ScriptEditor ? (
) : page === Page.ActiveScripts ? ( <ScriptEditorRoot filename={filename} code={code} player={player} router={Router} />
<ActiveScriptsRoot workerScripts={workerScripts} /> ) : page === Page.ActiveScripts ? (
) : page === Page.Hacknet ? ( <ActiveScriptsRoot workerScripts={workerScripts} />
<HacknetRoot player={player} /> ) : page === Page.Hacknet ? (
) : page === Page.CreateProgram ? ( <HacknetRoot player={player} />
<ProgramsRoot /> ) : page === Page.CreateProgram ? (
) : page === Page.Factions ? ( <ProgramsRoot />
<FactionsRoot player={player} router={Router} /> ) : page === Page.Factions ? (
) : page === Page.Faction ? ( <FactionsRoot player={player} router={Router} />
<FactionRoot faction={faction} /> ) : page === Page.Faction ? (
) : page === Page.Milestones ? ( <FactionRoot faction={faction} />
<MilestonesRoot player={player} /> ) : page === Page.Milestones ? (
) : page === Page.Tutorial ? ( <MilestonesRoot player={player} />
<TutorialRoot /> ) : page === Page.Tutorial ? (
) : page === Page.DevMenu ? ( <TutorialRoot />
<DevMenuRoot player={player} engine={engine} router={Router} /> ) : page === Page.DevMenu ? (
) : page === Page.Gang ? ( <DevMenuRoot player={player} engine={engine} router={Router} />
<GangRoot /> ) : page === Page.Gang ? (
) : page === Page.Corporation ? ( <GangRoot />
<CorporationRoot /> ) : page === Page.Corporation ? (
) : page === Page.Bladeburner ? ( <CorporationRoot />
<BladeburnerRoot /> ) : page === Page.Bladeburner ? (
) : page === Page.Resleeves ? ( <BladeburnerRoot />
<ResleeveRoot /> ) : page === Page.Resleeves ? (
) : page === Page.Travel ? ( <ResleeveRoot />
<TravelAgencyRoot p={player} router={Router} /> ) : page === Page.Travel ? (
) : page === Page.StockMarket ? ( <TravelAgencyRoot p={player} router={Router} />
<StockMarketRoot ) : page === Page.StockMarket ? (
buyStockLong={buyStock} <StockMarketRoot
buyStockShort={shortStock} buyStockLong={buyStock}
cancelOrder={cancelOrder} buyStockShort={shortStock}
eventEmitterForReset={eventEmitterForUiReset} cancelOrder={cancelOrder}
initStockMarket={initStockMarketFnForReact} eventEmitterForReset={eventEmitterForUiReset}
p={player} initStockMarket={initStockMarketFnForReact}
placeOrder={placeOrder} p={player}
sellStockLong={sellStock} placeOrder={placeOrder}
sellStockShort={sellShort} sellStockLong={sellStock}
stockMarket={StockMarket} sellStockShort={sellShort}
/> stockMarket={StockMarket}
) : page === Page.City ? ( />
<LocationCity /> ) : page === Page.City ? (
) : page === Page.Job ? ( <LocationCity />
<GenericLocation loc={location} /> ) : page === Page.Job ? (
) : page === Page.Location ? ( <GenericLocation loc={location} />
<GenericLocation loc={location} /> ) : page === Page.Location ? (
) : page === Page.Options ? ( <GenericLocation loc={location} />
<GameOptionsRoot ) : page === Page.Options ? (
player={player} <GameOptionsRoot
save={() => saveObject.saveGame()} player={player}
export={() => saveObject.exportGame()} save={() => saveObject.saveGame()}
forceKill={() => { export={() => saveObject.exportGame()}
for (const server of GetAllServers()) { forceKill={() => {
server.runningScripts = []; for (const server of GetAllServers()) {
} server.runningScripts = [];
dialogBoxCreate("Forcefully deleted all running scripts. Please save and refresh page."); }
}} dialogBoxCreate("Forcefully deleted all running scripts. Please save and refresh page.");
softReset={() => { }}
dialogBoxCreate("Soft Reset!"); softReset={() => {
prestigeAugmentation(); dialogBoxCreate("Soft Reset!");
Router.toTerminal(); prestigeAugmentation();
}} Router.toTerminal();
/> }}
) : page === Page.Augmentations ? ( />
<AugmentationsRoot ) : page === Page.Augmentations ? (
exportGameFn={() => { <AugmentationsRoot
saveObject.exportGame(); exportGameFn={() => {
onExport(player); saveObject.exportGame();
}} onExport(player);
installAugmentationsFn={() => { }}
installAugmentations(); installAugmentationsFn={() => {
Router.toTerminal(); installAugmentations();
}} Router.toTerminal();
/> }}
) : ( />
<> ) : (
<Typography>Cannot load</Typography> <>
</> <Typography>Cannot load</Typography>
)} </>
)}
</Box>
</Box> </Box>
</Box> <Snackbar />
</SnackbarProvider>
)} )}
<Unclickable /> <Unclickable />
<Snackbar />
<LogBoxManager /> <LogBoxManager />
<AlertManager /> <AlertManager />
<PromptManager /> <PromptManager />

@ -46,6 +46,31 @@ function Intelligence(): React.ReactElement {
); );
} }
function Bladeburner(): React.ReactElement {
const player = use.Player();
const classes = useStyles();
const bladeburner = player.bladeburner;
if (bladeburner === null) return <></>;
const action = bladeburner.getTypeAndNameFromActionId(bladeburner.action);
if (action.type === "Idle") return <></>;
return (
<>
<TableRow>
<TableCell component="th" scope="row" colSpan={2} classes={{ root: classes.cellNone }}>
<Typography>Bladeburner:</Typography>
</TableCell>
</TableRow>
<TableRow>
<TableCell component="th" scope="row" colSpan={2} classes={{ root: classes.cellNone }}>
<Typography>
{action.type}: {action.name}
</Typography>
</TableCell>
</TableRow>
</>
);
}
function Work(): React.ReactElement { function Work(): React.ReactElement {
const player = use.Player(); const player = use.Player();
const router = use.Router(); const router = use.Router();
@ -269,6 +294,7 @@ export function CharacterOverview({ save }: IProps): React.ReactElement {
</TableCell> </TableCell>
</TableRow> </TableRow>
<Work /> <Work />
<Bladeburner />
<TableRow> <TableRow>
<TableCell align="center" colSpan={2} classes={{ root: classes.cellNone }}> <TableCell align="center" colSpan={2} classes={{ root: classes.cellNone }}>

@ -1,29 +1,48 @@
import React, { useState, useEffect } from "react"; import React, { useEffect } from "react";
import { useSnackbar, SnackbarProvider as SB } from "notistack";
import { Snackbar as S } from "@mui/material";
import { EventEmitter } from "../../utils/EventEmitter"; import { EventEmitter } from "../../utils/EventEmitter";
import Typography from "@mui/material/Typography"; import Alert from "@mui/material/Alert";
import Paper from "@mui/material/Paper"; import Paper from "@mui/material/Paper";
export const GameSavedEvents = new EventEmitter<[]>(); interface IProps {
children: React.ReactNode | React.ReactNode[];
}
export function Snackbar(): React.ReactElement { export function SnackbarProvider(props: IProps): React.ReactElement {
const [open, setOpen] = useState(false);
useEffect(() => GameSavedEvents.subscribe(() => setOpen(true)));
return ( return (
<S <SB dense maxSnack={9} anchorOrigin={{ horizontal: "right", vertical: "bottom" }} autoHideDuration={2000}>
open={open} {props.children}
anchorOrigin={{ </SB>
vertical: "top",
horizontal: "center",
}}
autoHideDuration={2000}
onClose={() => setOpen(false)}
>
<Paper sx={{ p: 2 }}>
<Typography>Game Saved!</Typography>
</Paper>
</S>
); );
} }
export const SnackbarEvents = new EventEmitter<[string, "success" | "warning" | "error" | "info"]>();
export function Snackbar(): React.ReactElement {
const { enqueueSnackbar } = useSnackbar();
useEffect(() =>
SnackbarEvents.subscribe((s, variant) =>
enqueueSnackbar(<Alert severity={variant}>{s}</Alert>, {
content: (k, m) => <Paper key={k}>{m}</Paper>,
variant: variant,
}),
),
);
return <></>;
// return (
// <S
// open={open}
// anchorOrigin={{
// vertical: "top",
// horizontal: "center",
// }}
// autoHideDuration={2000}
// onClose={() => setOpen(false)}
// >
// <Paper sx={{ p: 2 }}>
// <Typography>Game Saved!</Typography>
// </Paper>
// </S>
// );
}

@ -294,6 +294,27 @@ export function refreshTheme(): void {
}, },
}, },
}, },
MuiAlert: {
styleOverrides: {
root: {
backgroundColor: Settings.theme.black,
borderRadius: 0,
border: "1px solid " + Settings.theme.well,
},
standardSuccess: {
color: Settings.theme.successLight,
},
standardError: {
color: Settings.theme.errorlight,
},
standardWarning: {
color: Settings.theme.warninglight,
},
standardInfo: {
color: Settings.theme.infolight,
},
},
},
}, },
}); });
} }

@ -1,7 +1,6 @@
/* eslint-disable spaced-comment */ /* eslint-disable spaced-comment */
module.exports = { module.exports = {
plugins: [ plugins: [
"stylelint-declaration-use-variable",
"stylelint-order" /*, "stylelint-order" /*,
"stylelint-scss" */, "stylelint-scss" */,
], ],

@ -95,7 +95,7 @@ describe("determineAllPossibilitiesForTabCompletion", function () {
Player.getHomeComputer().writeToTextFile("note.txt", "oh hai mark"); Player.getHomeComputer().writeToTextFile("note.txt", "oh hai mark");
Player.getHomeComputer().writeToScriptFile("/www/script.js", "oh hai mark"); Player.getHomeComputer().writeToScriptFile("/www/script.js", "oh hai mark");
Player.getHomeComputer().contracts.push(new CodingContract("linklist.cct")); Player.getHomeComputer().contracts.push(new CodingContract("linklist.cct"));
Player.getHomeComputer().messages.push(new Message("asl.msg")); Player.getHomeComputer().messages.push("asl.msg");
Player.getHomeComputer().messages.push("af.lit"); Player.getHomeComputer().messages.push("af.lit");
expect(determineAllPossibilitiesForTabCompletion(Player, "rm ", 0)).equal([ expect(determineAllPossibilitiesForTabCompletion(Player, "rm ", 0)).equal([
"/www/script.js", "/www/script.js",
@ -120,7 +120,7 @@ describe("determineAllPossibilitiesForTabCompletion", function () {
it("completes the cat command", () => { it("completes the cat command", () => {
Player.getHomeComputer().writeToTextFile("/www/note.txt", "oh hai mark"); Player.getHomeComputer().writeToTextFile("/www/note.txt", "oh hai mark");
Player.getHomeComputer().messages.push(new Message("asl.msg")); Player.getHomeComputer().messages.push("asl.msg");
Player.getHomeComputer().messages.push("af.lit"); Player.getHomeComputer().messages.push("af.lit");
expect(determineAllPossibilitiesForTabCompletion(Player, "cat ", 0)).equal([ expect(determineAllPossibilitiesForTabCompletion(Player, "cat ", 0)).equal([
"asl.msg", "asl.msg",