diff --git a/daemon.js b/daemon.js index 89b46388..9e62e965 100644 --- a/daemon.js +++ b/daemon.js @@ -1090,7 +1090,7 @@ export async function arbitraryExecution(ns, tool, threads, args, preferredServe // Sort servers by total ram, and try to fill these before utilizing another server. sortServerList("totalram"); - var preferredServerOrder = serverListByMaxRam.filter(server => server.hasRoot() && server.totalRam() > 1.6); + var preferredServerOrder = serverListByMaxRam.filter(server => server.hasRoot() && server.totalRam() > 1.6 || server.name == "home"); if (useSmallestServerPossible) // Fill up small servers before utilizing larger ones (can be laggy) preferredServerOrder.reverse(); // IDEA: "home" is more effective at grow() and weaken() than other nodes (has multiple cores) (TODO: By how much?) @@ -1186,7 +1186,7 @@ export async function arbitraryExecution(ns, tool, threads, args, preferredServe } // The run failed if there were threads left to schedule after we exhausted our pool of servers if (remainingThreads > 0 && threads < Number.MAX_SAFE_INTEGER) - log(`ERROR: Ran out of RAM to run ${tool.name} ${splitThreads ? '' : `on ${targetServer.name} `}- ${threads - remainingThreads} of ${threads} threads were spawned.`, false, 'error'); + log(`ERROR: Ran out of RAM to run ${tool.name} ${splitThreads ? '' : `on ${targetServer?.name} `}- ${threads - remainingThreads} of ${threads} threads were spawned.`, false, 'error'); if (splitThreads && !tool.isThreadSpreadingAllowed) return false; return remainingThreads == 0; diff --git a/helpers.js b/helpers.js index 8f54cd66..397b4fa7 100644 --- a/helpers.js +++ b/helpers.js @@ -150,8 +150,9 @@ export async function getNsDataThroughFile_Custom(ns, fnRun, fnIsAlive, command, // Prepare a command that will write out a new file containing the results of the command // unless it already exists with the same contents (saves time/ram to check first) // If an error occurs, it will write an empty file to avoid old results being misread. - const commandToFile = `let result = ""; try { result = JSON.stringify(${command}); } catch { } - if (ns.read("${fName}") != result) await ns.write("${fName}", result, 'w')`; + const commandToFile = `let result="";try{result=JSON.stringify( + ${command} + );}catch{} const f="${fName}"; if(ns.read(f)!=result) await ns.write(f,result,'w')`; // Run the command with auto-retries if it fails const pid = await runCommand_Custom(ns, fnRun, commandToFile, fNameCommand, false, maxRetries, retryDelayMs); // Wait for the process to complete @@ -285,13 +286,13 @@ export function scanAllServers(ns) { /** @param {NS} ns * Get a dictionary of active source files, taking into account the current active bitnode as well. **/ -export async function getActiveSourceFiles(ns) { - return await getActiveSourceFiles_Custom(ns, getNsDataThroughFile); +export async function getActiveSourceFiles(ns, includeLevelsFromCurrentBitnode = true) { + return await getActiveSourceFiles_Custom(ns, getNsDataThroughFile, includeLevelsFromCurrentBitnode); } /** @param {NS} ns * getActiveSourceFiles Helper that allows the user to pass in their chosen implementation of getNsDataThroughFile to minimize RAM usage **/ -export async function getActiveSourceFiles_Custom(ns, fnGetNsDataThroughFile) { +export async function getActiveSourceFiles_Custom(ns, fnGetNsDataThroughFile, includeLevelsFromCurrentBitnode = true) { checkNsInstance(ns, '"getActiveSourceFiles"'); let tempFile = '/Temp/owned-source-files.txt'; // Find out what source files the user has unlocked @@ -302,7 +303,10 @@ export async function getActiveSourceFiles_Custom(ns, fnGetNsDataThroughFile) { dictSourceFiles = dictSourceFiles ? JSON.parse(dictSourceFiles) : {}; } // If the user is currently in a given bitnode, they will have its features unlocked - dictSourceFiles[(await fnGetNsDataThroughFile(ns, 'ns.getPlayer()', '/Temp/player-info.txt')).bitNodeN] = 3; + if (includeLevelsFromCurrentBitnode) { + const bitNodeN = (await fnGetNsDataThroughFile(ns, 'ns.getPlayer()', '/Temp/player-info.txt')).bitNodeN; + dictSourceFiles[bitNodeN] = Math.max(3, dictSourceFiles[bitNodeN] || 0); + } return dictSourceFiles; } diff --git a/stats.js b/stats.js index 578e3421..d0d99380 100644 --- a/stats.js +++ b/stats.js @@ -16,9 +16,10 @@ export async function main(ns) { const doc = eval('document'); const hook0 = doc.getElementById('overview-extra-hook-0'); const hook1 = doc.getElementById('overview-extra-hook-1'); + const dictSourceFiles = await getActiveSourceFiles(ns, false); // Find out what source files the user has unlocked + let playerInfo = await getNsDataThroughFile(ns, 'ns.getPlayer()', '/Temp/player-info.txt'); + const bitNode = playerInfo.bitNodeN; let stkSymbols = null; - let dictSourceFiles = await getActiveSourceFiles(ns); // Find out what source files the user has unlocked - let playerInfo = (await getNsDataThroughFile(ns, 'ns.getPlayer()', '/Temp/player-info.txt')); if (!options['hide-stocks'] && playerInfo.hasTixApiAccess) // Auto-disabled if we do not have the TSK API stkSymbols = await getNsDataThroughFile(ns, `ns.stock.getSymbols()`, '/Temp/stock-symbols.txt'); // Main stats update loop @@ -27,15 +28,19 @@ export async function main(ns) { const headers = [] const values = []; - if (9 in dictSourceFiles) { // Section not relevant if you don't have access to hacknet servers + // Show what bitNode we're currently playing + headers.push("BitNode"); + values.push(`${bitNode}.${1 + (dictSourceFiles[bitNode] || 0)}`); + + if (9 in dictSourceFiles || 9 == bitNode) { // Section not relevant if you don't have access to hacknet servers const hashes = await getNsDataThroughFile(ns, '[ns.hacknet.numHashes(), ns.hacknet.hashCapacity()]', '/Temp/hash-stats.txt') if (hashes[1] > 0) { headers.push("Hashes"); values.push(`${formatNumberShort(hashes[0], 3, 1)}/${formatNumberShort(hashes[1], 3, 1)}`); } - // Detect and notify the HUD if we are liquidating - if (ns.ps("home").some(p => p.filename.includes('spend-hacknet-hashes') && (p.args.includes("--liquidate") || p.args.includes("-l")))) { - headers.splice(1, 0, " "); + // Detect and notify the HUD if we are liquidating hashes (selling them as quickly as possible) + if (ns.isRunning('spend-hacknet-hashes.js', 'home', '--liquidate') || ns.isRunning('spend-hacknet-hashes.js', 'home', '-l')) { + headers.push(" "); values.push("Liquidating"); } } @@ -57,7 +62,7 @@ export async function main(ns) { values.push(formatNumberShort(ns.getScriptExpGain(), 3, 2) + '/sec'); let gangInfo = false; - if (2 in dictSourceFiles) { // Gang income is only relevant once gangs are unlocked + if (2 in dictSourceFiles || 2 == bitNode) { // Gang income is only relevant once gangs are unlocked gangInfo = await getNsDataThroughFile(ns, 'ns.gang.inGang() ? ns.gang.getGangInformation() : false', '/Temp/gang-stats.txt'); if (gangInfo !== false) { // Add Gang Income @@ -76,16 +81,16 @@ export async function main(ns) { values.push(formatNumberShort(karma, 3, 2)); } - if(options['show-peoplekilled']) { - playerInfo = (await getNsDataThroughFile(ns, 'ns.getPlayer()', '/Temp/player-info.txt')); + if (options['show-peoplekilled']) { + playerInfo = await getNsDataThroughFile(ns, 'ns.getPlayer()', '/Temp/player-info.txt'); const numPeopleKilled = playerInfo.numPeopleKilled; if (numPeopleKilled > 0) { - headers.push("Ppl Killed"); + headers.push("Kills"); values.push(formatNumberShort(numPeopleKilled, 6, 0)); } } - const sharePower = ns.getSharePower(); + const sharePower = await getNsDataThroughFile(ns, 'ns.getSharePower()', '/Temp/share-power.txt'); if (sharePower > 1) { headers.push("Share Pwr"); values.push(formatNumberShort(sharePower, 3, 2)); @@ -98,4 +103,4 @@ export async function main(ns) { } await ns.sleep(1000); } -} +} \ No newline at end of file