2019-05-05 06:03:40 +02:00
|
|
|
/**
|
|
|
|
* The worker agent for running a script instance. Each running script instance
|
|
|
|
* has its own underlying WorkerScript object.
|
|
|
|
*
|
|
|
|
* Note that these objects are not saved and re-loaded when the game is refreshed.
|
|
|
|
* Instead, whenever the game is opened, WorkerScripts are re-created from
|
|
|
|
* RunningScript objects
|
|
|
|
*/
|
|
|
|
import { Environment } from "./Environment";
|
|
|
|
import { RamCostConstants } from "./RamCostGenerator";
|
|
|
|
|
|
|
|
import { RunningScript } from "../Script/RunningScript";
|
|
|
|
import { Script } from "../Script/Script";
|
2021-10-07 22:56:01 +02:00
|
|
|
import { GetServer } from "../Server/AllServers";
|
2019-05-05 06:03:40 +02:00
|
|
|
import { BaseServer } from "../Server/BaseServer";
|
2022-05-25 21:08:48 +02:00
|
|
|
import { NS } from "../ScriptEditor/NetscriptDefinitions";
|
2022-07-15 07:51:30 +02:00
|
|
|
import { ScriptDeath } from "./ScriptDeath";
|
|
|
|
import { ScriptArg } from "./ScriptArg";
|
2019-05-05 06:03:40 +02:00
|
|
|
|
|
|
|
export class WorkerScript {
|
2022-10-04 12:40:10 +02:00
|
|
|
/** Script's arguments */
|
2022-07-15 07:51:30 +02:00
|
|
|
args: ScriptArg[];
|
2021-09-05 01:09:30 +02:00
|
|
|
|
2022-10-04 12:40:10 +02:00
|
|
|
/** Copy of the script's code */
|
2021-09-05 01:09:30 +02:00
|
|
|
code = "";
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Holds the timeoutID (numeric value) for whenever this script is blocked by a
|
|
|
|
* timed Netscript function. i.e. Holds the return value of setTimeout()
|
|
|
|
*/
|
|
|
|
delay: number | null = null;
|
|
|
|
|
2022-10-04 12:40:10 +02:00
|
|
|
/** Holds the Promise reject() function while the script is "blocked" by an async op */
|
2022-07-15 07:51:30 +02:00
|
|
|
delayReject?: (reason?: ScriptDeath) => void;
|
2021-09-05 01:09:30 +02:00
|
|
|
|
2022-10-04 12:40:10 +02:00
|
|
|
/** Stores names of all functions that have logging disabled */
|
2022-10-03 18:12:16 +02:00
|
|
|
disableLogs: Record<string, boolean> = {};
|
2021-09-05 01:09:30 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Used for dynamic RAM calculation. Stores names of all functions that have
|
|
|
|
* already been checked by this script.
|
|
|
|
* TODO: Could probably just combine this with loadedFns?
|
|
|
|
*/
|
2022-10-03 18:12:16 +02:00
|
|
|
dynamicLoadedFns: Record<string, boolean> = {};
|
2021-09-05 01:09:30 +02:00
|
|
|
|
2022-10-04 12:40:10 +02:00
|
|
|
/** Tracks dynamic RAM usage */
|
2021-09-05 01:09:30 +02:00
|
|
|
dynamicRamUsage: number = RamCostConstants.ScriptBaseRamCost;
|
|
|
|
|
2022-10-04 12:40:10 +02:00
|
|
|
/** Netscript Environment for this script */
|
2021-09-05 01:09:30 +02:00
|
|
|
env: Environment;
|
|
|
|
|
2022-10-04 12:40:10 +02:00
|
|
|
/** Status message in case of script error. */
|
2021-09-05 01:09:30 +02:00
|
|
|
errorMessage = "";
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Used for static RAM calculation. Stores names of all functions that have
|
|
|
|
* already been checked by this script
|
|
|
|
*/
|
2022-10-03 18:12:16 +02:00
|
|
|
loadedFns: Record<string, boolean> = {};
|
2021-09-05 01:09:30 +02:00
|
|
|
|
2022-10-04 12:40:10 +02:00
|
|
|
/** Filename of script */
|
2021-09-05 01:09:30 +02:00
|
|
|
name: string;
|
|
|
|
|
2022-10-04 12:40:10 +02:00
|
|
|
/** Script's output/return value. Currently not used or implemented */
|
2021-09-05 01:09:30 +02:00
|
|
|
output = "";
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Process ID. Must be an integer. Used for efficient script
|
|
|
|
* killing and removal.
|
|
|
|
*/
|
|
|
|
pid: number;
|
|
|
|
|
2022-10-04 12:40:10 +02:00
|
|
|
/** Script's Static RAM usage. Equivalent to underlying script's RAM usage */
|
2021-09-05 01:09:30 +02:00
|
|
|
ramUsage = 0;
|
|
|
|
|
2022-10-04 12:40:10 +02:00
|
|
|
/** Reference to underlying RunningScript object */
|
2021-09-05 01:09:30 +02:00
|
|
|
scriptRef: RunningScript;
|
|
|
|
|
2022-10-04 12:40:10 +02:00
|
|
|
/** hostname on which this script is running */
|
2021-10-07 23:55:49 +02:00
|
|
|
hostname: string;
|
2021-09-05 01:09:30 +02:00
|
|
|
|
2022-10-04 12:40:10 +02:00
|
|
|
/** Function called when the script ends. */
|
2022-07-15 07:51:30 +02:00
|
|
|
atExit?: () => void;
|
2021-10-15 02:13:26 +02:00
|
|
|
|
2022-05-25 21:08:48 +02:00
|
|
|
constructor(runningScriptObj: RunningScript, pid: number, nsFuncsGenerator?: (ws: WorkerScript) => NS) {
|
2021-09-05 01:09:30 +02:00
|
|
|
this.name = runningScriptObj.filename;
|
2021-10-07 23:55:49 +02:00
|
|
|
this.hostname = runningScriptObj.server;
|
2021-09-05 01:09:30 +02:00
|
|
|
|
|
|
|
const sanitizedPid = Math.round(pid);
|
|
|
|
if (typeof sanitizedPid !== "number" || isNaN(sanitizedPid)) {
|
|
|
|
throw new Error(`Invalid PID when constructing WorkerScript: ${pid}`);
|
2019-05-05 06:03:40 +02:00
|
|
|
}
|
2021-09-05 01:09:30 +02:00
|
|
|
this.pid = sanitizedPid;
|
|
|
|
runningScriptObj.pid = sanitizedPid;
|
|
|
|
|
|
|
|
// Get the underlying script's code
|
2021-10-07 23:55:49 +02:00
|
|
|
const server = GetServer(this.hostname);
|
2021-09-05 01:09:30 +02:00
|
|
|
if (server == null) {
|
2021-10-07 23:55:49 +02:00
|
|
|
throw new Error(`WorkerScript constructed with invalid server ip: ${this.hostname}`);
|
2019-05-05 06:03:40 +02:00
|
|
|
}
|
2021-09-05 01:09:30 +02:00
|
|
|
let found = false;
|
|
|
|
for (let i = 0; i < server.scripts.length; ++i) {
|
|
|
|
if (server.scripts[i].filename === this.name) {
|
|
|
|
found = true;
|
|
|
|
this.code = server.scripts[i].code;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!found) {
|
2021-09-09 05:47:34 +02:00
|
|
|
throw new Error(`WorkerScript constructed with invalid script filename: ${this.name}`);
|
2019-05-05 06:03:40 +02:00
|
|
|
}
|
2021-10-15 19:12:18 +02:00
|
|
|
this.scriptRef = runningScriptObj;
|
|
|
|
this.args = runningScriptObj.args.slice();
|
2022-07-20 07:13:06 +02:00
|
|
|
this.env = new Environment();
|
2021-09-05 01:09:30 +02:00
|
|
|
if (typeof nsFuncsGenerator === "function") {
|
|
|
|
this.env.vars = nsFuncsGenerator(this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-04 12:40:10 +02:00
|
|
|
/** Returns the Server on which this script is running */
|
2021-09-05 01:09:30 +02:00
|
|
|
getServer(): BaseServer {
|
2021-10-07 23:55:49 +02:00
|
|
|
const server = GetServer(this.hostname);
|
2021-09-09 05:47:34 +02:00
|
|
|
if (server == null) throw new Error(`Script ${this.name} pid ${this.pid} is running on non-existent server?`);
|
2021-09-05 01:09:30 +02:00
|
|
|
return server;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the Script object for the underlying script.
|
|
|
|
* Returns null if it cannot be found (which would be a bug)
|
|
|
|
*/
|
|
|
|
getScript(): Script | null {
|
|
|
|
const server = this.getServer();
|
|
|
|
for (let i = 0; i < server.scripts.length; ++i) {
|
|
|
|
if (server.scripts[i].filename === this.name) {
|
|
|
|
return server.scripts[i];
|
|
|
|
}
|
2019-05-05 06:03:40 +02:00
|
|
|
}
|
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
console.error(
|
|
|
|
"Failed to find underlying Script object in WorkerScript.getScript(). This probably means somethings wrong",
|
|
|
|
);
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the script with the specified filename on the specified server,
|
|
|
|
* or null if it cannot be found
|
|
|
|
*/
|
|
|
|
getScriptOnServer(fn: string, server: BaseServer): Script | null {
|
|
|
|
if (server == null) {
|
|
|
|
server = this.getServer();
|
2019-05-05 06:03:40 +02:00
|
|
|
}
|
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
for (let i = 0; i < server.scripts.length; ++i) {
|
|
|
|
if (server.scripts[i].filename === fn) {
|
|
|
|
return server.scripts[i];
|
|
|
|
}
|
2021-03-11 09:02:05 +01:00
|
|
|
}
|
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
shouldLog(fn: string): boolean {
|
|
|
|
return this.disableLogs[fn] == null;
|
|
|
|
}
|
|
|
|
|
2021-11-27 00:30:58 +01:00
|
|
|
log(func: string, txt: () => string): void {
|
2021-09-05 01:09:30 +02:00
|
|
|
if (this.shouldLog(func)) {
|
|
|
|
if (func && txt) {
|
2021-11-27 00:30:58 +01:00
|
|
|
this.scriptRef.log(`${func}: ${txt()}`);
|
2021-09-05 01:09:30 +02:00
|
|
|
} else if (func) {
|
|
|
|
this.scriptRef.log(func);
|
|
|
|
} else {
|
2021-11-27 00:30:58 +01:00
|
|
|
this.scriptRef.log(txt());
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2019-05-05 06:03:40 +02:00
|
|
|
}
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
print(txt: string): void {
|
|
|
|
this.scriptRef.log(txt);
|
|
|
|
}
|
2019-05-05 06:03:40 +02:00
|
|
|
}
|