mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-18 21:53:50 +01:00
Unify error handling
This commit is contained in:
parent
5798c4c7d3
commit
572c68738f
@ -106,7 +106,7 @@ function initWebserver(): void {
|
||||
msg: "Home server does not exist.",
|
||||
};
|
||||
}
|
||||
const { success, overwritten } = home.writeToScriptFile(Player, filename, code);
|
||||
const { success, overwritten } = home.writeToScriptFile(filename, code);
|
||||
let script;
|
||||
if (success) {
|
||||
script = home.getScript(filename);
|
||||
|
@ -19,7 +19,7 @@ import {
|
||||
import { createRandomIp } from "../utils/IPAddress";
|
||||
|
||||
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { Player } from "../Player";
|
||||
|
||||
interface IConstructorParams {
|
||||
adminRights?: boolean;
|
||||
@ -123,9 +123,9 @@ export class HacknetServer extends BaseServer implements IHacknetNode {
|
||||
}
|
||||
}
|
||||
|
||||
updateRamUsed(ram: number, player: IPlayer): void {
|
||||
super.updateRamUsed(ram, player);
|
||||
this.updateHashRate(player.mults.hacknet_node_money);
|
||||
updateRamUsed(ram: number): void {
|
||||
super.updateRamUsed(ram);
|
||||
this.updateHashRate(Player.mults.hacknet_node_money);
|
||||
}
|
||||
|
||||
updateHashCapacity(): void {
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { getRamCost } from "./RamCostGenerator";
|
||||
import type { WorkerScript } from "./WorkerScript";
|
||||
import { Player } from "../Player";
|
||||
import { helpers } from "./NetscriptHelpers";
|
||||
import { ScriptArg } from "./ScriptArg";
|
||||
import { NSEnums } from "src/ScriptEditor/NetscriptDefinitions";
|
||||
@ -50,7 +49,7 @@ function wrapFunction(
|
||||
};
|
||||
function wrappedFunction(...args: unknown[]): unknown {
|
||||
helpers.checkEnvFlags(ctx);
|
||||
helpers.updateDynamicRam(ctx, getRamCost(Player, ...tree, ctx.function));
|
||||
helpers.updateDynamicRam(ctx, getRamCost(...tree, ctx.function));
|
||||
return func(ctx)(...args);
|
||||
}
|
||||
const parent = getNestedProperty(wrappedAPI, tree);
|
||||
|
@ -57,7 +57,6 @@ export const helpers = {
|
||||
gangMember,
|
||||
gangTask,
|
||||
log,
|
||||
getFunctionNames,
|
||||
getRunningScript,
|
||||
getRunningScriptByArgs,
|
||||
getCannotFindRunningScriptErrorMessage,
|
||||
@ -205,8 +204,8 @@ function makeRuntimeErrorMsg(ctx: NetscriptContext, msg: string): string {
|
||||
}
|
||||
|
||||
log(ctx, () => msg);
|
||||
let rejectMsg = `${caller}: ${msg}`;
|
||||
if (userstack.length !== 0) rejectMsg += `<br><br>Stack:<br>${userstack.join("<br>")}`;
|
||||
let rejectMsg = `RUNTIME ERROR\n${ws.name}@${ws.hostname} (PID - ${ws.pid})\n\n${caller}: ${msg}`;
|
||||
if (userstack.length !== 0) rejectMsg += `\n\nStack:\n${userstack.join("\n")}`;
|
||||
return makeBasicErrorMsg(ws, rejectMsg);
|
||||
}
|
||||
|
||||
@ -253,14 +252,15 @@ function checkEnvFlags(ctx: NetscriptContext): void {
|
||||
if (ws.env.runningFn && ctx.function !== "asleep") {
|
||||
//This one has no error message so it will not create a dialog
|
||||
if (ws.delayReject) ws.delayReject(new ScriptDeath(ws));
|
||||
ws.errorMessage = makeBasicErrorMsg(
|
||||
ws,
|
||||
ws.env.stopFlag = true;
|
||||
log(ctx, () => "Failed to run due to failed concurrency check.");
|
||||
throw makeRuntimeErrorMsg(
|
||||
ctx,
|
||||
`Concurrent calls to Netscript functions are not allowed!
|
||||
Did you forget to await hack(), grow(), or some other
|
||||
promise-returning function?
|
||||
Currently running: ${ws.env.runningFn} tried to run: ${ctx.function}`,
|
||||
);
|
||||
throw new ScriptDeath(ws);
|
||||
}
|
||||
}
|
||||
|
||||
@ -295,9 +295,10 @@ function updateDynamicRam(ctx: NetscriptContext, ramCost: number): void {
|
||||
ws.dynamicRamUsage += ramCost;
|
||||
if (ws.dynamicRamUsage > 1.01 * ws.ramUsage) {
|
||||
log(ctx, () => "Insufficient static ram available.");
|
||||
ws.errorMessage = makeBasicErrorMsg(
|
||||
ws,
|
||||
`Dynamic RAM usage calculated to be greater than initial RAM usage on fn: ${fnName}.
|
||||
ws.env.stopFlag = true;
|
||||
throw makeRuntimeErrorMsg(
|
||||
ctx,
|
||||
`Dynamic RAM usage calculated to be greater than initial RAM usage.
|
||||
This is probably because you somehow circumvented the static RAM calculation.
|
||||
|
||||
Threads: ${threads}
|
||||
@ -306,14 +307,13 @@ function updateDynamicRam(ctx: NetscriptContext, ramCost: number): void {
|
||||
|
||||
One of these could be the reason:
|
||||
* Using eval() to get a reference to a ns function
|
||||
const myScan = eval('ns.scan');
|
||||
\u00a0\u00a0const myScan = eval('ns.scan');
|
||||
|
||||
* Using map access to do the same
|
||||
const myScan = ns['scan'];
|
||||
\u00a0\u00a0const myScan = ns['scan'];
|
||||
|
||||
Sorry :(`,
|
||||
);
|
||||
throw new ScriptDeath(ws);
|
||||
}
|
||||
}
|
||||
|
||||
@ -368,7 +368,7 @@ function isScriptArgs(args: unknown): args is ScriptArg[] {
|
||||
return Array.isArray(args) && args.every(isScriptArg);
|
||||
}
|
||||
|
||||
async function hack(
|
||||
function hack(
|
||||
ctx: NetscriptContext,
|
||||
hostname: string,
|
||||
manual: boolean,
|
||||
@ -454,7 +454,7 @@ async function hack(
|
||||
if (manual) {
|
||||
server.backdoorInstalled = true;
|
||||
}
|
||||
return Promise.resolve(moneyGained);
|
||||
return moneyGained;
|
||||
} else {
|
||||
// Player only gains 25% exp for failure?
|
||||
Player.gainHackingExp(expGainedOnFailure);
|
||||
@ -466,7 +466,7 @@ async function hack(
|
||||
expGainedOnFailure,
|
||||
)} exp (t=${numeralWrapper.formatThreads(threads)})`,
|
||||
);
|
||||
return Promise.resolve(0);
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -598,10 +598,10 @@ function getRunningScriptByArgs(
|
||||
scriptArgs: ScriptArg[],
|
||||
): RunningScript | null {
|
||||
if (!Array.isArray(scriptArgs)) {
|
||||
throw helpers.makeBasicErrorMsg(
|
||||
ctx.workerScript,
|
||||
`Invalid scriptArgs argument passed into getRunningScript() from ${ctx.function}(). ` +
|
||||
`This is probably a bug. Please report to game developer`,
|
||||
throw helpers.makeRuntimeErrorMsg(
|
||||
ctx,
|
||||
"Invalid scriptArgs argument passed into getRunningScriptByArgs().\n" +
|
||||
"This is probably a bug. Please report to game developer",
|
||||
);
|
||||
}
|
||||
|
||||
@ -619,21 +619,6 @@ function getRunningScriptByArgs(
|
||||
return ctx.workerScript.scriptRef;
|
||||
}
|
||||
|
||||
/** Provides an array of all function names on a nested object */
|
||||
function getFunctionNames(obj: object, prefix: string): string[] {
|
||||
const functionNames: string[] = [];
|
||||
for (const [key, value] of Object.entries(obj)) {
|
||||
if (key === "args") {
|
||||
continue;
|
||||
} else if (typeof value == "function") {
|
||||
functionNames.push(prefix + key);
|
||||
} else if (typeof value == "object") {
|
||||
functionNames.push(...getFunctionNames(value, key + "."));
|
||||
}
|
||||
}
|
||||
return functionNames;
|
||||
}
|
||||
|
||||
function getRunningScriptByPid(pid: number): RunningScript | null {
|
||||
for (const server of GetAllServers()) {
|
||||
const runningScript = findRunningScriptByPid(pid, server);
|
||||
|
@ -1,13 +1,12 @@
|
||||
import { IPlayer } from "src/PersonObjects/IPlayer";
|
||||
import { Player } from "../Player";
|
||||
import { IMap } from "../types";
|
||||
|
||||
import { NS as INS } from "../ScriptEditor/NetscriptDefinitions";
|
||||
|
||||
import { INetscriptExtra } from "../NetscriptFunctions/Extra";
|
||||
|
||||
type RamCostTree<API> = {
|
||||
[Property in keyof API]: API[Property] extends () => void
|
||||
? number | ((p: IPlayer) => void)
|
||||
? number | (() => void)
|
||||
: API[Property] extends object
|
||||
? RamCostTree<API[Property]>
|
||||
: never;
|
||||
@ -89,10 +88,10 @@ export const RamCostConstants: IMap<number> = {
|
||||
ScriptStanekAcceptGift: 2,
|
||||
};
|
||||
|
||||
function SF4Cost(cost: number): (player: IPlayer) => number {
|
||||
return (player: IPlayer): number => {
|
||||
if (player.bitNodeN === 4) return cost;
|
||||
const sf4 = player.sourceFileLvl(4);
|
||||
function SF4Cost(cost: number): () => number {
|
||||
return () => {
|
||||
if (Player.bitNodeN === 4) return cost;
|
||||
const sf4 = Player.sourceFileLvl(4);
|
||||
if (sf4 <= 1) return cost * 16;
|
||||
if (sf4 === 2) return cost * 4;
|
||||
return cost;
|
||||
@ -611,7 +610,7 @@ export const RamCosts: IMap<any> = SourceRamCosts;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const _typecheck: RamCostTree<INS & INetscriptExtra> = SourceRamCosts;
|
||||
|
||||
export function getRamCost(player: IPlayer, ...args: string[]): number {
|
||||
export function getRamCost(...args: string[]): number {
|
||||
if (args.length === 0) {
|
||||
console.warn(`No arguments passed to getRamCost()`);
|
||||
return 0;
|
||||
@ -637,7 +636,7 @@ export function getRamCost(player: IPlayer, ...args: string[]): number {
|
||||
}
|
||||
|
||||
if (typeof curr === "function") {
|
||||
return curr(player);
|
||||
return curr();
|
||||
}
|
||||
|
||||
console.warn(`Unexpected type (${curr}) for value [${args}]`);
|
||||
|
@ -12,7 +12,6 @@ import { GetServer } from "../Server/AllServers";
|
||||
|
||||
import { errorDialog } from "../ui/React/DialogBox";
|
||||
import { AddRecentScript } from "./RecentScripts";
|
||||
import { Player } from "../Player";
|
||||
import { ITutorial } from "../InteractiveTutorial";
|
||||
import { AlertEvents } from "../ui/React/AlertManager";
|
||||
|
||||
@ -102,8 +101,8 @@ function removeWorkerScript(workerScript: WorkerScript): void {
|
||||
|
||||
// Recalculate ram used on that server
|
||||
|
||||
server.updateRamUsed(0, Player);
|
||||
for (const rs of server.runningScripts) server.updateRamUsed(server.ramUsed + rs.ramUsage * rs.threads, Player);
|
||||
server.updateRamUsed(0);
|
||||
for (const rs of server.runningScripts) server.updateRamUsed(server.ramUsed + rs.ramUsage * rs.threads);
|
||||
|
||||
// Delete script from global pool (workerScripts)
|
||||
workerScripts.delete(workerScript.pid);
|
||||
|
@ -931,13 +931,13 @@ const base: InternalAPI<NS> = {
|
||||
}
|
||||
|
||||
// Create new script if it does not already exist
|
||||
const newScript = new Script(Player, file);
|
||||
const newScript = new Script(file);
|
||||
newScript.code = sourceScript.code;
|
||||
newScript.ramUsage = sourceScript.ramUsage;
|
||||
newScript.server = destServer.hostname;
|
||||
destServer.scripts.push(newScript);
|
||||
helpers.log(ctx, () => `File '${file}' copied over to '${destServer?.hostname}'.`);
|
||||
newScript.updateRamUsage(Player, destServer.scripts);
|
||||
newScript.updateRamUsage(destServer.scripts);
|
||||
}
|
||||
|
||||
return noFailures;
|
||||
@ -1492,12 +1492,12 @@ const base: InternalAPI<NS> = {
|
||||
let script = ctx.workerScript.getScriptOnServer(fn, server);
|
||||
if (script == null) {
|
||||
// Create a new script
|
||||
script = new Script(Player, fn, String(data), server.hostname, server.scripts);
|
||||
script = new Script(fn, String(data), server.hostname, server.scripts);
|
||||
server.scripts.push(script);
|
||||
return script.updateRamUsage(Player, server.scripts);
|
||||
return script.updateRamUsage(server.scripts);
|
||||
}
|
||||
mode === "w" ? (script.code = String(data)) : (script.code += data);
|
||||
return script.updateRamUsage(Player, server.scripts);
|
||||
return script.updateRamUsage(server.scripts);
|
||||
} else {
|
||||
// Write to text file
|
||||
if (!fn.endsWith(".txt")) throw helpers.makeRuntimeErrorMsg(ctx, `Invalid filename: ${fn}`);
|
||||
@ -1820,7 +1820,7 @@ const base: InternalAPI<NS> = {
|
||||
function (data) {
|
||||
let res;
|
||||
if (isScriptFilename(target)) {
|
||||
res = s.writeToScriptFile(Player, target, data);
|
||||
res = s.writeToScriptFile(target, data);
|
||||
} else {
|
||||
res = s.writeToTextFile(target, data);
|
||||
}
|
||||
@ -1950,4 +1950,18 @@ const ns = {
|
||||
...NetscriptExtra(),
|
||||
};
|
||||
|
||||
const possibleLogs = Object.fromEntries([...helpers.getFunctionNames(ns, "")].map((a) => [a, true]));
|
||||
const possibleLogs = Object.fromEntries([...getFunctionNames(ns, "")].map((a) => [a, true]));
|
||||
/** Provides an array of all function names on a nested object */
|
||||
function getFunctionNames(obj: object, prefix: string): string[] {
|
||||
const functionNames: string[] = [];
|
||||
for (const [key, value] of Object.entries(obj)) {
|
||||
if (key === "args") {
|
||||
continue;
|
||||
} else if (typeof value == "function") {
|
||||
functionNames.push(prefix + key);
|
||||
} else if (typeof value == "object") {
|
||||
functionNames.push(...getFunctionNames(value, key + "."));
|
||||
}
|
||||
}
|
||||
return functionNames;
|
||||
}
|
||||
|
@ -5,12 +5,9 @@
|
||||
import * as walk from "acorn-walk";
|
||||
import { parse } from "acorn";
|
||||
|
||||
import { helpers } from "./Netscript/NetscriptHelpers";
|
||||
import { ScriptUrl } from "./Script/ScriptUrl";
|
||||
import { WorkerScript } from "./Netscript/WorkerScript";
|
||||
import { Script } from "./Script/Script";
|
||||
import { areImportsEquals } from "./Terminal/DirectoryHelpers";
|
||||
import { IPlayer } from "./PersonObjects/IPlayer";
|
||||
import { ScriptModule } from "./Script/ScriptModule";
|
||||
|
||||
// Acorn type def is straight up incomplete so we have to fill with our own.
|
||||
@ -21,7 +18,7 @@ function makeScriptBlob(code: string): Blob {
|
||||
return new Blob([code], { type: "text/javascript" });
|
||||
}
|
||||
|
||||
export async function compile(player: IPlayer, script: Script, scripts: Script[]): Promise<ScriptModule> {
|
||||
export async function compile(script: Script, scripts: Script[]): Promise<ScriptModule> {
|
||||
//!shouldCompile ensures that script.module is non-null, hence the "as".
|
||||
if (!shouldCompile(script, scripts)) return script.module as Promise<ScriptModule>;
|
||||
script.queueCompile = true;
|
||||
@ -31,7 +28,7 @@ export async function compile(player: IPlayer, script: Script, scripts: Script[]
|
||||
//If multiple compiles were called on the same script before a compilation could be completed this ensures only one complilation is actually performed.
|
||||
if (!script.queueCompile) return script.module as Promise<ScriptModule>;
|
||||
script.queueCompile = false;
|
||||
script.updateRamUsage(player, scripts);
|
||||
script.updateRamUsage(scripts);
|
||||
const uurls = _getScriptUrls(script, scripts, []);
|
||||
const url = uurls[uurls.length - 1].url;
|
||||
if (script.url && script.url !== url) URL.revokeObjectURL(script.url);
|
||||
@ -50,50 +47,6 @@ export async function compile(player: IPlayer, script: Script, scripts: Script[]
|
||||
return script.module;
|
||||
}
|
||||
|
||||
// Begin executing a user JS script, and return a promise that resolves
|
||||
// or rejects when the script finishes.
|
||||
// - script is a script to execute (see Script.js). We depend only on .filename and .code.
|
||||
// scripts is an array of other scripts on the server.
|
||||
// env is the global environment that should be visible to all the scripts
|
||||
// (i.e. hack, grow, etc.).
|
||||
// When the promise returned by this resolves, we'll have finished
|
||||
// running the main function of the script.
|
||||
export async function executeJSScript(
|
||||
player: IPlayer,
|
||||
scripts: Script[] = [],
|
||||
workerScript: WorkerScript,
|
||||
): Promise<void> {
|
||||
const script = workerScript.getScript();
|
||||
if (script === null) throw new Error("script is null");
|
||||
const loadedModule = await compile(player, script, scripts);
|
||||
workerScript.ramUsage = script.ramUsage;
|
||||
|
||||
const ns = workerScript.env.vars;
|
||||
|
||||
if (!loadedModule) {
|
||||
throw helpers.makeBasicErrorMsg(
|
||||
workerScript,
|
||||
`${script.filename} cannot be run because the script module won't load`,
|
||||
);
|
||||
}
|
||||
// TODO: putting await in a non-async function yields unhelpful
|
||||
// "SyntaxError: unexpected reserved word" with no line number information.
|
||||
if (!loadedModule.main) {
|
||||
throw helpers.makeBasicErrorMsg(
|
||||
workerScript,
|
||||
`${script.filename} cannot be run because it does not have a main function.`,
|
||||
);
|
||||
}
|
||||
if (!ns) {
|
||||
throw helpers.makeBasicErrorMsg(
|
||||
workerScript,
|
||||
`${script.filename} cannot be run because the NS object hasn't been constructed properly.`,
|
||||
);
|
||||
}
|
||||
await loadedModule.main(ns);
|
||||
return;
|
||||
}
|
||||
|
||||
function isDependencyOutOfDate(filename: string, scripts: Script[], scriptModuleSequenceNumber: number): boolean {
|
||||
const depScript = scripts.find((s) => s.filename == filename);
|
||||
|
||||
|
@ -12,7 +12,7 @@ import { generateNextPid } from "./Netscript/Pid";
|
||||
import { CONSTANTS } from "./Constants";
|
||||
import { Interpreter } from "./ThirdParty/JSInterpreter";
|
||||
import { NetscriptFunctions } from "./NetscriptFunctions";
|
||||
import { executeJSScript, Node } from "./NetscriptJSEvaluator";
|
||||
import { compile, Node } from "./NetscriptJSEvaluator";
|
||||
import { IPort } from "./NetscriptPort";
|
||||
import { RunningScript } from "./Script/RunningScript";
|
||||
import { getRamUsageFromRunningScript } from "./Script/RunningScriptHelpers";
|
||||
@ -31,7 +31,6 @@ import { roundToTwo } from "./utils/helpers/roundToTwo";
|
||||
import { parse } from "acorn";
|
||||
import { simple as walksimple } from "acorn-walk";
|
||||
import { areFilesEqual } from "./Terminal/DirectoryHelpers";
|
||||
import { Player } from "./Player";
|
||||
import { Terminal } from "./Terminal";
|
||||
import { ScriptArg } from "./Netscript/ScriptArg";
|
||||
|
||||
@ -49,14 +48,26 @@ export function prestigeWorkerScripts(): void {
|
||||
workerScripts.clear();
|
||||
}
|
||||
|
||||
// JS script promises need a little massaging to have the same guarantees as netscript
|
||||
// promises. This does said massaging and kicks the script off. It returns a promise
|
||||
// that resolves or rejects when the corresponding worker script is done.
|
||||
const startNetscript2Script = (workerScript: WorkerScript): Promise<void> =>
|
||||
executeJSScript(Player, workerScript.getServer().scripts, workerScript);
|
||||
async function startNetscript2Script(workerScript: WorkerScript): Promise<void> {
|
||||
const scripts = workerScript.getServer().scripts;
|
||||
const script = workerScript.getScript();
|
||||
if (script === null) throw "workerScript had no associated script. This is a bug.";
|
||||
const loadedModule = await compile(script, scripts);
|
||||
workerScript.ramUsage = script.ramUsage;
|
||||
const ns = workerScript.env.vars;
|
||||
|
||||
function startNetscript1Script(workerScript: WorkerScript): Promise<void> {
|
||||
if (!loadedModule) throw `${script.filename} cannot be run because the script module won't load`;
|
||||
// TODO: Better error for "unexpected reserved word" when using await in non-async function?
|
||||
if (typeof loadedModule.main !== "function")
|
||||
throw `${script.filename} cannot be run because it does not have a main function.`;
|
||||
if (!ns) throw `${script.filename} cannot be run because the NS object hasn't been constructed properly.`;
|
||||
await loadedModule.main(ns);
|
||||
return;
|
||||
}
|
||||
|
||||
async function startNetscript1Script(workerScript: WorkerScript): Promise<void> {
|
||||
const code = workerScript.code;
|
||||
let errorToThrow: unknown;
|
||||
|
||||
//Process imports
|
||||
let codeWithImports, codeLineOffset;
|
||||
@ -65,10 +76,7 @@ function startNetscript1Script(workerScript: WorkerScript): Promise<void> {
|
||||
codeWithImports = importProcessingRes.code;
|
||||
codeLineOffset = importProcessingRes.lineOffset;
|
||||
} catch (e: unknown) {
|
||||
dialogBoxCreate(`Error processing Imports in ${workerScript.name} on ${workerScript.hostname}:\n\n${e}`);
|
||||
workerScript.env.stopFlag = true;
|
||||
killWorkerScript(workerScript);
|
||||
return Promise.resolve();
|
||||
throw `Error processing Imports in ${workerScript.name}@${workerScript.hostname}:\n\n${e}`;
|
||||
}
|
||||
|
||||
interface BasicObject {
|
||||
@ -77,20 +85,14 @@ function startNetscript1Script(workerScript: WorkerScript): Promise<void> {
|
||||
function wrapNS1Layer(int: Interpreter, intLayer: unknown, nsLayer = workerScript.env.vars as BasicObject) {
|
||||
for (const [name, entry] of Object.entries(nsLayer)) {
|
||||
if (typeof entry === "function") {
|
||||
// Async functions need to be wrapped. See JS-Interpreter documentation
|
||||
const wrapper = async (...args: unknown[]) => {
|
||||
// This async wrapper is sent a resolver function as an extra arg.
|
||||
// See JSInterpreter.js:3209
|
||||
try {
|
||||
// Sent a resolver function as an extra arg. See createAsyncFunction JSInterpreter.js:3209
|
||||
const callback = args.pop() as (value: unknown) => void;
|
||||
const result = await entry(...args.map((arg) => int.pseudoToNative(arg)));
|
||||
return callback(int.nativeToPseudo(result));
|
||||
} catch (e: unknown) {
|
||||
// NS1 interpreter doesn't cleanly handle throwing. Need to show dialog here.
|
||||
errorDialog(e, `RUNTIME ERROR:\n${workerScript.name}@${workerScript.hostname}\n\n`);
|
||||
workerScript.env.stopFlag = true;
|
||||
killWorkerScript(workerScript);
|
||||
return;
|
||||
errorToThrow = e;
|
||||
}
|
||||
};
|
||||
int.setProperty(intLayer, name, int.createAsyncFunction(wrapper));
|
||||
@ -109,31 +111,16 @@ function startNetscript1Script(workerScript: WorkerScript): Promise<void> {
|
||||
try {
|
||||
interpreter = new Interpreter(codeWithImports, wrapNS1Layer, codeLineOffset);
|
||||
} catch (e: unknown) {
|
||||
dialogBoxCreate(`Syntax ERROR in ${workerScript.name} on ${workerScript.hostname}:\n\n${String(e)}`);
|
||||
workerScript.env.stopFlag = true;
|
||||
killWorkerScript(workerScript);
|
||||
return Promise.resolve();
|
||||
throw `Syntax ERROR in ${workerScript.name}@${workerScript.hostname}:\n\n${String(e)}`;
|
||||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
function runInterpreter(): void {
|
||||
if (workerScript.env.stopFlag) resolve();
|
||||
|
||||
let more = true;
|
||||
let i = 0;
|
||||
while (i < 3 && more) {
|
||||
more = more && interpreter.step();
|
||||
i++;
|
||||
while (more) {
|
||||
if (errorToThrow) throw errorToThrow;
|
||||
if (workerScript.env.stopFlag) return;
|
||||
for (let i = 0; more && i < 3; i++) more = interpreter.step();
|
||||
if (more) await new Promise((r) => setTimeout(r, Settings.CodeInstructionRunTime));
|
||||
}
|
||||
|
||||
if (more) {
|
||||
setTimeout(runInterpreter, Settings.CodeInstructionRunTime);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
runInterpreter();
|
||||
});
|
||||
}
|
||||
|
||||
/* Since the JS Interpreter used for Netscript 1.0 only supports ES5, the keyword
|
||||
@ -326,7 +313,7 @@ function createAndAddWorkerScript(runningScriptObj: RunningScript, server: BaseS
|
||||
return false;
|
||||
}
|
||||
|
||||
server.updateRamUsed(roundToTwo(server.ramUsed + ramUsage), Player);
|
||||
server.updateRamUsed(roundToTwo(server.ramUsed + ramUsage));
|
||||
|
||||
// Get the pid
|
||||
const pid = generateNextPid();
|
||||
@ -346,20 +333,10 @@ function createAndAddWorkerScript(runningScriptObj: RunningScript, server: BaseS
|
||||
workerScripts.set(pid, workerScript);
|
||||
WorkerScriptStartStopEventEmitter.emit();
|
||||
|
||||
// Start the script's execution
|
||||
let scriptExecution: Promise<void> | null = null; // Script's resulting promise
|
||||
if (workerScript.name.endsWith(".js")) {
|
||||
scriptExecution = startNetscript2Script(workerScript);
|
||||
} else {
|
||||
scriptExecution = startNetscript1Script(workerScript);
|
||||
if (!(scriptExecution instanceof Promise)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Start the script's execution using the correct function for file type
|
||||
(workerScript.name.endsWith(".js") ? startNetscript2Script : startNetscript1Script)(workerScript)
|
||||
// Once the code finishes (either resolved or rejected, doesnt matter), set its
|
||||
// running status to false
|
||||
scriptExecution
|
||||
.then(function () {
|
||||
// On natural death, the earnings are transfered to the parent if it still exists.
|
||||
if (parent && !parent.env.stopFlag) {
|
||||
@ -370,13 +347,15 @@ function createAndAddWorkerScript(runningScriptObj: RunningScript, server: BaseS
|
||||
workerScript.log("", () => "Script finished running");
|
||||
})
|
||||
.catch(function (e) {
|
||||
errorDialog(e, `RUNTIME ERROR\n${workerScript.name}@${workerScript.hostname} (PID - ${workerScript.pid})\n\n`);
|
||||
let logText = "Script crashed due to an error.";
|
||||
if (e instanceof ScriptDeath) logText = "Script killed.";
|
||||
workerScript.log("", () => logText);
|
||||
let initialText = `ERROR\n${workerScript.name}@${workerScript.hostname} (PID - ${workerScript.pid})\n\n`;
|
||||
if (e instanceof SyntaxError) e = `SYNTAX ${initialText}${e.message} (sorry we can't be more helpful)`;
|
||||
else if (e instanceof Error) {
|
||||
e = `RUNTIME ${initialText}${e.message}${e.stack ? `\nstack:\n${e.stack.toString()}` : ""}`;
|
||||
}
|
||||
errorDialog(e, typeof e === "string" && e.includes(initialText) ? "" : initialText);
|
||||
workerScript.log("", () => (e instanceof ScriptDeath ? "Script killed." : "Script crashed due to an error."));
|
||||
killWorkerScript(workerScript);
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { Player } from "../Player";
|
||||
import { isScriptFilename } from "../Script/isScriptFilename";
|
||||
import { GetServer } from "../Server/AllServers";
|
||||
import { isValidFilePath } from "../Terminal/DirectoryHelpers";
|
||||
@ -29,7 +28,7 @@ export const RFARequestHandler: Record<string, (message: RFAMessage) => void | R
|
||||
const server = GetServer(fileData.server);
|
||||
if (!server) return error("Server hostname invalid", msg);
|
||||
|
||||
if (isScriptFilename(fileData.filename)) server.writeToScriptFile(Player, fileData.filename, fileData.content);
|
||||
if (isScriptFilename(fileData.filename)) server.writeToScriptFile(fileData.filename, fileData.content);
|
||||
// Assume it's a text file
|
||||
else server.writeToTextFile(fileData.filename, fileData.content);
|
||||
|
||||
|
@ -13,7 +13,6 @@ import { RamCalculationErrorCode } from "./RamCalculationErrorCodes";
|
||||
import { RamCosts, RamCostConstants } from "../Netscript/RamCostGenerator";
|
||||
import { Script } from "./Script";
|
||||
import { areImportsEquals } from "../Terminal/DirectoryHelpers";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { Node } from "../NetscriptJSEvaluator";
|
||||
|
||||
export interface RamUsageEntry {
|
||||
@ -40,11 +39,8 @@ const memCheckGlobalKey = ".__GLOBAL__";
|
||||
* Parses code into an AST and walks through it recursively to calculate
|
||||
* RAM usage. Also accounts for imported modules.
|
||||
* @param {Script[]} otherScripts - All other scripts on the server. Used to account for imported scripts
|
||||
* @param {string} codeCopy - The code being parsed
|
||||
* @param {WorkerScript} workerScript - Object containing RAM costs of Netscript functions. Also used to
|
||||
* keep track of what functions have/havent been accounted for
|
||||
*/
|
||||
function parseOnlyRamCalculate(player: IPlayer, otherScripts: Script[], code: string): RamCalculation {
|
||||
* @param {string} code - The code being parsed */
|
||||
function parseOnlyRamCalculate(otherScripts: Script[], code: string): RamCalculation {
|
||||
try {
|
||||
/**
|
||||
* Maps dependent identifiers to their dependencies.
|
||||
@ -157,11 +153,11 @@ function parseOnlyRamCalculate(player: IPlayer, otherScripts: Script[], code: st
|
||||
// Check if this identifier is a function in the workerScript environment.
|
||||
// If it is, then we need to get its RAM cost.
|
||||
try {
|
||||
function applyFuncRam(cost: number | ((p: IPlayer) => number)): number {
|
||||
function applyFuncRam(cost: number | (() => number)): number {
|
||||
if (typeof cost === "number") {
|
||||
return cost;
|
||||
} else if (typeof cost === "function") {
|
||||
return cost(player);
|
||||
return cost();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
@ -178,7 +174,7 @@ function parseOnlyRamCalculate(player: IPlayer, otherScripts: Script[], code: st
|
||||
prefix: string,
|
||||
obj: object,
|
||||
ref: string,
|
||||
): { func: (p: IPlayer) => number | number; refDetail: string } | undefined => {
|
||||
): { func: () => number | number; refDetail: string } | undefined => {
|
||||
if (!obj) return;
|
||||
const elem = Object.entries(obj).find(([key]) => key === ref);
|
||||
if (elem !== undefined && (typeof elem[1] === "function" || typeof elem[1] === "number")) {
|
||||
@ -381,9 +377,9 @@ function parseOnlyCalculateDeps(code: string, currentModule: string): ParseDepsR
|
||||
* @param {Script[]} otherScripts - All other scripts on the server.
|
||||
* Used to account for imported scripts
|
||||
*/
|
||||
export function calculateRamUsage(player: IPlayer, codeCopy: string, otherScripts: Script[]): RamCalculation {
|
||||
export function calculateRamUsage(codeCopy: string, otherScripts: Script[]): RamCalculation {
|
||||
try {
|
||||
return parseOnlyRamCalculate(player, otherScripts, codeCopy);
|
||||
return parseOnlyRamCalculate(otherScripts, codeCopy);
|
||||
} catch (e) {
|
||||
console.error(`Failed to parse script for RAM calculations:`);
|
||||
console.error(e);
|
||||
|
@ -9,7 +9,6 @@ import { ScriptUrl } from "./ScriptUrl";
|
||||
|
||||
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
||||
import { roundToTwo } from "../utils/helpers/roundToTwo";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { ScriptModule } from "./ScriptModule";
|
||||
|
||||
let globalModuleSequenceNumber = 0;
|
||||
@ -52,13 +51,13 @@ export class Script {
|
||||
// hostname of server that this script is on.
|
||||
server = "";
|
||||
|
||||
constructor(player: IPlayer | null = null, fn = "", code = "", server = "", otherScripts: Script[] = []) {
|
||||
constructor(fn = "", code = "", server = "", otherScripts: Script[] = []) {
|
||||
this.filename = fn;
|
||||
this.code = code;
|
||||
this.server = server; // hostname of server this script is on
|
||||
this.moduleSequenceNumber = ++globalModuleSequenceNumber;
|
||||
if (this.code !== "" && player !== null) {
|
||||
this.updateRamUsage(player, otherScripts);
|
||||
if (this.code !== "") {
|
||||
this.updateRamUsage(otherScripts);
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,13 +93,13 @@ export class Script {
|
||||
* @param {string} code - The new contents of the script
|
||||
* @param {Script[]} otherScripts - Other scripts on the server. Used to process imports
|
||||
*/
|
||||
saveScript(player: IPlayer, filename: string, code: string, hostname: string, otherScripts: Script[]): void {
|
||||
saveScript(filename: string, code: string, hostname: string, otherScripts: Script[]): void {
|
||||
// Update code and filename
|
||||
this.code = Script.formatCode(code);
|
||||
|
||||
this.filename = filename;
|
||||
this.server = hostname;
|
||||
this.updateRamUsage(player, otherScripts);
|
||||
this.updateRamUsage(otherScripts);
|
||||
this.markUpdated();
|
||||
for (const dependent of this.dependents) {
|
||||
const [dependentScript] = otherScripts.filter(
|
||||
@ -114,8 +113,8 @@ export class Script {
|
||||
* Calculates and updates the script's RAM usage based on its code
|
||||
* @param {Script[]} otherScripts - Other scripts on the server. Used to process imports
|
||||
*/
|
||||
updateRamUsage(player: IPlayer, otherScripts: Script[]): void {
|
||||
const res = calculateRamUsage(player, this.code, otherScripts);
|
||||
updateRamUsage(otherScripts: Script[]): void {
|
||||
const res = calculateRamUsage(this.code, otherScripts);
|
||||
if (res.cost > 0) {
|
||||
this.ramUsage = roundToTwo(res.cost);
|
||||
this.ramUsageEntries = res.entries;
|
||||
|
@ -252,7 +252,7 @@ export function Root(props: IProps): React.ReactElement {
|
||||
return;
|
||||
}
|
||||
const codeCopy = newCode + "";
|
||||
const ramUsage = calculateRamUsage(props.player, codeCopy, props.player.getCurrentServer().scripts);
|
||||
const ramUsage = calculateRamUsage(codeCopy, props.player.getCurrentServer().scripts);
|
||||
if (ramUsage.cost > 0) {
|
||||
const entries = ramUsage.entries?.sort((a, b) => b.cost - a.cost) ?? [];
|
||||
const entriesDisp = [];
|
||||
@ -466,7 +466,6 @@ export function Root(props: IProps): React.ReactElement {
|
||||
for (let i = 0; i < server.scripts.length; i++) {
|
||||
if (scriptToSave.fileName == server.scripts[i].filename) {
|
||||
server.scripts[i].saveScript(
|
||||
props.player,
|
||||
scriptToSave.fileName,
|
||||
scriptToSave.code,
|
||||
props.player.currentServer,
|
||||
@ -480,13 +479,7 @@ export function Root(props: IProps): React.ReactElement {
|
||||
|
||||
//If the current script does NOT exist, create a new one
|
||||
const script = new Script();
|
||||
script.saveScript(
|
||||
props.player,
|
||||
scriptToSave.fileName,
|
||||
scriptToSave.code,
|
||||
props.player.currentServer,
|
||||
server.scripts,
|
||||
);
|
||||
script.saveScript(scriptToSave.fileName, scriptToSave.code, props.player.currentServer, server.scripts);
|
||||
server.scripts.push(script);
|
||||
} else if (scriptToSave.isTxt) {
|
||||
for (let i = 0; i < server.textFiles.length; ++i) {
|
||||
@ -555,7 +548,6 @@ export function Root(props: IProps): React.ReactElement {
|
||||
for (let i = 0; i < server.scripts.length; i++) {
|
||||
if (currentScript.fileName == server.scripts[i].filename) {
|
||||
server.scripts[i].saveScript(
|
||||
props.player,
|
||||
currentScript.fileName,
|
||||
currentScript.code,
|
||||
props.player.currentServer,
|
||||
@ -569,13 +561,7 @@ export function Root(props: IProps): React.ReactElement {
|
||||
|
||||
//If the current script does NOT exist, create a new one
|
||||
const script = new Script();
|
||||
script.saveScript(
|
||||
props.player,
|
||||
currentScript.fileName,
|
||||
currentScript.code,
|
||||
props.player.currentServer,
|
||||
server.scripts,
|
||||
);
|
||||
script.saveScript(currentScript.fileName, currentScript.code, props.player.currentServer, server.scripts);
|
||||
server.scripts.push(script);
|
||||
} else if (currentScript.isTxt) {
|
||||
for (let i = 0; i < server.textFiles.length; ++i) {
|
||||
|
@ -12,7 +12,6 @@ import { isScriptFilename } from "../Script/isScriptFilename";
|
||||
|
||||
import { createRandomIp } from "../utils/IPAddress";
|
||||
import { compareArrays } from "../utils/helpers/compareArrays";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { ScriptArg } from "../Netscript/ScriptArg";
|
||||
|
||||
interface IConstructorParams {
|
||||
@ -245,7 +244,7 @@ export class BaseServer {
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
updateRamUsed(ram: number, player: IPlayer): void {
|
||||
updateRamUsed(ram: number): void {
|
||||
this.ramUsed = ram;
|
||||
}
|
||||
|
||||
@ -266,7 +265,7 @@ export class BaseServer {
|
||||
* Write to a script file
|
||||
* Overwrites existing files. Creates new files if the script does not eixst
|
||||
*/
|
||||
writeToScriptFile(player: IPlayer, fn: string, code: string): writeResult {
|
||||
writeToScriptFile(fn: string, code: string): writeResult {
|
||||
const ret = { success: false, overwritten: false };
|
||||
if (!isValidFilePath(fn) || !isScriptFilename(fn)) {
|
||||
return ret;
|
||||
@ -277,7 +276,7 @@ export class BaseServer {
|
||||
if (fn === this.scripts[i].filename) {
|
||||
const script = this.scripts[i];
|
||||
script.code = code;
|
||||
script.updateRamUsage(player, this.scripts);
|
||||
script.updateRamUsage(this.scripts);
|
||||
script.markUpdated();
|
||||
ret.overwritten = true;
|
||||
ret.success = true;
|
||||
@ -286,7 +285,7 @@ export class BaseServer {
|
||||
}
|
||||
|
||||
// Otherwise, create a new script
|
||||
const newScript = new Script(player, fn, code, this.hostname, this.scripts);
|
||||
const newScript = new Script(fn, code, this.hostname, this.scripts);
|
||||
this.scripts.push(newScript);
|
||||
ret.success = true;
|
||||
return ret;
|
||||
|
@ -326,7 +326,7 @@ export function prestigeHomeComputer(player: IPlayer, homeComp: Server): void {
|
||||
|
||||
//Update RAM usage on all scripts
|
||||
homeComp.scripts.forEach(function (script) {
|
||||
script.updateRamUsage(player, homeComp.scripts);
|
||||
script.updateRamUsage(homeComp.scripts);
|
||||
});
|
||||
|
||||
homeComp.messages.length = 0; //Remove .lit and .msg files
|
||||
|
@ -89,7 +89,7 @@ export function cp(
|
||||
return;
|
||||
}
|
||||
|
||||
const sRes = server.writeToScriptFile(player, dst, sourceScript.code);
|
||||
const sRes = server.writeToScriptFile(dst, sourceScript.code);
|
||||
if (!sRes.success) {
|
||||
terminal.error(`cp failed`);
|
||||
return;
|
||||
|
@ -94,7 +94,7 @@ export function scp(
|
||||
return;
|
||||
}
|
||||
|
||||
const sRes = destServer.writeToScriptFile(player, scriptname, sourceScript.code);
|
||||
const sRes = destServer.writeToScriptFile(scriptname, sourceScript.code);
|
||||
if (!sRes.success) {
|
||||
terminal.error(`scp failed`);
|
||||
return;
|
||||
|
@ -28,7 +28,7 @@ export function wget(
|
||||
function (data: unknown) {
|
||||
let res;
|
||||
if (isScriptFilename(target)) {
|
||||
res = server.writeToScriptFile(player, target, String(data));
|
||||
res = server.writeToScriptFile(target, String(data));
|
||||
} else {
|
||||
res = server.writeToTextFile(target, String(data));
|
||||
}
|
||||
|
@ -286,7 +286,7 @@ export async function determineAllPossibilitiesForTabCompletion(
|
||||
});
|
||||
if (!script) return; // Doesn't exist.
|
||||
//Will return the already compiled module if recompilation not needed.
|
||||
const loadedModule = await compile(p, script, currServ.scripts);
|
||||
const loadedModule = await compile(script, currServ.scripts);
|
||||
if (!loadedModule || !loadedModule.autocomplete) return; // Doesn't have an autocomplete function.
|
||||
|
||||
const runArgs = { "--tail": Boolean, "-t": Number };
|
||||
|
@ -1,8 +1,8 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { IEngine } from "../IEngine";
|
||||
import { ITerminal } from "../Terminal/ITerminal";
|
||||
import { Player } from "../Player";
|
||||
import { Engine } from "../engine";
|
||||
import { Terminal } from "../Terminal";
|
||||
import { installAugmentations } from "../Augmentation/AugmentationHelpers";
|
||||
import { saveObject } from "../SaveObject";
|
||||
import { onExport } from "../ExportBonus";
|
||||
@ -84,12 +84,6 @@ import { V2Modal } from "../utils/V2Modal";
|
||||
|
||||
const htmlLocation = location;
|
||||
|
||||
interface IProps {
|
||||
terminal: ITerminal;
|
||||
player: IPlayer;
|
||||
engine: IEngine;
|
||||
}
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
root: {
|
||||
@ -148,20 +142,20 @@ export let Router: IRouter = {
|
||||
toImportSave: uninitialized,
|
||||
};
|
||||
|
||||
function determineStartPage(player: IPlayer): Page {
|
||||
function determineStartPage(): Page {
|
||||
if (RecoveryMode) return Page.Recovery;
|
||||
if (player.currentWork !== null) return Page.Work;
|
||||
if (Player.currentWork !== null) return Page.Work;
|
||||
return Page.Terminal;
|
||||
}
|
||||
|
||||
export function GameRoot({ player, engine, terminal }: IProps): React.ReactElement {
|
||||
export function GameRoot(): React.ReactElement {
|
||||
const classes = useStyles();
|
||||
const [{ files, vim }, setEditorOptions] = useState({ files: {}, vim: false });
|
||||
const [page, setPage] = useState(determineStartPage(player));
|
||||
const [page, setPage] = useState(determineStartPage());
|
||||
const setRerender = useState(0)[1];
|
||||
const [augPage, setAugPage] = useState<boolean>(false);
|
||||
const [faction, setFaction] = useState<Faction>(
|
||||
isFactionWork(player.currentWork) ? Factions[player.currentWork.factionName] : (undefined as unknown as Faction),
|
||||
isFactionWork(Player.currentWork) ? Factions[Player.currentWork.factionName] : (undefined as unknown as Faction),
|
||||
);
|
||||
if (faction === undefined && page === Page.Faction)
|
||||
throw new Error("Trying to go to a page without the proper setup");
|
||||
@ -243,7 +237,7 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
|
||||
setPage(Page.City);
|
||||
},
|
||||
toTravel: () => {
|
||||
player.gotoLocation(LocationName.TravelAgency);
|
||||
Player.gotoLocation(LocationName.TravelAgency);
|
||||
setPage(Page.Travel);
|
||||
},
|
||||
toBitVerse: (flume: boolean, quick: boolean) => {
|
||||
@ -347,7 +341,7 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
|
||||
break;
|
||||
}
|
||||
case Page.Terminal: {
|
||||
mainPage = <TerminalRoot terminal={terminal} router={Router} player={player} />;
|
||||
mainPage = <TerminalRoot terminal={Terminal} router={Router} player={Player} />;
|
||||
break;
|
||||
}
|
||||
case Page.Sleeves: {
|
||||
@ -366,8 +360,8 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
|
||||
mainPage = (
|
||||
<ScriptEditorRoot
|
||||
files={files}
|
||||
hostname={player.getCurrentServer().hostname}
|
||||
player={player}
|
||||
hostname={Player.getCurrentServer().hostname}
|
||||
player={Player}
|
||||
router={Router}
|
||||
vim={vim}
|
||||
/>
|
||||
@ -379,7 +373,7 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
|
||||
break;
|
||||
}
|
||||
case Page.Hacknet: {
|
||||
mainPage = <HacknetRoot player={player} />;
|
||||
mainPage = <HacknetRoot player={Player} />;
|
||||
break;
|
||||
}
|
||||
case Page.CreateProgram: {
|
||||
@ -387,7 +381,7 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
|
||||
break;
|
||||
}
|
||||
case Page.Factions: {
|
||||
mainPage = <FactionsRoot player={player} router={Router} />;
|
||||
mainPage = <FactionsRoot player={Player} router={Router} />;
|
||||
break;
|
||||
}
|
||||
case Page.Faction: {
|
||||
@ -395,7 +389,7 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
|
||||
break;
|
||||
}
|
||||
case Page.Milestones: {
|
||||
mainPage = <MilestonesRoot player={player} />;
|
||||
mainPage = <MilestonesRoot player={Player} />;
|
||||
break;
|
||||
}
|
||||
case Page.Tutorial: {
|
||||
@ -411,7 +405,7 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
|
||||
break;
|
||||
}
|
||||
case Page.DevMenu: {
|
||||
mainPage = <DevMenuRoot player={player} engine={engine} router={Router} />;
|
||||
mainPage = <DevMenuRoot player={Player} engine={Engine} router={Router} />;
|
||||
break;
|
||||
}
|
||||
case Page.Gang: {
|
||||
@ -431,11 +425,11 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
|
||||
break;
|
||||
}
|
||||
case Page.Travel: {
|
||||
mainPage = <TravelAgencyRoot p={player} router={Router} />;
|
||||
mainPage = <TravelAgencyRoot p={Player} router={Router} />;
|
||||
break;
|
||||
}
|
||||
case Page.StockMarket: {
|
||||
mainPage = <StockMarketRoot p={player} stockMarket={StockMarket} />;
|
||||
mainPage = <StockMarketRoot p={Player} stockMarket={StockMarket} />;
|
||||
break;
|
||||
}
|
||||
case Page.City: {
|
||||
@ -450,12 +444,12 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
|
||||
case Page.Options: {
|
||||
mainPage = (
|
||||
<GameOptionsRoot
|
||||
player={player}
|
||||
player={Player}
|
||||
router={Router}
|
||||
save={() => saveObject.saveGame()}
|
||||
export={() => {
|
||||
// Apply the export bonus before saving the game
|
||||
onExport(player);
|
||||
onExport(Player);
|
||||
saveObject.exportGame();
|
||||
}}
|
||||
forceKill={killAllScripts}
|
||||
@ -469,7 +463,7 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
|
||||
<AugmentationsRoot
|
||||
exportGameFn={() => {
|
||||
// Apply the export bonus before saving the game
|
||||
onExport(player);
|
||||
onExport(Player);
|
||||
saveObject.exportGame();
|
||||
}}
|
||||
installAugmentationsFn={() => {
|
||||
@ -496,7 +490,7 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
|
||||
}
|
||||
|
||||
return (
|
||||
<Context.Player.Provider value={player}>
|
||||
<Context.Player.Provider value={Player}>
|
||||
<Context.Router.Provider value={Router}>
|
||||
<ErrorBoundary key={errorBoundaryKey} router={Router} softReset={softReset}>
|
||||
<BypassWrapper content={bypassGame ? mainPage : null}>
|
||||
@ -511,7 +505,7 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
|
||||
{withSidebar ? (
|
||||
<Box display="flex" flexDirection="row" width="100%">
|
||||
<SidebarRoot
|
||||
player={player}
|
||||
player={Player}
|
||||
router={Router}
|
||||
page={page}
|
||||
opened={sidebarOpened}
|
||||
|
@ -3,9 +3,7 @@ import CircularProgress from "@mui/material/CircularProgress";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Grid from "@mui/material/Grid";
|
||||
|
||||
import { Terminal } from "../Terminal";
|
||||
import { load } from "../db";
|
||||
import { Player } from "../Player";
|
||||
import { Engine } from "../engine";
|
||||
import { GameRoot } from "./GameRoot";
|
||||
|
||||
@ -57,7 +55,7 @@ export function LoadingScreen(): React.ReactElement {
|
||||
}, []);
|
||||
|
||||
return loaded ? (
|
||||
<GameRoot terminal={Terminal} engine={Engine} player={Player} />
|
||||
<GameRoot />
|
||||
) : (
|
||||
<Grid container direction="column" justifyContent="center" alignItems="center" style={{ minHeight: "100vh" }}>
|
||||
<Grid item>
|
||||
|
@ -14,8 +14,10 @@ export function errorDialog(e: unknown, initialText = "") {
|
||||
else if (e instanceof ScriptDeath) {
|
||||
if (!e.errorMessage) return; //No need for a dialog for an empty ScriptDeath
|
||||
errorText = e.errorMessage;
|
||||
} else if (e instanceof SyntaxError) errorText = e.message + " (sorry we can't be more helpful)";
|
||||
else if (e instanceof Error) errorText = e.message + (e.stack ? `\nstack:\n${e.stack.toString()}` : "");
|
||||
if (!e.errorMessage.includes(`${e.name}@${e.hostname}`)) {
|
||||
initialText += `${e.name}@${e.hostname} (PID - ${e.pid})\n\n`;
|
||||
}
|
||||
} else if (e instanceof Error) errorText = "Original error message:\n" + e.message;
|
||||
else {
|
||||
errorText = "An unknown error was thrown, see console.";
|
||||
console.error(e);
|
||||
|
@ -126,7 +126,7 @@ export function v1APIBreak(): void {
|
||||
for (const script of server.scripts) {
|
||||
if (!hasChanges(script.code)) continue;
|
||||
const prefix = script.filename.includes("/") ? "/BACKUP_" : "BACKUP_";
|
||||
backups.push(new Script(Player, prefix + script.filename, script.code, script.server));
|
||||
backups.push(new Script(prefix + script.filename, script.code, script.server));
|
||||
script.code = convert(script.code);
|
||||
}
|
||||
server.scripts = server.scripts.concat(backups);
|
||||
|
Loading…
Reference in New Issue
Block a user