diff --git a/src/Achievements/Achievements.ts b/src/Achievements/Achievements.ts index 99db7d960..79edf12a9 100644 --- a/src/Achievements/Achievements.ts +++ b/src/Achievements/Achievements.ts @@ -1,4 +1,4 @@ -import { PlayerObject } from "src/PersonObjects/Player/PlayerObject"; +import { PlayerObject } from "../PersonObjects/Player/PlayerObject"; import { AugmentationNames } from "../Augmentation/data/AugmentationNames"; import { SkillNames } from "../Bladeburner/data/SkillNames"; import { Skills } from "../Bladeburner/Skills"; @@ -341,7 +341,7 @@ export const achievements: Record = { SCRIPT_32GB: { ...achievementData["SCRIPT_32GB"], Icon: "bigcost", - Condition: () => Player.getHomeComputer().scripts.some((s) => s.ramUsage >= 32), + Condition: () => Player.getHomeComputer().scripts.some((s) => (s.ramUsage as number) >= 32), }, FIRST_HACKNET_NODE: { ...achievementData["FIRST_HACKNET_NODE"], diff --git a/src/Netscript/NetscriptHelpers.ts b/src/Netscript/NetscriptHelpers.ts index 9f94fb3ed..d40b2cc08 100644 --- a/src/Netscript/NetscriptHelpers.ts +++ b/src/Netscript/NetscriptHelpers.ts @@ -33,6 +33,7 @@ import { BaseServer } from "../Server/BaseServer"; import { dialogBoxCreate } from "../ui/React/DialogBox"; import { checkEnum } from "../utils/helpers/enum"; import { RamCostConstants } from "./RamCostGenerator"; +import { PositiveInteger } from "../types"; export const helpers = { string, @@ -158,12 +159,12 @@ function number(ctx: NetscriptContext, argName: string, v: unknown): number { } /** Convert provided value v for argument argName to a positive integer, throwing if it looks like something else. */ -function positiveInteger(ctx: NetscriptContext, argName: string, v: unknown): number { +function positiveInteger(ctx: NetscriptContext, argName: string, v: unknown): PositiveInteger { const n = number(ctx, argName, v); if (n < 1 || !Number.isInteger(n)) { throw makeRuntimeErrorMsg(ctx, `${argName} should be a positive integer, was ${n}`, "TYPE"); } - return n; + return n as PositiveInteger; } /** Returns args back if it is a ScriptArg[]. Throws an error if it is not. */ @@ -348,11 +349,6 @@ function updateDynamicRam(ctx: NetscriptContext, ramCost: number): void { if (ws.dynamicLoadedFns[fnName]) return; ws.dynamicLoadedFns[fnName] = true; - let threads = ws.scriptRef.threads; - if (typeof threads !== "number") { - console.warn(`WorkerScript detected NaN for thread count for ${ws.name} on ${ws.hostname}`); - threads = 1; - } ws.dynamicRamUsage = Math.min(ws.dynamicRamUsage + ramCost, RamCostConstants.Max); if (ws.dynamicRamUsage > 1.01 * ws.ramUsage) { log(ctx, () => "Insufficient static ram available."); @@ -362,7 +358,7 @@ function updateDynamicRam(ctx: NetscriptContext, ramCost: number): void { `Dynamic RAM usage calculated to be greater than initial RAM usage. This is probably because you somehow circumvented the static RAM calculation. - Threads: ${threads} + Threads: ${ws.scriptRef.threads} Dynamic RAM Usage: ${formatRam(ws.dynamicRamUsage)} per thread Static RAM Usage: ${formatRam(ws.ramUsage)} per thread diff --git a/src/Netscript/WorkerScript.ts b/src/Netscript/WorkerScript.ts index 5687e0ced..0b2047fb2 100644 --- a/src/Netscript/WorkerScript.ts +++ b/src/Netscript/WorkerScript.ts @@ -72,7 +72,7 @@ export class WorkerScript { pid: number; /** Script's Static RAM usage. Equivalent to underlying script's RAM usage */ - ramUsage = 0; + ramUsage = RamCostConstants.Base; /** Reference to underlying RunningScript object */ scriptRef: RunningScript; diff --git a/src/NetscriptFunctions.ts b/src/NetscriptFunctions.ts index 68dafd904..0794f74ee 100644 --- a/src/NetscriptFunctions.ts +++ b/src/NetscriptFunctions.ts @@ -36,7 +36,7 @@ import { } from "./Server/ServerPurchases"; import { Server } from "./Server/Server"; import { influenceStockThroughServerGrow } from "./StockMarket/PlayerInfluencing"; -import { isValidFilePath, removeLeadingSlash } from "./Terminal/DirectoryHelpers"; +import { areFilesEqual, isValidFilePath, removeLeadingSlash } from "./Terminal/DirectoryHelpers"; import { TextFile, getTextFile, createTextFile } from "./TextFile"; import { runScriptFromScript } from "./NetscriptWorker"; import { killWorkerScript } from "./Netscript/killWorkerScript"; @@ -890,7 +890,8 @@ export const ns: InternalAPI = { continue; } destScript.code = sourceScript.code; - destScript.ramUsage = sourceScript.ramUsage; + // Set ramUsage to null in order to force a recalculation prior to next run. + destScript.ramUsage = null; destScript.markUpdated(); helpers.log(ctx, () => `WARNING: File '${file}' overwritten on '${destServer?.hostname}'`); continue; @@ -899,11 +900,11 @@ export const ns: InternalAPI = { // Create new script if it does not already exist const newScript = new Script(file); newScript.code = sourceScript.code; - newScript.ramUsage = sourceScript.ramUsage; + // Set ramUsage to null in order to force a recalculation prior to next run. + newScript.ramUsage = null; newScript.server = destServer.hostname; destServer.scripts.push(newScript); helpers.log(ctx, () => `File '${file}' copied over to '${destServer?.hostname}'.`); - newScript.updateRamUsage(destServer.scripts); } return noFailures; @@ -1430,12 +1431,14 @@ export const ns: InternalAPI = { let script = ctx.workerScript.getScriptOnServer(fn, server); if (script == null) { // Create a new script - script = new Script(fn, String(data), server.hostname, server.scripts); + script = new Script(fn, String(data), server.hostname); server.scripts.push(script); - return script.updateRamUsage(server.scripts); + return; } mode === "w" ? (script.code = String(data)) : (script.code += data); - return script.updateRamUsage(server.scripts); + // Set ram to null so a recalc is performed the next time ram usage is needed + script.ramUsage = null; + return; } else { // Write to text file if (!fn.endsWith(".txt")) throw helpers.makeRuntimeErrorMsg(ctx, `Invalid filename: ${fn}`); @@ -1566,12 +1569,14 @@ export const ns: InternalAPI = { const scriptname = helpers.string(ctx, "scriptname", _scriptname); const hostname = helpers.string(ctx, "hostname", _hostname); const server = helpers.getServer(ctx, hostname); - for (let i = 0; i < server.scripts.length; ++i) { - if (server.scripts[i].filename == scriptname) { - return server.scripts[i].ramUsage; - } + const script = server.scripts.find((serverScript) => areFilesEqual(serverScript.filename, scriptname)); + if (!script) return 0; + const ramUsage = script.getRamUsage(server.scripts); + if (!ramUsage) { + helpers.log(ctx, () => `Could not calculate ram usage for ${scriptname} on ${hostname}.`); + return 0; } - return 0; + return ramUsage; }, getRunningScript: (ctx) => diff --git a/src/NetscriptFunctions/Extra.ts b/src/NetscriptFunctions/Extra.ts index c5f8b0866..fe44f03f3 100644 --- a/src/NetscriptFunctions/Extra.ts +++ b/src/NetscriptFunctions/Extra.ts @@ -6,6 +6,7 @@ import { Apr1Events as devMenu } from "../ui/Apr1"; import { InternalAPI } from "../Netscript/APIWrapper"; import { helpers } from "../Netscript/NetscriptHelpers"; import { Terminal } from "../Terminal"; +import { RamCostConstants } from "../Netscript/RamCostGenerator"; export type INetscriptExtra = { heart: { @@ -36,7 +37,7 @@ export function NetscriptExtra(): InternalAPI { real_document.completely_unused_field = undefined; // set one to true and check that it affected the other. real_document.completely_unused_field = true; - if (d.completely_unused_field && ctx.workerScript.ramUsage === 1.6) { + if (d.completely_unused_field && ctx.workerScript.ramUsage === RamCostConstants.Base) { Player.giveExploit(Exploit.Bypass); } d.completely_unused_field = undefined; diff --git a/src/NetscriptFunctions/Singularity.ts b/src/NetscriptFunctions/Singularity.ts index 1601a017f..c7fd32815 100644 --- a/src/NetscriptFunctions/Singularity.ts +++ b/src/NetscriptFunctions/Singularity.ts @@ -49,6 +49,7 @@ import { canGetBonus, onExport } from "../ExportBonus"; import { saveObject } from "../SaveObject"; import { calculateCrimeWorkStats } from "../Work/Formulas"; import { findEnumMember } from "../utils/helpers/enum"; +import { areFilesEqual } from "../Terminal/DirectoryHelpers"; export function NetscriptSingularity(): InternalAPI { const getAugmentation = function (ctx: NetscriptContext, name: string): Augmentation { @@ -77,18 +78,17 @@ export function NetscriptSingularity(): InternalAPI { //Run a script after reset if (!cbScript) return; const home = Player.getHomeComputer(); - for (const script of home.scripts) { - if (script.filename === cbScript) { - const ramUsage = script.ramUsage; - const ramAvailable = home.maxRam - home.ramUsed; - if (ramUsage > ramAvailable + 0.001) { - return; // Not enough RAM - } - const runningScriptObj = new RunningScript(script, []); // No args - runningScriptObj.threads = 1; // Only 1 thread - startWorkerScript(runningScriptObj, home); - } + const script = home.scripts.find((serverScript) => areFilesEqual(serverScript.filename, cbScript)); + if (!script) return; + const ramUsage = script.getRamUsage(home.scripts); + if (!ramUsage) { + return Terminal.error(`Attempted to launch ${cbScript} after reset but could not calculate ram usage.`); } + const ramAvailable = home.maxRam - home.ramUsed; + if (ramUsage > ramAvailable + 0.001) return; + // Start script with no args and 1 thread (default). + const runningScriptObj = new RunningScript(script, ramUsage, []); + startWorkerScript(runningScriptObj, home); }; const singularityAPI: InternalAPI = { diff --git a/src/NetscriptJSEvaluator.ts b/src/NetscriptJSEvaluator.ts index dc43556d3..83e5e6a84 100644 --- a/src/NetscriptJSEvaluator.ts +++ b/src/NetscriptJSEvaluator.ts @@ -28,7 +28,6 @@ export async function compile(script: Script, scripts: Script[]): Promise