This commit is contained in:
hydroflame 2021-04-21 08:20:26 -04:00 committed by GitHub
parent 135df8703c
commit b2aafea656
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 263 additions and 73 deletions

File diff suppressed because one or more lines are too long

@ -1,2 +1,2 @@
!function(n){function t(t){for(var e,i,f=t[0],c=t[1],l=t[2],p=0,s=[];p<f.length;p++)i=f[p],u[i]&&s.push(u[i][0]),u[i]=0;for(e in c)Object.prototype.hasOwnProperty.call(c,e)&&(n[e]=c[e]);for(a&&a(t);s.length;)s.shift()();return r.push.apply(r,l||[]),o()}function o(){for(var n,t=0;t<r.length;t++){for(var o=r[t],e=!0,f=1;f<o.length;f++){var c=o[f];0!==u[c]&&(e=!1)}e&&(r.splice(t--,1),n=i(i.s=o[0]))}return n}var e={},u={1:0},r=[];function i(t){if(e[t])return e[t].exports;var o=e[t]={i:t,l:!1,exports:{}};return n[t].call(o.exports,o,o.exports,i),o.l=!0,o.exports}i.m=n,i.c=e,i.d=function(n,t,o){i.o(n,t)||Object.defineProperty(n,t,{enumerable:!0,get:o})},i.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},i.t=function(n,t){if(1&t&&(n=i(n)),8&t)return n;if(4&t&&"object"==typeof n&&n&&n.__esModule)return n;var o=Object.create(null);if(i.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:n}),2&t&&"string"!=typeof n)for(var e in n)i.d(o,e,function(t){return n[t]}.bind(null,e));return o},i.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return i.d(t,"a",t),t},i.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},i.p="";var f=window.webpackJsonp=window.webpackJsonp||[],c=f.push.bind(f);f.push=t,f=f.slice();for(var l=0;l<f.length;l++)t(f[l]);var a=c;r.push([401,0]),o()}({344:function(n,t,o){},346:function(n,t,o){},348:function(n,t,o){},350:function(n,t,o){},352:function(n,t,o){},354:function(n,t,o){},356:function(n,t,o){},358:function(n,t,o){},360:function(n,t,o){},362:function(n,t,o){},364:function(n,t,o){},366:function(n,t,o){},368:function(n,t,o){},370:function(n,t,o){},372:function(n,t,o){},374:function(n,t,o){},376:function(n,t,o){},378:function(n,t,o){},380:function(n,t,o){},382:function(n,t,o){},384:function(n,t,o){},386:function(n,t,o){},388:function(n,t,o){},390:function(n,t,o){},392:function(n,t,o){},394:function(n,t,o){},396:function(n,t,o){},398:function(n,t,o){},401:function(n,t,o){"use strict";o.r(t);o(400),o(398),o(396),o(394),o(392),o(390),o(388),o(386),o(384),o(382),o(380),o(378),o(376),o(374),o(372),o(370),o(368),o(366),o(364),o(362),o(360),o(358),o(356),o(354),o(352),o(350),o(348),o(346),o(344)}}); !function(n){function t(t){for(var e,i,f=t[0],c=t[1],l=t[2],p=0,s=[];p<f.length;p++)i=f[p],u[i]&&s.push(u[i][0]),u[i]=0;for(e in c)Object.prototype.hasOwnProperty.call(c,e)&&(n[e]=c[e]);for(a&&a(t);s.length;)s.shift()();return r.push.apply(r,l||[]),o()}function o(){for(var n,t=0;t<r.length;t++){for(var o=r[t],e=!0,f=1;f<o.length;f++){var c=o[f];0!==u[c]&&(e=!1)}e&&(r.splice(t--,1),n=i(i.s=o[0]))}return n}var e={},u={1:0},r=[];function i(t){if(e[t])return e[t].exports;var o=e[t]={i:t,l:!1,exports:{}};return n[t].call(o.exports,o,o.exports,i),o.l=!0,o.exports}i.m=n,i.c=e,i.d=function(n,t,o){i.o(n,t)||Object.defineProperty(n,t,{enumerable:!0,get:o})},i.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},i.t=function(n,t){if(1&t&&(n=i(n)),8&t)return n;if(4&t&&"object"==typeof n&&n&&n.__esModule)return n;var o=Object.create(null);if(i.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:n}),2&t&&"string"!=typeof n)for(var e in n)i.d(o,e,function(t){return n[t]}.bind(null,e));return o},i.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return i.d(t,"a",t),t},i.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},i.p="";var f=window.webpackJsonp=window.webpackJsonp||[],c=f.push.bind(f);f.push=t,f=f.slice();for(var l=0;l<f.length;l++)t(f[l]);var a=c;r.push([402,0]),o()}({345:function(n,t,o){},347:function(n,t,o){},349:function(n,t,o){},351:function(n,t,o){},353:function(n,t,o){},355:function(n,t,o){},357:function(n,t,o){},359:function(n,t,o){},361:function(n,t,o){},363:function(n,t,o){},365:function(n,t,o){},367:function(n,t,o){},369:function(n,t,o){},371:function(n,t,o){},373:function(n,t,o){},375:function(n,t,o){},377:function(n,t,o){},379:function(n,t,o){},381:function(n,t,o){},383:function(n,t,o){},385:function(n,t,o){},387:function(n,t,o){},389:function(n,t,o){},391:function(n,t,o){},393:function(n,t,o){},395:function(n,t,o){},397:function(n,t,o){},399:function(n,t,o){},402:function(n,t,o){"use strict";o.r(t);o(401),o(399),o(397),o(395),o(393),o(391),o(389),o(387),o(385),o(383),o(381),o(379),o(377),o(375),o(373),o(371),o(369),o(367),o(365),o(363),o(361),o(359),o(357),o(355),o(353),o(351),o(349),o(347),o(345)}});
//# sourceMappingURL=engineStyle.bundle.js.map //# sourceMappingURL=engineStyle.bundle.js.map

28
dist/vendor.bundle.js vendored

File diff suppressed because one or more lines are too long

@ -3,6 +3,29 @@
Changelog Changelog
========= =========
v0.51.5 - 2021-04-20 Flags! (hydroflame)
----------------------------------------
Netscript
* 'flags' is a new function that helps script handle flags.
This is subject to change if it doesn't meet the need of the players.
* 'ps' now returns the pid.
* 'tail' now works with pid as first argument.
* 'tail' hostname defaults to current server. (like the documentation says)
* 'isRunning' hostname defaults to current server.
* 'isRunning' now works with pid as first argument.
Gang
* Nerfed ascension mechanic once again :(
Misc.
* Souce-File typo fix
* Fix 'while you were away' screen.
* Bladeburner team size can no longer be set to negative amounts.
v0.51.4 - 2021-04-19 Manual hacking is fun (hydroflame) v0.51.4 - 2021-04-19 Manual hacking is fun (hydroflame)
------------------------------------------------------- -------------------------------------------------------

@ -66,7 +66,7 @@ documentation_title = '{0} Documentation'.format(project)
# The short X.Y version. # The short X.Y version.
version = '0.51' version = '0.51'
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
release = '0.51.4' release = '0.51.5'
# The language for content autogenerated by Sphinx. Refer to documentation # The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages. # for a list of supported languages.

@ -0,0 +1,40 @@
flags() Netscript Function
============================
.. js:function:: flags(data)
:RAM cost: 0 GB
:param data array of pairs of strings: Flags definition.
:returns: Object containing all the flags that were parsed or default.
The flag definition is an array of pairs of values, the first value is the
name of the flag, the 2nd value is the default value for that flag.
The return object is a map containing flag names to the value. It also
contains the special field '_' which contains all arguments that were not flags.
Example:
.. code-block:: javascript
/* example.script
var data = flags([
['delay', 0], // a default number means this flag is a number
['server', 'foodnstuff'], // a default string means this flag is a string
['exclude', []], // a default array means this flag is a default array of string
['help', false], // a default boolean means this flag is a boolean
]);
tprint(data);
*/
[home ~/]> run example.script
{"_":[],"delay":0,"server":"foodnstuff"}
[home ~/]> run example.script --delay 3000
{"_":[],"server":"foodnstuff","delay":3000}
[home ~/]> run example.script --delay 3000 --server harakiri-sushi
{"_":[],"delay":3000,"server":"harakiri-sushi"}
[home ~/]> run example.script --delay 3000 --server harakiri-sushi hello world
{"_":["hello","world"],"delay":3000,"server":"harakiri-sushi"}
[home ~/]> run example.script --delay 3000 --server harakiri-sushi hello world --exclude a --exclude b
{"_":["hello","world"],"delay":3000,"server":"harakiri-sushi","exclude":["a","b"]}
[home ~/]> run example.script --help
{"_":[],"delay":0,"server":"foodnstuff","exclude":[],"help":true}

@ -1,11 +1,11 @@
isRunning() Netscript Function isRunning() Netscript Function
============================== ==============================
.. js:function:: isRunning(filename, hostname, [args...]) .. js:function:: isRunning(filename[, hostname=current hostname[, args...]])
:RAM cost: 0.1 GB :RAM cost: 0.1 GB
:param string filename: Filename of script to check. case-sensitive. :param string filename: Filename of script to check. case-sensitive.
:param string hostname: Hostname of target server. :param string hostname: Hostname of target server. Defaults to current server
:param args...: Arguments to specify/identify which scripts to search for :param args...: Arguments to specify/identify which scripts to search for
:returns: ``true`` if that script with those args is running on that server. :returns: ``true`` if that script with those args is running on that server.
@ -38,3 +38,19 @@ isRunning() Netscript Function
.. code-block:: javascript .. code-block:: javascript
isRunning("foo.script", "joesguns", 1, 5, "test"); isRunning("foo.script", "joesguns", 1, 5, "test");
.. js:function:: isRunning(scriptPid[, hostname=current hostname])
:RAM cost: 0.1 GB
:param number scriptPid: PID of the script to check.
Same as the above version but with pid.
Example:
.. code-block:: javascript
isRunning(39);
isRunning(39, getHostname());

@ -1,7 +1,7 @@
tail() Netscript Function tail() Netscript Function
================================== ==================================
.. js:function:: tail([fn[, hostname=current hostname[, [...args]]]) .. js:function:: tail([fn[, hostname=current hostname[, ...args]])
:RAM cost: 0 GB :RAM cost: 0 GB
:param string fn: Optional. Filename of script to get logs from. :param string fn: Optional. Filename of script to get logs from.
@ -29,3 +29,20 @@ tail() Netscript Function
// Open logs from foo.script on the foodnstuff server that was run with the arguments [1, "test"] // Open logs from foo.script on the foodnstuff server that was run with the arguments [1, "test"]
tail("foo.script", "foodnstuff", 1, "test"); tail("foo.script", "foodnstuff", 1, "test");
.. js:function:: tail(scriptPid[, hostname=current hostname])
:RAM cost: 0 GB
:param number scriptPid: PID of the script to tail.
Opens a script's logs by pid
Example:
.. code-block:: javascript
// Open logs from process with id 42
tail(42);
// Open logs from process with id 42 on the foodnstuff server
tail(42, "foodnstuff");

@ -88,3 +88,4 @@ This includes information such as function signatures, what they do, and their r
prompt() <basicfunctions/prompt> prompt() <basicfunctions/prompt>
wget() <basicfunctions/wget> wget() <basicfunctions/wget>
getFavorToDonate() <basicfunctions/getFavorToDonate> getFavorToDonate() <basicfunctions/getFavorToDonate>
flags() <basicfunctions/flags>

15
package-lock.json generated

@ -1,11 +1,11 @@
{ {
"name": "bitburner", "name": "bitburner",
"version": "0.49.2", "version": "0.51.4",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"version": "0.49.2", "version": "0.51.4",
"hasInstallScript": true, "hasInstallScript": true,
"license": "SEE LICENSE IN license.txt", "license": "SEE LICENSE IN license.txt",
"dependencies": { "dependencies": {
@ -16,6 +16,7 @@
"acorn-walk": "^6.2.0", "acorn-walk": "^6.2.0",
"ajv": "^5.1.5", "ajv": "^5.1.5",
"ajv-keywords": "^2.0.0", "ajv-keywords": "^2.0.0",
"arg": "^5.0.0",
"async": "^2.6.1", "async": "^2.6.1",
"autosize": "^4.0.2", "autosize": "^4.0.2",
"brace": "^0.11.1", "brace": "^0.11.1",
@ -1020,6 +1021,11 @@
"readable-stream": "^2.0.6" "readable-stream": "^2.0.6"
} }
}, },
"node_modules/arg": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/arg/-/arg-5.0.0.tgz",
"integrity": "sha512-4P8Zm2H+BRS+c/xX1LrHw0qKpEhdlZjLCgWy+d78T9vqa2Z2SiD2wMrYuWIAFy5IZUD7nnNXroRttz+0RzlrzQ=="
},
"node_modules/argparse": { "node_modules/argparse": {
"version": "1.0.10", "version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
@ -18412,6 +18418,11 @@
"readable-stream": "^2.0.6" "readable-stream": "^2.0.6"
} }
}, },
"arg": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/arg/-/arg-5.0.0.tgz",
"integrity": "sha512-4P8Zm2H+BRS+c/xX1LrHw0qKpEhdlZjLCgWy+d78T9vqa2Z2SiD2wMrYuWIAFy5IZUD7nnNXroRttz+0RzlrzQ=="
},
"argparse": { "argparse": {
"version": "1.0.10", "version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",

@ -13,6 +13,7 @@
"acorn-walk": "^6.2.0", "acorn-walk": "^6.2.0",
"ajv": "^5.1.5", "ajv": "^5.1.5",
"ajv-keywords": "^2.0.0", "ajv-keywords": "^2.0.0",
"arg": "^5.0.0",
"async": "^2.6.1", "async": "^2.6.1",
"autosize": "^4.0.2", "autosize": "^4.0.2",
"brace": "^0.11.1", "brace": "^0.11.1",
@ -121,5 +122,5 @@
"watch": "webpack --watch --mode production", "watch": "webpack --watch --mode production",
"watch:dev": "webpack --watch --mode development" "watch:dev": "webpack --watch --mode development"
}, },
"version": "0.51.4" "version": "0.51.5"
} }

@ -234,7 +234,7 @@ BitNodes["BitNode11"] = new BitNode(11, "The Big Crash", "Okay. Sell it all.",
"Level 3: 56%"); "Level 3: 56%");
BitNodes["BitNode12"] = new BitNode(12, "The Recursion", "Repeat.", BitNodes["BitNode12"] = new BitNode(12, "The Recursion", "Repeat.",
"To iterate is human, to recurse divine.<br><br>" + "To iterate is human, to recurse divine.<br><br>" +
"Every time this BitNode is destroyed, it becomes slightly harder. Destroying this BitNode will give you Souce-File 12, or " + "Every time this BitNode is destroyed, it becomes slightly harder. Destroying this BitNode will give you Source-File 12, or " +
"if you already have this Source-File it will upgrade its level. There is no maximum level for Source-File 12. Each level " + "if you already have this Source-File it will upgrade its level. There is no maximum level for Source-File 12. Each level " +
"of Source-File 12 will increase all of your multipliers by 1%. This effect is multiplicative with itself. " + "of Source-File 12 will increase all of your multipliers by 1%. This effect is multiplicative with itself. " +
"In other words, level N of this Source-File will result in a multiplier of 1.01^N (or 0.99^N for multipliers that decrease)"); "In other words, level N of this Source-File will result in a multiplier of 1.01^N (or 0.99^N for multipliers that decrease)");

@ -2075,8 +2075,8 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
innerText:"Confirm", class:"a-link-button", innerText:"Confirm", class:"a-link-button",
clickListener:() => { clickListener:() => {
var num = Math.round(parseFloat(input.value)); var num = Math.round(parseFloat(input.value));
if (isNaN(num)) { if (isNaN(num) || num < 0) {
dialogBoxCreate("Invalid value entered for number of Team Members (must be numeric)") dialogBoxCreate("Invalid value entered for number of Team Members (must be numeric, positive)")
} else { } else {
action.teamCount = num; action.teamCount = num;
this.updateOperationsUIElement(el, action); this.updateOperationsUIElement(el, action);
@ -2227,8 +2227,8 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) {
innerText:"Confirm", class:"a-link-button", innerText:"Confirm", class:"a-link-button",
clickListener:() => { clickListener:() => {
var num = Math.round(parseFloat(input.value)); var num = Math.round(parseFloat(input.value));
if (isNaN(num)) { if (isNaN(num) || num < 0) {
dialogBoxCreate("Invalid value entered for number of Team Members (must be numeric)") dialogBoxCreate("Invalid value entered for number of Team Members (must be numeric, positive)")
} else { } else {
action.teamCount = num; action.teamCount = num;
this.updateBlackOpsUIElement(el, action); this.updateBlackOpsUIElement(el, action);
@ -3211,7 +3211,7 @@ Bladeburner.prototype.setTeamSizeNetscriptFn = function(type, name, size, worker
} }
const sanitizedSize = Math.round(size); const sanitizedSize = Math.round(size);
if (isNaN(sanitizedSize)) { if (isNaN(sanitizedSize) || sanitizedSize < 0) {
workerScript.log("bladeburner.setTeamSize", `Invalid size: ${size}`); workerScript.log("bladeburner.setTeamSize", `Invalid size: ${size}`);
return -1; return -1;
} }

@ -6,7 +6,7 @@
import { IMap } from "./types"; import { IMap } from "./types";
export let CONSTANTS: IMap<any> = { export let CONSTANTS: IMap<any> = {
Version: "0.51.4", Version: "0.51.5",
/** Max level for any skill, assuming no multipliers. Determined by max numerical value in javascript for experience /** Max level for any skill, assuming no multipliers. Determined by max numerical value in javascript for experience
* and the skill level formula in Player.js. Note that all this means it that when experience hits MAX_INT, then * and the skill level formula in Player.js. Note that all this means it that when experience hits MAX_INT, then
@ -228,34 +228,24 @@ export let CONSTANTS: IMap<any> = {
LatestUpdate: LatestUpdate:
` `
v0.51.4 - 2021-04-19 Manual hacking is fun (hydroflame) v0.51.5 - 2021-04-20 Flags! (hydroflame)
------- -------
Manual hacking
* These bonus require an install or a soft reset to take effect.
* Manual hacking gyms and university gives you a 10% discount.
* Manual hacking a corporation server decreases the penalty for leaving work
early.
BladeBurner
* nerfed int exp gained.
Documentation
* purchaseServer specifies what happens on failure.
* Fixed typo in recommended bitnode page.
* Removed misleading ram requirements for hacking factions.
Netscript Netscript
* growthAnalyze handles Infinity correctly. * 'flags' is a new function that helps script handle flags.
This is subject to change if it doesn't meet the need of the players.
* 'ps' now returns the pid.
* 'tail' now works with pid as first argument.
* 'tail' hostname defaults to current server. (like the documentation says)
* 'isRunning' hostname defaults to current server.
* 'isRunning' now works with pid as first argument.
Gang
* Nerfed ascension mechanic once again :(
Misc. Misc.
* Faction Augmentation will list how much reputation is required even after * Souce-File typo fix
that goal has been reached. * Fix 'while you were away' screen.
* Removed dollar sign in travel agency confirmation dialog box. * Bladeburner team size can no longer be set to negative amounts.
* Fixed typo in alpha-omega.lit
* the 'Game saved!' text no longer blocks the save game/options button.
* The text editor now remembers the location of your cursor and restores it.
* skills are recalculated instantly.
* Fix typo in Operation Zero description.
` `
} }

@ -809,7 +809,7 @@ GangMember.prototype.ascend = function() {
GangMember.prototype.getAscensionEfficiency = function() { GangMember.prototype.getAscensionEfficiency = function() {
function formula(mult) { function formula(mult) {
return 1/(1+Math.log(mult)/Math.log(10)); return 1/(1+Math.log(mult)/Math.log(20));
} }
return { return {
hack: formula(this.hack_asc_mult), hack: formula(this.hack_asc_mult),

@ -1,5 +1,6 @@
const sprintf = require("sprintf-js").sprintf; const sprintf = require("sprintf-js").sprintf;
const vsprintf = require("sprintf-js").vsprintf; const vsprintf = require("sprintf-js").vsprintf;
import * as libarg from 'arg';
import { getRamCost } from "./Netscript/RamCostGenerator"; import { getRamCost } from "./Netscript/RamCostGenerator";
import { WorkerScriptStartStopEventEmitter } from "./Netscript/WorkerScriptStartStopEventEmitter"; import { WorkerScriptStartStopEventEmitter } from "./Netscript/WorkerScriptStartStopEventEmitter";
@ -88,7 +89,10 @@ import { inMission } from "./Missions";
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";
import { findRunningScript } from "./Script/ScriptHelpers"; import {
findRunningScript,
findRunningScriptByPid,
} from "./Script/ScriptHelpers";
import { isScriptFilename } from "./Script/ScriptHelpersTS"; import { isScriptFilename } from "./Script/ScriptHelpersTS";
import { _getScriptUrls } from "./NetscriptJSEvaluator"; import { _getScriptUrls } from "./NetscriptJSEvaluator";
import { import {
@ -162,6 +166,7 @@ import {
netscriptDelay, netscriptDelay,
resolveNetscriptRequestedThreads, resolveNetscriptRequestedThreads,
} from "./NetscriptEvaluator"; } from "./NetscriptEvaluator";
import { Interpreter } from "./JSInterpreter";
import { NetscriptPort } from "./NetscriptPort"; import { NetscriptPort } from "./NetscriptPort";
import { SleeveTaskType } from "./PersonObjects/Sleeve/SleeveTaskTypesEnum"; import { SleeveTaskType } from "./PersonObjects/Sleeve/SleeveTaskTypesEnum";
import { findSleevePurchasableAugs } from "./PersonObjects/Sleeve/SleeveHelpers"; import { findSleevePurchasableAugs } from "./PersonObjects/Sleeve/SleeveHelpers";
@ -256,6 +261,38 @@ const possibleLogs = {
setTerritoryWarfare: true, setTerritoryWarfare: true,
} }
const defaultInterpreter = new Interpreter('', function(){});
// the acorn interpreter has a bug where it doesn't convert arrays correctly.
// so we have to more or less copy it here.
function toNative(pseudoObj) {
if(!pseudoObj.hasOwnProperty('properties') ||
!pseudoObj.hasOwnProperty('getter') ||
!pseudoObj.hasOwnProperty('setter') ||
!pseudoObj.hasOwnProperty('proto')) {
return pseudoObj; // it wasn't a pseudo object anyway.
}
let nativeObj;
if (pseudoObj.hasOwnProperty('class') && pseudoObj.class === 'Array') {
nativeObj = [];
const length = defaultInterpreter.getProperty(pseudoObj, 'length');
for (let i = 0; i < length; i++) {
if (defaultInterpreter.hasProperty(pseudoObj, i)) {
nativeObj[i] =
toNative(defaultInterpreter.getProperty(pseudoObj, i));
}
}
} else { // Object.
nativeObj = {};
for (var key in pseudoObj.properties) {
const val = pseudoObj.properties[key];
nativeObj[key] = toNative(val);
}
}
return nativeObj;
}
function NetscriptFunctions(workerScript) { function NetscriptFunctions(workerScript) {
const updateDynamicRam = function(fnName, ramCost) { const updateDynamicRam = function(fnName, ramCost) {
if (workerScript.dynamicLoadedFns[fnName]) { return; } if (workerScript.dynamicLoadedFns[fnName]) { return; }
@ -305,7 +342,6 @@ function NetscriptFunctions(workerScript) {
* is not specified. * is not specified.
*/ */
const getRunningScript = function(fn, ip, callingFnName, scriptArgs) { const getRunningScript = function(fn, ip, callingFnName, scriptArgs) {
// Sanitize arguments
if (typeof callingFnName !== "string" || callingFnName === "") { if (typeof callingFnName !== "string" || callingFnName === "") {
callingFnName = "getRunningScript"; callingFnName = "getRunningScript";
} }
@ -330,6 +366,15 @@ function NetscriptFunctions(workerScript) {
return workerScript.scriptRef; return workerScript.scriptRef;
} }
const getRunningScriptByPid = function(pid, ip, callingFnName) {
if (typeof callingFnName !== "string" || callingFnName === "") {
callingFnName = "getRunningScriptgetRunningScriptByPid";
}
const server = safeGetServer(ip, callingFnName);
return findRunningScriptByPid(pid, server);
}
/** /**
* Helper function for getting the error log message when the user specifies * Helper function for getting the error log message when the user specifies
* a nonexistent running script * a nonexistent running script
@ -689,6 +734,7 @@ function NetscriptFunctions(workerScript) {
const argsToString = function(args) { const argsToString = function(args) {
let out = ''; let out = '';
for(let arg of args) { for(let arg of args) {
arg = toNative(arg);
if(typeof arg === 'object') { if(typeof arg === 'object') {
out += JSON.stringify(arg); out += JSON.stringify(arg);
continue continue
@ -1004,8 +1050,13 @@ function NetscriptFunctions(workerScript) {
return runningScriptObj.logs.slice(); return runningScriptObj.logs.slice();
}, },
tail: function(fn, ip, ...scriptArgs) { tail: function(fn, ip=workerScript.serverIp, ...scriptArgs) {
const runningScriptObj = getRunningScript(fn, ip, "tail", scriptArgs); let runningScriptObj;
if(typeof fn === 'number') {
runningScriptObj = getRunningScriptByPid(fn, ip, 'tail');
} else {
runningScriptObj = getRunningScript(fn, ip, "tail", scriptArgs);
}
if (runningScriptObj == null) { if (runningScriptObj == null) {
workerScript.log("tail", getCannotFindRunningScriptErrorMessage(fn, ip, scriptArgs)); workerScript.log("tail", getCannotFindRunningScriptErrorMessage(fn, ip, scriptArgs));
return; return;
@ -1509,7 +1560,12 @@ function NetscriptFunctions(workerScript) {
const processes = []; const processes = [];
for (const i in server.runningScripts) { for (const i in server.runningScripts) {
const script = server.runningScripts[i]; const script = server.runningScripts[i];
processes.push({filename:script.filename, threads: script.threads, args: script.args.slice()}) processes.push({
filename:script.filename,
threads: script.threads,
args: script.args.slice(),
pid: script.pid,
})
} }
return processes; return processes;
}, },
@ -1692,20 +1748,16 @@ function NetscriptFunctions(workerScript) {
} }
return false; return false;
}, },
isRunning: function(filename,ip) { isRunning: function(fn, ip=workerScript.serverIp, ...scriptArgs) {
updateDynamicRam("isRunning", getRamCost("isRunning")); updateDynamicRam("isRunning", getRamCost("isRunning"));
if (filename === undefined || ip === undefined) { if (fn === undefined || ip === undefined) {
throw makeRuntimeErrorMsg("isRunning", "Usage: isRunning(scriptname, server, [arg1], [arg2]...)"); throw makeRuntimeErrorMsg("isRunning", "Usage: isRunning(scriptname, server, [arg1], [arg2]...)");
} }
var server = getServer(ip); if(typeof fn === 'number') {
if (server == null) { return getRunningScriptByPid(fn, ip, 'isRunning') != null;
throw makeRuntimeErrorMsg("isRunning", `Invalid IP/hostname: ${ip}`); } else {
return getRunningScript(fn, ip, "isRunning", scriptArgs) != null;
} }
var argsForTargetScript = [];
for (var i = 2; i < arguments.length; ++i) {
argsForTargetScript.push(arguments[i]);
}
return (findRunningScript(filename, argsForTargetScript, server) != null);
}, },
getStockSymbols: function() { getStockSymbols: function() {
updateDynamicRam("getStockSymbols", getRamCost("getStockSymbols")); updateDynamicRam("getStockSymbols", getRamCost("getStockSymbols"));
@ -4396,6 +4448,34 @@ function NetscriptFunctions(workerScript) {
}, },
exploit: function() { exploit: function() {
Player.giveExploit(Exploit.UndocumentedFunctionCall); Player.giveExploit(Exploit.UndocumentedFunctionCall);
},
flags: function(data) {
data = toNative(data);
// We always want the help flag.
const args = {};
for(const d of data) {
let t = String;
if(typeof d[1] === 'number') {
t = Number;
} else if(typeof d[1] === 'boolean') {
t = Boolean;
} else if(Array.isArray(d[1])) {
t = [String];
}
args['--'+d[0]] = t
}
const ret = libarg(args, {argv: workerScript.args});
for(const d of data) {
if(!ret.hasOwnProperty('--'+d[0])) ret[d[0]] = d[1];
}
for(const key of Object.keys(ret)) {
if(!key.startsWith('--')) continue;
const value = ret[key];
delete ret[key];
ret[key.slice(2)] = value;
}
return ret;
} }
} // End return } // End return
} // End NetscriptFunction() } // End NetscriptFunction()

@ -414,3 +414,14 @@ export function findRunningScript(filename, args, server) {
} }
return null; return null;
} }
//Returns a RunningScript object matching the pid on the
//designated server, and false otherwise
export function findRunningScriptByPid(pid, server) {
for (var i = 0; i < server.runningScripts.length; ++i) {
if (server.runningScripts[i].pid === pid) {
return server.runningScripts[i];
}
}
return null;
}

@ -1097,7 +1097,7 @@ const Engine = {
// Hacknet Nodes offline progress // Hacknet Nodes offline progress
var offlineProductionFromHacknetNodes = processHacknetEarnings(numCyclesOffline); var offlineProductionFromHacknetNodes = processHacknetEarnings(numCyclesOffline);
const hacknetProdInfo = hasHacknetServers() ? const hacknetProdInfo = hasHacknetServers() ?
Hashes(offlineProductionFromHacknetNodes): <>{Hashes(offlineProductionFromHacknetNodes)} hashes</>:
Money(offlineProductionFromHacknetNodes); Money(offlineProductionFromHacknetNodes);
// Passive faction rep gain offline // Passive faction rep gain offline
@ -1151,7 +1151,7 @@ const Engine = {
removeLoadingScreen(); removeLoadingScreen();
const timeOfflineString = convertTimeMsToTimeElapsedString(time); const timeOfflineString = convertTimeMsToTimeElapsedString(time);
dialogBoxCreate(<> dialogBoxCreate(<>
Offline for {timeOfflineString}. While you were offline, your scripts generated {Money(offlineProductionFromScripts)} and your Hacknet Nodes generated {hacknetProdInfo} hashes. Offline for {timeOfflineString}. While you were offline, your scripts generated {Money(offlineProductionFromScripts)} and your Hacknet Nodes generated {hacknetProdInfo}.
</>); </>);
// Close main menu accordions for loaded game // Close main menu accordions for loaded game
var visibleMenuTabs = [terminal, createScript, activeScripts, stats, var visibleMenuTabs = [terminal, createScript, activeScripts, stats,