2022-04-17 02:29:20 +02:00
import $ from "jquery" ;
2021-09-05 01:09:30 +02:00
import { vsprintf , sprintf } from "sprintf-js" ;
2017-10-12 22:10:34 +02:00
2019-06-22 10:12:17 +02:00
import { WorkerScriptStartStopEventEmitter } from "./Netscript/WorkerScriptStartStopEventEmitter" ;
2019-05-05 06:03:40 +02:00
2019-04-11 10:37:40 +02:00
import { BitNodeMultipliers } from "./BitNode/BitNodeMultipliers" ;
2021-11-03 23:16:10 +01:00
2019-04-11 10:37:40 +02:00
import { CONSTANTS } from "./Constants" ;
2021-11-03 23:16:10 +01:00
2019-04-11 10:37:40 +02:00
import {
2021-09-05 01:09:30 +02:00
calculateHackingChance ,
calculateHackingExpGain ,
calculatePercentMoneyHacked ,
calculateHackingTime ,
calculateGrowTime ,
calculateWeakenTime ,
2019-04-11 10:37:40 +02:00
} from "./Hacking" ;
2021-11-03 23:16:10 +01:00
2021-09-09 05:47:34 +02:00
import { netscriptCanGrow , netscriptCanHack , netscriptCanWeaken } from "./Hacking/netscriptCanHack" ;
2019-03-30 04:01:34 +01:00
2021-05-01 09:17:31 +02:00
import { HacknetServer } from "./Hacknet/HacknetServer" ;
2021-11-03 23:16:10 +01:00
2021-03-23 21:02:34 +01:00
import { Terminal } from "./Terminal" ;
2019-04-04 02:12:11 +02:00
2019-04-11 10:37:40 +02:00
import { Player } from "./Player" ;
import { Programs } from "./Programs/Programs" ;
import { Script } from "./Script/Script" ;
2021-09-09 05:47:34 +02:00
import { findRunningScript , findRunningScriptByPid } from "./Script/ScriptHelpers" ;
2021-09-24 22:34:21 +02:00
import { isScriptFilename } from "./Script/isScriptFilename" ;
2021-10-02 04:53:23 +02:00
import { PromptEvent } from "./ui/React/PromptManager" ;
2021-09-24 22:34:21 +02:00
2021-10-07 22:56:01 +02:00
import { GetServer , GetAllServers , DeleteServer , AddToAllServers , createUniqueRandomIp } from "./Server/AllServers" ;
2021-03-12 02:37:58 +01:00
import { RunningScript } from "./Script/RunningScript" ;
2019-04-11 10:37:40 +02:00
import {
2021-09-05 01:09:30 +02:00
getServerOnNetwork ,
numCycleForGrowth ,
2022-04-13 15:54:48 +02:00
numCycleForGrowthCorrected ,
2021-09-05 01:09:30 +02:00
processSingleServerGrowth ,
safetlyCreateUniqueServer ,
2019-04-11 10:37:40 +02:00
} from "./Server/ServerHelpers" ;
2021-09-09 05:47:34 +02:00
import { getPurchaseServerCost , getPurchaseServerLimit , getPurchaseServerMaxRam } from "./Server/ServerPurchases" ;
2021-09-25 03:49:49 +02:00
import { Server } from "./Server/Server" ;
2021-09-09 05:47:34 +02:00
import { influenceStockThroughServerHack , influenceStockThroughServerGrow } from "./StockMarket/PlayerInfluencing" ;
2021-10-14 09:22:02 +02:00
2021-09-09 05:47:34 +02:00
import { isValidFilePath , removeLeadingSlash } from "./Terminal/DirectoryHelpers" ;
2019-04-11 10:37:40 +02:00
import { TextFile , getTextFile , createTextFile } from "./TextFile" ;
2017-08-30 19:44:29 +02:00
2021-10-14 09:22:02 +02:00
import { NetscriptPorts , runScriptFromScript } from "./NetscriptWorker" ;
2019-05-16 08:05:36 +02:00
import { killWorkerScript } from "./Netscript/killWorkerScript" ;
import { workerScripts } from "./Netscript/WorkerScripts" ;
2021-09-25 03:49:49 +02:00
import { WorkerScript } from "./Netscript/WorkerScript" ;
2021-09-09 05:47:34 +02:00
import { makeRuntimeRejectMsg , netscriptDelay , resolveNetscriptRequestedThreads } from "./NetscriptEvaluator" ;
2017-08-30 19:44:29 +02:00
2019-04-11 10:37:40 +02:00
import { numeralWrapper } from "./ui/numeralFormat" ;
2021-09-25 20:42:57 +02:00
import { convertTimeMsToTimeElapsedString } from "./utils/StringHelperFunctions" ;
2019-02-27 03:26:29 +01:00
2022-05-17 20:45:30 +02:00
import { LogBoxEvents , LogBoxCloserEvents } from "./ui/React/LogBoxManager" ;
2021-09-25 20:42:57 +02:00
import { arrayToString } from "./utils/helpers/arrayToString" ;
import { isString } from "./utils/helpers/isString" ;
2017-08-21 18:59:06 +02:00
2021-09-25 08:36:49 +02:00
import { BaseServer } from "./Server/BaseServer" ;
2021-11-03 23:16:10 +01:00
import { NetscriptGang } from "./NetscriptFunctions/Gang" ;
import { NetscriptSleeve } from "./NetscriptFunctions/Sleeve" ;
2022-05-25 02:16:39 +02:00
import { NetscriptExtra } from "./NetscriptFunctions/Extra" ;
2021-11-03 23:16:10 +01:00
import { NetscriptHacknet } from "./NetscriptFunctions/Hacknet" ;
2021-11-14 04:44:17 +01:00
import { NetscriptStanek } from "./NetscriptFunctions/Stanek" ;
2022-03-27 09:53:13 +02:00
import { NetscriptInfiltration } from "./NetscriptFunctions/Infiltration" ;
2021-12-29 08:04:24 +01:00
import { NetscriptUserInterface } from "./NetscriptFunctions/UserInterface" ;
2021-10-28 05:58:07 +02:00
import { NetscriptBladeburner } from "./NetscriptFunctions/Bladeburner" ;
2021-11-03 23:16:10 +01:00
import { NetscriptCodingContract } from "./NetscriptFunctions/CodingContract" ;
2021-11-04 01:19:52 +01:00
import { NetscriptCorporation } from "./NetscriptFunctions/Corporation" ;
2021-11-03 23:16:10 +01:00
import { NetscriptFormulas } from "./NetscriptFunctions/Formulas" ;
2021-10-30 22:03:34 +02:00
import { NetscriptStockMarket } from "./NetscriptFunctions/StockMarket" ;
2022-03-23 18:35:15 +01:00
import { NetscriptGrafting } from "./NetscriptFunctions/Grafting" ;
2021-12-27 19:06:38 +01:00
import { IPort } from "./NetscriptPort" ;
2021-10-14 09:22:02 +02:00
2021-11-14 05:45:26 +01:00
import {
NS as INS ,
Player as INetscriptPlayer ,
Gang as IGang ,
Bladeburner as IBladeburner ,
Stanek as IStanek ,
2022-03-27 09:53:13 +02:00
Infiltration as IInfiltration ,
2022-01-19 08:04:48 +01:00
RunningScript as IRunningScript ,
RecentScript as IRecentScript ,
2021-12-03 21:35:45 +01:00
SourceFileLvl ,
2022-03-30 03:42:27 +02:00
BasicHGWOptions ,
ProcessInfo ,
HackingMultipliers ,
HacknetMultipliers ,
BitNodeMultipliers as IBNMults ,
Server as IServerDef ,
2022-03-30 04:14:56 +02:00
RunningScript as IRunningScriptDef ,
2022-04-13 07:50:35 +02:00
// ToastVariant,
2021-11-14 05:45:26 +01:00
} from "./ScriptEditor/NetscriptDefinitions" ;
2021-11-14 04:44:17 +01:00
import { NetscriptSingularity } from "./NetscriptFunctions/Singularity" ;
2021-09-25 23:21:50 +02:00
2021-10-15 18:47:43 +02:00
import { toNative } from "./NetscriptFunctions/toNative" ;
2021-09-05 01:09:30 +02:00
2021-10-13 02:02:37 +02:00
import { dialogBoxCreate } from "./ui/React/DialogBox" ;
2022-04-13 07:50:35 +02:00
import { SnackbarEvents , ToastVariant } from "./ui/React/Snackbar" ;
2022-04-09 05:42:07 +02:00
import { checkEnum } from "./utils/helpers/checkEnum" ;
2021-11-03 23:16:10 +01:00
2021-10-15 18:47:43 +02:00
import { Flags } from "./NetscriptFunctions/Flags" ;
2022-01-18 20:02:12 +01:00
import { calculateIntelligenceBonus } from "./PersonObjects/formulas/intelligence" ;
import { CalculateShareMult , StartSharing } from "./NetworkShare/Share" ;
2022-01-19 08:04:48 +01:00
import { recentScripts } from "./Netscript/RecentScripts" ;
2022-03-30 17:34:03 +02:00
import { CityName } from "./Locations/data/CityNames" ;
2022-05-25 02:16:39 +02:00
import { InternalAPI , NetscriptContext , wrapAPI } from "./Netscript/APIWrapper" ;
import { INetscriptHelper } from "./NetscriptFunctions/INetscriptHelper" ;
2021-04-21 14:20:26 +02:00
2021-11-04 01:19:52 +01:00
interface NS extends INS {
2021-09-25 03:49:49 +02:00
[ key : string ] : any ;
2021-11-14 05:45:26 +01:00
gang : IGang ;
bladeburner : IBladeburner ;
stanek : IStanek ;
2022-03-27 09:53:13 +02:00
infiltration : IInfiltration ;
2021-09-25 03:49:49 +02:00
}
2021-11-04 01:19:52 +01:00
export function NetscriptFunctions ( workerScript : WorkerScript ) : NS {
2021-09-25 08:36:49 +02:00
const updateDynamicRam = function ( fnName : string , ramCost : number ) : void {
2021-09-05 01:09:30 +02:00
if ( workerScript . dynamicLoadedFns [ fnName ] ) {
return ;
}
workerScript . dynamicLoadedFns [ fnName ] = true ;
let threads = workerScript . scriptRef . threads ;
if ( typeof threads !== "number" ) {
2021-10-07 23:55:49 +02:00
console . warn ( ` WorkerScript detected NaN for threadcount for ${ workerScript . name } on ${ workerScript . hostname } ` ) ;
2021-09-05 01:09:30 +02:00
threads = 1 ;
2018-09-23 02:25:48 +02:00
}
2021-10-28 00:55:06 +02:00
workerScript . dynamicRamUsage += ramCost ;
2021-09-05 01:09:30 +02:00
if ( workerScript . dynamicRamUsage > 1.01 * workerScript . ramUsage ) {
throw makeRuntimeRejectMsg (
workerScript ,
2021-09-05 01:27:16 +02:00
` Dynamic RAM usage calculated to be greater than initial RAM usage on fn: ${ fnName } .
This is probably because you somehow circumvented the static RAM calculation .
2021-10-28 00:55:06 +02:00
Threads : $ { threads }
2021-09-09 05:47:34 +02:00
Dynamic RAM Usage : $ { numeralWrapper . formatRAM ( workerScript . dynamicRamUsage ) }
2021-09-05 01:27:16 +02:00
Static RAM Usage : $ { numeralWrapper . formatRAM ( workerScript . ramUsage ) }
One of these could be the reason :
* Using eval ( ) to get a reference to a ns function
2021-10-19 16:13:19 +02:00
& nbsp ; & nbsp ; const myScan = eval ( 'ns.scan' ) ;
2021-09-05 01:27:16 +02:00
* Using map access to do the same
2021-10-19 16:13:19 +02:00
& nbsp ; & nbsp ; const myScan = ns [ 'scan' ] ;
2021-09-05 01:27:16 +02:00
Sorry : ( ` ,
2021-09-05 01:09:30 +02:00
) ;
}
} ;
/ * *
* Gets the Server for a specific hostname / ip , throwing an error
* if the server doesn ' t exist .
2021-10-19 16:13:19 +02:00
* @param { string } hostname - Hostname or IP of the server
2021-09-05 01:09:30 +02:00
* @param { string } callingFnName - Name of calling function . For logging purposes
2021-10-19 16:13:19 +02:00
* @returns { BaseServer } The specified server as a BaseServer
2021-09-05 01:09:30 +02:00
* /
2022-05-25 02:16:39 +02:00
const safeGetServer = function ( hostname : string , ctx : NetscriptContext ) : BaseServer {
2021-10-19 16:13:19 +02:00
const server = GetServer ( hostname ) ;
2021-09-05 01:09:30 +02:00
if ( server == null ) {
2022-05-25 02:16:39 +02:00
throw ctx . makeRuntimeErrorMsg ( ` Invalid hostname: ${ hostname } ` ) ;
2021-09-05 01:09:30 +02:00
}
return server ;
} ;
/ * *
* Searches for and returns the RunningScript object for the specified script .
* If the 'fn' argument is not specified , this returns the current RunningScript .
* @param { string } fn - Filename of script
2021-10-19 16:13:19 +02:00
* @param { string } hostname - Hostname / ip of the server on which the script resides
2021-09-05 01:09:30 +02:00
* @param { any [ ] } scriptArgs - Running script ' s arguments
* @returns { RunningScript }
* Running script identified by the parameters , or null if no such script
* exists , or the current running script if the first argument 'fn'
* is not specified .
* /
2021-10-23 16:09:43 +02:00
const getRunningScript = function (
2022-05-25 02:16:39 +02:00
ctx : NetscriptContext ,
2022-03-30 03:42:27 +02:00
fn : string ,
hostname : string ,
2021-10-23 16:09:43 +02:00
scriptArgs : any ,
) : RunningScript | null {
2021-09-05 01:09:30 +02:00
if ( ! Array . isArray ( scriptArgs ) ) {
throw makeRuntimeRejectMsg (
workerScript ,
2022-05-25 02:16:39 +02:00
` Invalid scriptArgs argument passed into getRunningScript() from ${ ctx . function } (). ` +
2022-01-18 20:02:12 +01:00
` This is probably a bug. Please report to game developer ` ,
2021-09-05 01:09:30 +02:00
) ;
2021-04-21 14:20:26 +02:00
}
2021-09-05 01:09:30 +02:00
if ( fn != null && typeof fn === "string" ) {
// Get Logs of another script
2021-10-19 16:13:19 +02:00
if ( hostname == null ) {
hostname = workerScript . hostname ;
2021-09-05 01:09:30 +02:00
}
2022-05-25 02:16:39 +02:00
const server = safeGetServer ( hostname , ctx ) ;
2019-07-05 03:01:09 +02:00
2021-09-05 01:09:30 +02:00
return findRunningScript ( fn , scriptArgs , server ) ;
2019-07-05 03:01:09 +02:00
}
2021-09-05 01:09:30 +02:00
// If no arguments are specified, return the current RunningScript
return workerScript . scriptRef ;
} ;
2022-05-25 02:16:39 +02:00
const getRunningScriptByPid = function ( pid : number ) : RunningScript | null {
2021-10-07 22:04:04 +02:00
for ( const server of GetAllServers ( ) ) {
2021-09-05 01:09:30 +02:00
const runningScript = findRunningScriptByPid ( pid , server ) ;
if ( runningScript ) return runningScript ;
}
return null ;
} ;
2022-01-19 08:04:48 +01:00
/ * *
* Sanitizes a ` RunningScript ` to remove sensitive information , making it suitable for
* return through an NS function .
* @see NS . getRecentScripts
* @see NS . getRunningScript
* @param runningScript Existing , internal RunningScript
* @returns A sanitized , NS - facing copy of the RunningScript
* /
const createPublicRunningScript = function ( runningScript : RunningScript ) : IRunningScript {
return {
args : runningScript.args.slice ( ) ,
filename : runningScript.filename ,
logs : runningScript.logs.slice ( ) ,
offlineExpGained : runningScript.offlineExpGained ,
offlineMoneyMade : runningScript.offlineMoneyMade ,
offlineRunningTime : runningScript.offlineRunningTime ,
onlineExpGained : runningScript.onlineExpGained ,
onlineMoneyMade : runningScript.onlineMoneyMade ,
onlineRunningTime : runningScript.onlineRunningTime ,
pid : runningScript.pid ,
ramUsage : runningScript.ramUsage ,
server : runningScript.server ,
threads : runningScript.threads ,
} ;
} ;
2021-09-05 01:09:30 +02:00
/ * *
* Helper function for getting the error log message when the user specifies
* a nonexistent running script
* @param { string } fn - Filename of script
2021-10-19 16:13:19 +02:00
* @param { string } hostname - Hostname / ip of the server on which the script resides
2021-09-05 01:09:30 +02:00
* @param { any [ ] } scriptArgs - Running script ' s arguments
* @returns { string } Error message to print to logs
* /
2022-03-30 03:42:27 +02:00
const getCannotFindRunningScriptErrorMessage = function ( fn : string , hostname : string , scriptArgs : any ) : string {
2021-09-05 01:09:30 +02:00
if ( ! Array . isArray ( scriptArgs ) ) {
scriptArgs = [ ] ;
}
2019-04-29 08:20:27 +02:00
2021-10-19 16:13:19 +02:00
return ` Cannot find running script ${ fn } on server ${ hostname } with args: ${ arrayToString ( scriptArgs ) } ` ;
2021-09-05 01:09:30 +02:00
} ;
/ * *
* Used to fail a function if the function ' s target is a Hacknet Server .
* This is used for functions that should run on normal Servers , but not Hacknet Servers
* @param { Server } server - Target server
* @param { string } callingFn - Name of calling function . For logging purposes
* @returns { boolean } True if the server is a Hacknet Server , false otherwise
* /
2022-03-30 03:42:27 +02:00
const failOnHacknetServer = function ( server : BaseServer , callingFn = "" ) : boolean {
2021-09-05 01:09:30 +02:00
if ( server instanceof HacknetServer ) {
2021-11-27 00:30:58 +01:00
workerScript . log ( callingFn , ( ) = > ` Does not work on Hacknet Servers ` ) ;
2021-09-05 01:09:30 +02:00
return true ;
} else {
return false ;
}
} ;
2021-09-25 08:36:49 +02:00
const makeRuntimeErrorMsg = function ( caller : string , msg : string ) : string {
2021-09-25 03:49:49 +02:00
const errstack = new Error ( ) . stack ;
if ( errstack === undefined ) throw new Error ( "how did we not throw an error?" ) ;
const stack = errstack . split ( "\n" ) . slice ( 1 ) ;
2021-09-05 01:09:30 +02:00
const scripts = workerScript . getServer ( ) . scripts ;
const userstack = [ ] ;
for ( const stackline of stack ) {
let filename ;
for ( const script of scripts ) {
if ( script . url && stackline . includes ( script . url ) ) {
filename = script . filename ;
2018-07-15 02:25:50 +02:00
}
2021-09-05 01:09:30 +02:00
for ( const dependency of script . dependencies ) {
if ( stackline . includes ( dependency . url ) ) {
filename = dependency . filename ;
}
2018-07-15 02:25:50 +02:00
}
2021-09-05 01:09:30 +02:00
}
if ( ! filename ) continue ;
2019-03-30 00:14:32 +01:00
2021-09-25 08:36:49 +02:00
interface ILine {
line : string ;
func : string ;
}
function parseChromeStackline ( line : string ) : ILine | null {
2021-09-05 01:09:30 +02:00
const lineRe = /.*:(\d+):\d+.*/ ;
const funcRe = /.*at (.+) \(.*/ ;
2019-03-30 00:14:32 +01:00
2021-09-05 01:09:30 +02:00
const lineMatch = line . match ( lineRe ) ;
const funcMatch = line . match ( funcRe ) ;
if ( lineMatch && funcMatch ) {
return { line : lineMatch [ 1 ] , func : funcMatch [ 1 ] } ;
}
return null ;
}
let call = { line : "-1" , func : "unknown" } ;
const chromeCall = parseChromeStackline ( stackline ) ;
if ( chromeCall ) {
call = chromeCall ;
}
2021-03-25 07:48:15 +01:00
2021-09-25 08:36:49 +02:00
function parseFirefoxStackline ( line : string ) : ILine | null {
2021-09-05 01:09:30 +02:00
const lineRe = /.*:(\d+):\d+$/ ;
const lineMatch = line . match ( lineRe ) ;
2021-03-10 07:27:14 +01:00
2021-09-05 01:09:30 +02:00
const lio = line . lastIndexOf ( "@" ) ;
2021-03-11 09:02:05 +01:00
2021-09-05 01:09:30 +02:00
if ( lineMatch && lio !== - 1 ) {
return { line : lineMatch [ 1 ] , func : line.slice ( 0 , lio ) } ;
}
return null ;
}
2021-03-25 07:48:15 +01:00
2021-09-25 07:26:03 +02:00
const firefoxCall = parseFirefoxStackline ( stackline ) ;
2021-09-05 01:09:30 +02:00
if ( firefoxCall ) {
call = firefoxCall ;
}
2021-03-11 09:02:05 +01:00
2021-09-05 01:09:30 +02:00
userstack . push ( ` ${ filename } :L ${ call . line } @ ${ call . func } ` ) ;
}
2021-03-11 09:02:05 +01:00
2021-11-27 00:30:58 +01:00
workerScript . log ( caller , ( ) = > msg ) ;
2021-09-05 01:09:30 +02:00
let rejectMsg = ` ${ caller } : ${ msg } ` ;
2021-09-09 05:47:34 +02:00
if ( userstack . length !== 0 ) rejectMsg += ` <br><br>Stack:<br> ${ userstack . join ( "<br>" ) } ` ;
2021-09-05 01:09:30 +02:00
return makeRuntimeRejectMsg ( workerScript , rejectMsg ) ;
} ;
2022-01-05 04:21:44 +01:00
const checkSingularityAccess = function ( func : string ) : void {
2021-09-05 01:09:30 +02:00
if ( Player . bitNodeN !== 4 ) {
2022-01-05 04:21:44 +01:00
if ( Player . sourceFileLvl ( 4 ) === 0 ) {
2021-12-19 00:13:49 +01:00
throw makeRuntimeErrorMsg (
func ,
2022-01-05 04:21:44 +01:00
` This singularity function requires Source-File 4 to run. A power up you obtain later in the game. It will be very obvious when and how you can obtain it. ` ,
2021-12-19 00:13:49 +01:00
) ;
2021-09-05 01:09:30 +02:00
}
}
} ;
2022-05-08 01:08:07 +02:00
const hack = async function (
2022-05-25 02:16:39 +02:00
ctx : NetscriptContext ,
2022-03-30 03:42:27 +02:00
hostname : string ,
manual : boolean ,
{ threads : requestedThreads , stock } : any = { } ,
) : Promise < number > {
2021-10-19 16:13:19 +02:00
if ( hostname === undefined ) {
2022-05-25 02:16:39 +02:00
throw ctx . makeRuntimeErrorMsg ( "Takes 1 argument." ) ;
2021-09-05 01:09:30 +02:00
}
2022-05-25 02:16:39 +02:00
const threads = resolveNetscriptRequestedThreads ( ctx , requestedThreads ) ;
const server = safeGetServer ( hostname , ctx ) ;
2021-09-25 03:49:49 +02:00
if ( ! ( server instanceof Server ) ) {
2022-05-25 02:16:39 +02:00
throw ctx . makeRuntimeErrorMsg ( "Cannot be executed on this server." ) ;
2021-03-11 09:02:05 +01:00
}
2021-09-05 01:09:30 +02:00
// Calculate the hacking time
2021-09-25 03:49:49 +02:00
const hackingTime = calculateHackingTime ( server , Player ) ; // This is in seconds
2021-09-05 01:09:30 +02:00
// No root access or skill level too low
const canHack = netscriptCanHack ( server , Player ) ;
if ( ! canHack . res ) {
2022-05-25 02:16:39 +02:00
throw ctx . makeRuntimeErrorMsg ( canHack . msg || "" ) ;
2021-03-11 09:02:05 +01:00
}
2022-05-25 02:16:39 +02:00
ctx . log (
2021-11-27 00:30:58 +01:00
( ) = >
2022-01-12 14:58:12 +01:00
` Executing on ' ${ server . hostname } ' in ${ convertTimeMsToTimeElapsedString (
2021-11-27 00:30:58 +01:00
hackingTime * 1000 ,
true ,
) } ( t = $ { numeralWrapper . formatThreads ( threads ) } ) ` ,
2021-09-05 01:09:30 +02:00
) ;
return netscriptDelay ( hackingTime * 1000 , workerScript ) . then ( function ( ) {
2021-09-25 07:26:03 +02:00
const hackChance = calculateHackingChance ( server , Player ) ;
const rand = Math . random ( ) ;
let expGainedOnSuccess = calculateHackingExpGain ( server , Player ) * threads ;
const expGainedOnFailure = expGainedOnSuccess / 4 ;
2021-09-05 01:09:30 +02:00
if ( rand < hackChance ) {
// Success!
const percentHacked = calculatePercentMoneyHacked ( server , Player ) ;
2022-01-15 20:33:46 +01:00
let maxThreadNeeded = Math . ceil ( 1 / percentHacked ) ;
2021-09-05 01:09:30 +02:00
if ( isNaN ( maxThreadNeeded ) ) {
// Server has a 'max money' of 0 (probably). We'll set this to an arbitrarily large value
maxThreadNeeded = 1 e6 ;
2021-03-11 09:02:05 +01:00
}
2021-09-09 05:47:34 +02:00
let moneyDrained = Math . floor ( server . moneyAvailable * percentHacked ) * threads ;
2021-03-11 09:02:05 +01:00
2021-09-05 01:09:30 +02:00
// Over-the-top safety checks
if ( moneyDrained <= 0 ) {
moneyDrained = 0 ;
expGainedOnSuccess = expGainedOnFailure ;
2021-03-11 09:02:05 +01:00
}
2021-09-05 01:09:30 +02:00
if ( moneyDrained > server . moneyAvailable ) {
moneyDrained = server . moneyAvailable ;
}
server . moneyAvailable -= moneyDrained ;
if ( server . moneyAvailable < 0 ) {
server . moneyAvailable = 0 ;
2021-03-11 09:02:05 +01:00
}
2022-05-25 11:20:32 +02:00
let moneyGained = moneyDrained * BitNodeMultipliers . ScriptHackMoneyGain ;
2022-05-24 18:28:10 +02:00
if ( manual ) {
2022-05-25 11:20:32 +02:00
moneyGained = moneyDrained * BitNodeMultipliers . ManualHackMoney ;
2022-05-24 18:28:10 +02:00
}
2021-09-05 01:09:30 +02:00
2021-10-27 20:18:33 +02:00
Player . gainMoney ( moneyGained , "hacking" ) ;
2021-09-05 01:09:30 +02:00
workerScript . scriptRef . onlineMoneyMade += moneyGained ;
Player . scriptProdSinceLastAug += moneyGained ;
2021-10-07 23:55:49 +02:00
workerScript . scriptRef . recordHack ( server . hostname , moneyGained , threads ) ;
2021-09-05 01:09:30 +02:00
Player . gainHackingExp ( expGainedOnSuccess ) ;
2022-01-09 21:22:23 +01:00
if ( manual ) Player . gainIntelligenceExp ( 0.005 ) ;
2021-09-05 01:09:30 +02:00
workerScript . scriptRef . onlineExpGained += expGainedOnSuccess ;
2022-05-25 02:16:39 +02:00
ctx . log (
2021-11-27 00:30:58 +01:00
( ) = >
` Successfully hacked ' ${ server . hostname } ' for ${ numeralWrapper . formatMoney (
moneyGained ,
) } and $ { numeralWrapper . formatExp ( expGainedOnSuccess ) } exp ( t = $ { numeralWrapper . formatThreads ( threads ) } ) ` ,
2021-09-05 01:09:30 +02:00
) ;
2021-09-09 05:47:34 +02:00
server . fortify ( CONSTANTS . ServerFortifyAmount * Math . min ( threads , maxThreadNeeded ) ) ;
2021-09-05 01:09:30 +02:00
if ( stock ) {
2021-11-25 17:47:31 +01:00
influenceStockThroughServerHack ( server , moneyDrained ) ;
2021-03-11 09:02:05 +01:00
}
2021-09-05 01:09:30 +02:00
if ( manual ) {
server . backdoorInstalled = true ;
}
return Promise . resolve ( moneyGained ) ;
} else {
// Player only gains 25% exp for failure?
Player . gainHackingExp ( expGainedOnFailure ) ;
workerScript . scriptRef . onlineExpGained += expGainedOnFailure ;
2022-05-25 02:16:39 +02:00
ctx . log (
2021-11-27 00:30:58 +01:00
( ) = >
` Failed to hack ' ${ server . hostname } '. Gained ${ numeralWrapper . formatExp (
expGainedOnFailure ,
) } exp ( t = $ { numeralWrapper . formatThreads ( threads ) } ) ` ,
2021-09-05 01:09:30 +02:00
) ;
return Promise . resolve ( 0 ) ;
}
} ) ;
} ;
2021-09-25 08:36:49 +02:00
const argsToString = function ( args : any [ ] ) : string {
2021-09-05 01:09:30 +02:00
let out = "" ;
for ( let arg of args ) {
arg = toNative ( arg ) ;
2021-10-23 16:09:43 +02:00
out += typeof arg === "object" ? JSON . stringify ( arg ) : ` ${ arg } ` ;
2021-03-11 09:02:05 +01:00
}
2021-09-05 01:09:30 +02:00
return out ;
} ;
2022-05-25 02:16:39 +02:00
const helper : INetscriptHelper = {
2021-10-05 03:06:55 +02:00
updateDynamicRam : updateDynamicRam ,
makeRuntimeErrorMsg : makeRuntimeErrorMsg ,
2022-03-17 00:33:45 +01:00
string : ( funcName : string , argName : string , v : unknown ) : string = > {
2021-10-05 04:25:21 +02:00
if ( typeof v === "string" ) return v ;
if ( typeof v === "number" ) return v + "" ; // cast to string;
2022-03-30 17:34:03 +02:00
throw makeRuntimeErrorMsg ( funcName , ` ${ argName } should be a string. ` ) ;
2021-10-05 04:25:21 +02:00
} ,
2022-03-17 00:33:45 +01:00
number : ( funcName : string , argName : string , v : unknown ) : number = > {
if ( typeof v === "string" ) {
const x = parseFloat ( v ) ;
if ( ! isNaN ( x ) ) return x ; // otherwise it wasn't even a string representing a number.
} else if ( typeof v === "number" ) {
2022-03-30 17:34:03 +02:00
if ( isNaN ( v ) ) throw makeRuntimeErrorMsg ( funcName , ` ${ argName } is NaN. ` ) ;
2022-03-17 00:33:45 +01:00
return v ;
2022-01-12 07:24:03 +01:00
}
2022-03-30 17:34:03 +02:00
throw makeRuntimeErrorMsg ( funcName , ` ${ argName } should be a number. ` ) ;
2021-10-05 04:25:21 +02:00
} ,
2022-03-17 00:33:45 +01:00
boolean : ( v : unknown ) : boolean = > {
2021-10-05 04:25:21 +02:00
return ! ! v ; // Just convert it to boolean.
} ,
2022-03-30 17:34:03 +02:00
city : ( funcName : string , argName : string , v : unknown ) : CityName = > {
if ( typeof v !== "string" ) throw makeRuntimeErrorMsg ( funcName , ` ${ argName } should be a city name. ` ) ;
const s = v as CityName ;
if ( ! Object . values ( CityName ) . includes ( s ) )
throw makeRuntimeErrorMsg ( funcName , ` ${ argName } should be a city name. ` ) ;
return s ;
} ,
2021-10-14 09:22:02 +02:00
getServer : safeGetServer ,
checkSingularityAccess : checkSingularityAccess ,
2021-11-03 23:16:10 +01:00
hack : hack ,
2022-03-30 03:42:27 +02:00
getValidPort : ( funcName : string , port : number ) : IPort = > {
2021-12-27 19:06:38 +01:00
if ( isNaN ( port ) ) {
throw makeRuntimeErrorMsg (
funcName ,
` Invalid argument. Must be a port number between 1 and ${ CONSTANTS . NumNetscriptPorts } , is ${ port } ` ,
) ;
}
port = Math . round ( port ) ;
if ( port < 1 || port > CONSTANTS . NumNetscriptPorts ) {
throw makeRuntimeErrorMsg (
funcName ,
2021-12-27 20:36:14 +01:00
` Trying to use an invalid port: ${ port } . Only ports 1- ${ CONSTANTS . NumNetscriptPorts } are valid. ` ,
2021-12-27 19:06:38 +01:00
) ;
}
const iport = NetscriptPorts [ port - 1 ] ;
if ( iport == null || ! ( iport instanceof Object ) ) {
throw makeRuntimeErrorMsg ( funcName , ` Could not find port: ${ port } . This is a bug. Report to dev. ` ) ;
}
return iport ;
2022-01-05 01:09:34 +01:00
} ,
2021-10-05 03:06:55 +02:00
} ;
2021-03-11 09:02:05 +01:00
2022-05-25 02:16:39 +02:00
const singularity = NetscriptSingularity ( Player , workerScript ) ;
const base : InternalAPI < INS > = {
2021-11-04 01:19:52 +01:00
. . . singularity ,
2022-05-25 02:16:39 +02:00
args : workerScript.args as unknown as any ,
enums : {
toast : ToastVariant ,
} as unknown as any ,
2022-03-29 23:48:45 +02:00
singularity : singularity ,
2022-05-25 02:16:39 +02:00
gang : NetscriptGang ( Player , workerScript ) ,
bladeburner : NetscriptBladeburner ( Player , workerScript ) ,
codingcontract : NetscriptCodingContract ( Player , workerScript ) ,
sleeve : NetscriptSleeve ( Player ) ,
corporation : NetscriptCorporation ( Player , workerScript ) ,
stanek : NetscriptStanek ( Player , workerScript , helper ) ,
infiltration : NetscriptInfiltration ( Player ) ,
ui : NetscriptUserInterface ( ) ,
formulas : NetscriptFormulas ( Player , helper ) ,
stock : NetscriptStockMarket ( Player , workerScript ) ,
grafting : NetscriptGrafting ( Player ) ,
hacknet : NetscriptHacknet ( Player , workerScript ) ,
2022-05-26 06:34:30 +02:00
sprintf : ( ) = > sprintf ,
vsprintf : ( ) = > vsprintf ,
2022-05-25 02:16:39 +02:00
scan :
( ctx : NetscriptContext ) = >
( _hostname : unknown = workerScript . hostname ) : string [ ] = > {
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
const server = safeGetServer ( hostname , ctx ) ;
const out = [ ] ;
for ( let i = 0 ; i < server . serversOnNetwork . length ; i ++ ) {
const s = getServerOnNetwork ( server , i ) ;
if ( s === null ) continue ;
const entry = s . hostname ;
if ( entry === null ) continue ;
out . push ( entry ) ;
}
ctx . log ( ( ) = > ` returned ${ server . serversOnNetwork . length } connections for ${ server . hostname } ` ) ;
return out ;
} ,
hack :
( ctx : NetscriptContext ) = >
( _hostname : unknown , { threads : requestedThreads , stock } : BasicHGWOptions = { } ) : Promise < number > = > {
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
return hack ( ctx , hostname , false , { threads : requestedThreads , stock : stock } ) ;
} ,
hackAnalyzeThreads :
( ctx : NetscriptContext ) = >
( _hostname : unknown , _hackAmount : unknown ) : number = > {
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
const hackAmount = ctx . helper . number ( "hackAmount" , _hackAmount ) ;
// Check argument validity
const server = safeGetServer ( hostname , ctx ) ;
if ( ! ( server instanceof Server ) ) {
ctx . log ( ( ) = > "Cannot be executed on this server." ) ;
return - 1 ;
}
if ( isNaN ( hackAmount ) ) {
throw ctx . makeRuntimeErrorMsg (
` Invalid hackAmount argument passed into hackAnalyzeThreads: ${ hackAmount } . Must be numeric. ` ,
) ;
}
2021-03-10 07:27:14 +01:00
2022-05-25 02:16:39 +02:00
if ( hackAmount < 0 || hackAmount > server . moneyAvailable ) {
return - 1 ;
} else if ( hackAmount === 0 ) {
return 0 ;
}
2021-09-02 06:36:33 +02:00
2022-05-25 02:16:39 +02:00
const percentHacked = calculatePercentMoneyHacked ( server , Player ) ;
2022-01-30 23:14:10 +01:00
2022-05-25 02:16:39 +02:00
if ( percentHacked === 0 || server . moneyAvailable === 0 ) {
return 0 ; // To prevent returning infinity below
}
2021-09-02 06:36:33 +02:00
2022-05-25 02:16:39 +02:00
return hackAmount / Math . floor ( server . moneyAvailable * percentHacked ) ;
} ,
hackAnalyze :
( ctx : NetscriptContext ) = >
( _hostname : unknown ) : number = > {
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
2021-09-02 06:36:33 +02:00
2022-05-25 02:16:39 +02:00
const server = safeGetServer ( hostname , ctx ) ;
2022-04-12 17:42:49 +02:00
if ( ! ( server instanceof Server ) ) {
2022-05-25 02:16:39 +02:00
ctx . log ( ( ) = > "Cannot be executed on this server." ) ;
2022-04-12 17:42:49 +02:00
return 0 ;
}
2022-05-25 02:16:39 +02:00
return calculatePercentMoneyHacked ( server , Player ) ;
} ,
hackAnalyzeSecurity :
( ctx : NetscriptContext ) = >
( _threads : unknown , _hostname? : unknown ) : number = > {
let threads = ctx . helper . number ( "threads" , _threads ) ;
if ( _hostname ) {
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
const server = safeGetServer ( hostname , ctx ) ;
if ( ! ( server instanceof Server ) ) {
ctx . log ( ( ) = > "Cannot be executed on this server." ) ;
return 0 ;
}
const percentHacked = calculatePercentMoneyHacked ( server , Player ) ;
2022-04-12 17:42:49 +02:00
2022-05-25 02:16:39 +02:00
if ( percentHacked > 0 ) {
// thread count is limited to the maximum number of threads needed
threads = Math . min ( threads , Math . ceil ( 1 / percentHacked ) ) ;
}
2022-04-12 17:42:49 +02:00
}
2022-05-25 02:16:39 +02:00
return CONSTANTS . ServerFortifyAmount * threads ;
} ,
hackAnalyzeChance :
( ctx : NetscriptContext ) = >
( _hostname : unknown ) : number = > {
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
2021-09-02 06:36:33 +02:00
2022-05-25 02:16:39 +02:00
const server = safeGetServer ( hostname , ctx ) ;
if ( ! ( server instanceof Server ) ) {
ctx . log ( ( ) = > "Cannot be executed on this server." ) ;
return 0 ;
}
2021-09-05 01:09:30 +02:00
2022-05-25 02:16:39 +02:00
return calculateHackingChance ( server , Player ) ;
} ,
sleep :
( ctx : NetscriptContext ) = >
async ( _time : unknown = 0 ) : Promise < true > = > {
const time = ctx . helper . number ( "time" , _time ) ;
if ( time === undefined ) {
throw ctx . makeRuntimeErrorMsg ( "Takes 1 argument." ) ;
}
ctx . log ( ( ) = > ` Sleeping for ${ time } milliseconds ` ) ;
return netscriptDelay ( time , workerScript ) . then ( function ( ) {
return Promise . resolve ( true ) ;
} ) ;
} ,
asleep : ( ctx : NetscriptContext ) = >
function ( _time : unknown = 0 ) : Promise < true > {
const time = ctx . helper . number ( "time" , _time ) ;
ctx . log ( ( ) = > ` Sleeping for ${ time } milliseconds ` ) ;
return new Promise ( ( resolve ) = > setTimeout ( ( ) = > resolve ( true ) , time ) ) ;
} ,
grow :
( ctx : NetscriptContext ) = >
async ( _hostname : unknown , { threads : requestedThreads , stock } : BasicHGWOptions = { } ) : Promise < number > = > {
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
const threads = resolveNetscriptRequestedThreads ( ctx , requestedThreads ? ? workerScript . scriptRef . threads ) ;
const server = safeGetServer ( hostname , ctx ) ;
if ( ! ( server instanceof Server ) ) {
ctx . log ( ( ) = > "Cannot be executed on this server." ) ;
return Promise . resolve ( 0 ) ;
}
2021-09-05 01:09:30 +02:00
2022-05-25 02:16:39 +02:00
const host = GetServer ( workerScript . hostname ) ;
if ( host === null ) {
throw new Error ( "Workerscript host is null" ) ;
}
2021-09-05 01:09:30 +02:00
2022-05-25 02:16:39 +02:00
// No root access or skill level too low
const canHack = netscriptCanGrow ( server ) ;
if ( ! canHack . res ) {
throw ctx . makeRuntimeErrorMsg ( canHack . msg || "" ) ;
}
2021-03-12 02:37:58 +01:00
2022-05-25 02:16:39 +02:00
const growTime = calculateGrowTime ( server , Player ) ;
ctx . log (
2021-11-27 00:30:58 +01:00
( ) = >
2022-05-25 02:16:39 +02:00
` Executing on ' ${ server . hostname } ' in ${ convertTimeMsToTimeElapsedString (
growTime * 1000 ,
true ,
) } ( t = $ { numeralWrapper . formatThreads ( threads ) } ) . ` ,
2021-09-05 01:09:30 +02:00
) ;
2022-05-25 02:16:39 +02:00
return netscriptDelay ( growTime * 1000 , workerScript ) . then ( function ( ) {
const moneyBefore = server . moneyAvailable <= 0 ? 1 : server.moneyAvailable ;
processSingleServerGrowth ( server , threads , Player , host . cpuCores ) ;
const moneyAfter = server . moneyAvailable ;
workerScript . scriptRef . recordGrow ( server . hostname , threads ) ;
const expGain = calculateHackingExpGain ( server , Player ) * threads ;
const logGrowPercent = moneyAfter / moneyBefore - 1 ;
ctx . log (
( ) = >
` Available money on ' ${ server . hostname } ' grown by ${ numeralWrapper . formatPercentage (
logGrowPercent ,
6 ,
) } . Gained $ { numeralWrapper . formatExp ( expGain ) } hacking exp ( t = $ { numeralWrapper . formatThreads (
threads ,
) } ) . ` ,
) ;
workerScript . scriptRef . onlineExpGained += expGain ;
Player . gainHackingExp ( expGain ) ;
if ( stock ) {
influenceStockThroughServerGrow ( server , moneyAfter - moneyBefore ) ;
}
return Promise . resolve ( moneyAfter / moneyBefore ) ;
} ) ;
} ,
growthAnalyze :
( ctx : NetscriptContext ) = >
( _hostname : unknown , _growth : unknown , _cores : unknown = 1 ) : number = > {
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
const growth = ctx . helper . number ( "growth" , _growth ) ;
const cores = ctx . helper . number ( "cores" , _cores ) ;
// Check argument validity
const server = safeGetServer ( hostname , ctx ) ;
2022-04-13 09:16:59 +02:00
if ( ! ( server instanceof Server ) ) {
2022-05-25 02:16:39 +02:00
ctx . log ( ( ) = > "Cannot be executed on this server." ) ;
2022-04-13 09:16:59 +02:00
return 0 ;
}
2022-05-25 02:16:39 +02:00
if ( typeof growth !== "number" || isNaN ( growth ) || growth < 1 || ! isFinite ( growth ) ) {
throw ctx . makeRuntimeErrorMsg ( ` Invalid argument: growth must be numeric and >= 1, is ${ growth } . ` ) ;
}
2022-04-13 09:16:59 +02:00
2022-05-25 02:16:39 +02:00
return numCycleForGrowth ( server , Number ( growth ) , Player , cores ) ;
} ,
growthAnalyzeSecurity :
( ctx : NetscriptContext ) = >
( _threads : unknown , _hostname? : unknown , _cores? : unknown ) : number = > {
let threads = ctx . helper . number ( "threads" , _threads ) ;
if ( _hostname ) {
const cores = ctx . helper . number ( "cores" , _cores ) || 1 ;
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
const server = safeGetServer ( hostname , ctx ) ;
2022-04-13 09:16:59 +02:00
2022-05-25 02:16:39 +02:00
if ( ! ( server instanceof Server ) ) {
ctx . log ( ( ) = > "Cannot be executed on this server." ) ;
return 0 ;
}
2022-04-13 09:16:59 +02:00
2022-05-25 02:16:39 +02:00
const maxThreadsNeeded = Math . ceil (
numCycleForGrowthCorrected ( server , server . moneyMax , server . moneyAvailable , Player , cores ) ,
) ;
2021-09-05 01:09:30 +02:00
2022-05-25 02:16:39 +02:00
threads = Math . min ( threads , maxThreadsNeeded ) ;
}
2021-09-05 01:09:30 +02:00
2022-05-25 02:16:39 +02:00
return 2 * CONSTANTS . ServerFortifyAmount * threads ;
} ,
weaken :
( ctx : NetscriptContext ) = >
async ( _hostname : unknown , { threads : requestedThreads } : BasicHGWOptions = { } ) : Promise < number > = > {
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
const threads = resolveNetscriptRequestedThreads ( ctx , requestedThreads ? ? workerScript . scriptRef . threads ) ;
if ( hostname === undefined ) {
throw ctx . makeRuntimeErrorMsg ( "Takes 1 argument." ) ;
}
const server = safeGetServer ( hostname , ctx ) ;
if ( ! ( server instanceof Server ) ) {
ctx . log ( ( ) = > "Cannot be executed on this server." ) ;
2021-09-25 03:49:49 +02:00
return Promise . resolve ( 0 ) ;
}
2022-05-25 02:16:39 +02:00
// No root access or skill level too low
const canHack = netscriptCanWeaken ( server ) ;
if ( ! canHack . res ) {
throw ctx . makeRuntimeErrorMsg ( canHack . msg || "" ) ;
}
const weakenTime = calculateWeakenTime ( server , Player ) ;
ctx . log (
2021-11-27 00:30:58 +01:00
( ) = >
2022-05-25 02:16:39 +02:00
` Executing on ' ${ server . hostname } ' in ${ convertTimeMsToTimeElapsedString (
weakenTime * 1000 ,
true ,
) } ( t = $ { numeralWrapper . formatThreads ( threads ) } ) ` ,
2021-09-05 01:09:30 +02:00
) ;
2022-05-25 02:16:39 +02:00
return netscriptDelay ( weakenTime * 1000 , workerScript ) . then ( function ( ) {
const host = GetServer ( workerScript . hostname ) ;
if ( host === null ) {
ctx . log ( ( ) = > "Server is null, did it die?" ) ;
return Promise . resolve ( 0 ) ;
}
const coreBonus = 1 + ( host . cpuCores - 1 ) / 16 ;
server . weaken ( CONSTANTS . ServerWeakenAmount * threads * coreBonus ) ;
workerScript . scriptRef . recordWeaken ( server . hostname , threads ) ;
const expGain = calculateHackingExpGain ( server , Player ) * threads ;
ctx . log (
( ) = >
` ' ${ server . hostname } ' security level weakened to ${
server . hackDifficulty
} . Gained $ { numeralWrapper . formatExp ( expGain ) } hacking exp ( t = $ { numeralWrapper . formatThreads ( threads ) } ) ` ,
) ;
workerScript . scriptRef . onlineExpGained += expGain ;
Player . gainHackingExp ( expGain ) ;
return Promise . resolve ( CONSTANTS . ServerWeakenAmount * threads * coreBonus ) ;
} ) ;
} ,
weakenAnalyze :
( ctx : NetscriptContext ) = >
( _threads : unknown , _cores : unknown = 1 ) : number = > {
const threads = ctx . helper . number ( "threads" , _threads ) ;
const cores = ctx . helper . number ( "cores" , _cores ) ;
const coreBonus = 1 + ( cores - 1 ) / 16 ;
return CONSTANTS . ServerWeakenAmount * threads * coreBonus * BitNodeMultipliers . ServerWeakenRate ;
} ,
share : ( ctx : NetscriptContext ) = > async ( ) : Promise < void > = > {
ctx . log ( ( ) = > "Sharing this computer." ) ;
2022-01-18 20:02:12 +01:00
const end = StartSharing ( workerScript . scriptRef . threads * calculateIntelligenceBonus ( Player . intelligence , 2 ) ) ;
return netscriptDelay ( 10000 , workerScript ) . finally ( function ( ) {
2022-05-25 02:16:39 +02:00
ctx . log ( ( ) = > "Finished sharing this computer." ) ;
2022-01-18 20:02:12 +01:00
end ( ) ;
} ) ;
} ,
2022-05-25 02:16:39 +02:00
getSharePower : ( ) = > ( ) : number = > {
2022-01-18 20:02:12 +01:00
return CalculateShareMult ( ) ;
} ,
2022-05-25 02:16:39 +02:00
print :
( ctx : NetscriptContext ) = >
( . . . args : any [ ] ) : void = > {
if ( args . length === 0 ) {
throw ctx . makeRuntimeErrorMsg ( "Takes at least 1 argument." ) ;
}
workerScript . print ( argsToString ( args ) ) ;
} ,
printf :
( ctx : NetscriptContext ) = >
( _format : unknown , . . . args : any [ ] ) : void = > {
const format = ctx . helper . string ( "format" , _format ) ;
if ( typeof format !== "string" ) {
throw ctx . makeRuntimeErrorMsg ( "First argument must be string for the format." ) ;
}
workerScript . print ( vsprintf ( format , args ) ) ;
} ,
tprint :
( ctx : NetscriptContext ) = >
( . . . args : any [ ] ) : void = > {
if ( args . length === 0 ) {
throw ctx . makeRuntimeErrorMsg ( "Takes at least 1 argument." ) ;
}
const str = argsToString ( args ) ;
if ( str . startsWith ( "ERROR" ) || str . startsWith ( "FAIL" ) ) {
Terminal . error ( ` ${ workerScript . scriptRef . filename } : ${ str } ` ) ;
return ;
}
if ( str . startsWith ( "SUCCESS" ) ) {
Terminal . success ( ` ${ workerScript . scriptRef . filename } : ${ str } ` ) ;
return ;
}
if ( str . startsWith ( "WARN" ) ) {
Terminal . warn ( ` ${ workerScript . scriptRef . filename } : ${ str } ` ) ;
return ;
}
if ( str . startsWith ( "INFO" ) ) {
Terminal . info ( ` ${ workerScript . scriptRef . filename } : ${ str } ` ) ;
return ;
}
Terminal . print ( ` ${ workerScript . scriptRef . filename } : ${ str } ` ) ;
} ,
tprintf :
( ctx : NetscriptContext ) = >
( _format : unknown , . . . args : any [ ] ) : void = > {
const format = ctx . helper . string ( "format" , _format ) ;
const str = vsprintf ( format , args ) ;
2021-11-19 21:44:12 +01:00
2022-05-25 02:16:39 +02:00
if ( str . startsWith ( "ERROR" ) || str . startsWith ( "FAIL" ) ) {
Terminal . error ( ` ${ str } ` ) ;
return ;
}
if ( str . startsWith ( "SUCCESS" ) ) {
Terminal . success ( ` ${ str } ` ) ;
return ;
}
if ( str . startsWith ( "WARN" ) ) {
Terminal . warn ( ` ${ str } ` ) ;
return ;
}
if ( str . startsWith ( "INFO" ) ) {
Terminal . info ( ` ${ str } ` ) ;
return ;
}
Terminal . print ( ` ${ str } ` ) ;
} ,
clearLog : ( ) = > ( ) : void = > {
2021-09-05 01:09:30 +02:00
workerScript . scriptRef . clearLog ( ) ;
} ,
2022-05-25 02:16:39 +02:00
disableLog :
( ctx : NetscriptContext ) = >
( _fn : unknown ) : void = > {
const fn = ctx . helper . string ( "fn" , _fn ) ;
if ( fn === "ALL" ) {
for ( const fn of Object . keys ( possibleLogs ) ) {
workerScript . disableLogs [ fn ] = true ;
}
ctx . log ( ( ) = > ` Disabled logging for all functions ` ) ;
} else if ( possibleLogs [ fn ] === undefined ) {
throw ctx . makeRuntimeErrorMsg ( ` Invalid argument: ${ fn } . ` ) ;
} else {
2021-09-05 01:09:30 +02:00
workerScript . disableLogs [ fn ] = true ;
2022-05-25 02:16:39 +02:00
ctx . log ( ( ) = > ` Disabled logging for ${ fn } ` ) ;
}
} ,
enableLog :
( ctx : NetscriptContext ) = >
( _fn : unknown ) : void = > {
const fn = ctx . helper . string ( "fn" , _fn ) ;
if ( fn === "ALL" ) {
for ( const fn of Object . keys ( possibleLogs ) ) {
delete workerScript . disableLogs [ fn ] ;
}
ctx . log ( ( ) = > ` Enabled logging for all functions ` ) ;
} else if ( possibleLogs [ fn ] === undefined ) {
throw ctx . makeRuntimeErrorMsg ( ` Invalid argument: ${ fn } . ` ) ;
}
delete workerScript . disableLogs [ fn ] ;
ctx . log ( ( ) = > ` Enabled logging for ${ fn } ` ) ;
} ,
isLogEnabled :
( ctx : NetscriptContext ) = >
( _fn : unknown ) : boolean = > {
const fn = ctx . helper . string ( "fn" , _fn ) ;
if ( possibleLogs [ fn ] === undefined ) {
throw ctx . makeRuntimeErrorMsg ( ` Invalid argument: ${ fn } . ` ) ;
}
return ! workerScript . disableLogs [ fn ] ;
} ,
getScriptLogs :
( ctx : NetscriptContext ) = >
( fn : any , hostname : any , . . . scriptArgs : any [ ] ) : string [ ] = > {
const runningScriptObj = getRunningScript ( ctx , fn , hostname , scriptArgs ) ;
if ( runningScriptObj == null ) {
ctx . log ( ( ) = > getCannotFindRunningScriptErrorMessage ( fn , hostname , scriptArgs ) ) ;
return [ ] ;
}
return runningScriptObj . logs . slice ( ) ;
} ,
tail :
( ctx : NetscriptContext ) = >
( fn : any , hostname : any = workerScript . hostname , . . . scriptArgs : any [ ] ) : void = > {
let runningScriptObj ;
2022-05-25 17:10:25 +02:00
if ( fn === undefined ) {
2022-05-25 02:16:39 +02:00
runningScriptObj = workerScript . scriptRef ;
} else if ( typeof fn === "number" ) {
runningScriptObj = getRunningScriptByPid ( fn ) ;
} else {
runningScriptObj = getRunningScript ( ctx , fn , hostname , scriptArgs ) ;
}
if ( runningScriptObj == null ) {
ctx . log ( ( ) = > getCannotFindRunningScriptErrorMessage ( fn , hostname , scriptArgs ) ) ;
return ;
2021-04-18 17:18:56 +02:00
}
2019-01-03 09:39:32 +01:00
2022-05-25 02:16:39 +02:00
LogBoxEvents . emit ( runningScriptObj ) ;
} ,
closeTail :
( ctx : NetscriptContext ) = >
( _pid : unknown = workerScript . scriptRef . pid ) : void = > {
const pid = ctx . helper . number ( "pid" , _pid ) ;
//Emit an event to tell the game to close the tail window if it exists
LogBoxCloserEvents . emit ( pid ) ;
} ,
nuke :
( ctx : NetscriptContext ) = >
( _hostname : unknown ) : boolean = > {
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
const server = safeGetServer ( hostname , ctx ) ;
if ( ! ( server instanceof Server ) ) {
ctx . log ( ( ) = > "Cannot be executed on this server." ) ;
return false ;
2021-09-05 01:09:30 +02:00
}
2022-05-25 02:16:39 +02:00
if ( server . hasAdminRights ) {
ctx . log ( ( ) = > ` Already have root access to ' ${ server . hostname } '. ` ) ;
return true ;
2021-09-05 01:09:30 +02:00
}
2022-05-25 02:16:39 +02:00
if ( ! Player . hasProgram ( Programs . NukeProgram . name ) ) {
throw ctx . makeRuntimeErrorMsg ( "You do not have the NUKE.exe virus!" ) ;
2021-09-05 01:09:30 +02:00
}
2022-05-25 02:16:39 +02:00
if ( server . openPortCount < server . numOpenPortsRequired ) {
throw ctx . makeRuntimeErrorMsg ( "Not enough ports opened to use NUKE.exe virus." ) ;
}
server . hasAdminRights = true ;
ctx . log ( ( ) = > ` Executed NUKE.exe virus on ' ${ server . hostname } ' to gain root access. ` ) ;
return true ;
} ,
brutessh :
( ctx : NetscriptContext ) = >
( _hostname : unknown ) : boolean = > {
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
const server = safeGetServer ( hostname , ctx ) ;
if ( ! ( server instanceof Server ) ) {
ctx . log ( ( ) = > "Cannot be executed on this server." ) ;
2021-09-05 01:09:30 +02:00
return false ;
}
2022-05-25 02:16:39 +02:00
if ( ! Player . hasProgram ( Programs . BruteSSHProgram . name ) ) {
throw ctx . makeRuntimeErrorMsg ( "You do not have the BruteSSH.exe program!" ) ;
}
if ( ! server . sshPortOpen ) {
ctx . log ( ( ) = > ` Executed BruteSSH.exe on ' ${ server . hostname } ' to open SSH port (22). ` ) ;
server . sshPortOpen = true ;
++ server . openPortCount ;
2021-09-05 01:09:30 +02:00
} else {
2022-05-25 02:16:39 +02:00
ctx . log ( ( ) = > ` SSH Port (22) already opened on ' ${ server . hostname } '. ` ) ;
2021-09-05 01:09:30 +02:00
}
return true ;
2022-05-25 02:16:39 +02:00
} ,
ftpcrack :
( ctx : NetscriptContext ) = >
( _hostname : unknown ) : boolean = > {
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
if ( hostname === undefined ) {
throw ctx . makeRuntimeErrorMsg ( "Takes 1 argument." ) ;
}
const server = safeGetServer ( hostname , ctx ) ;
if ( ! ( server instanceof Server ) ) {
ctx . log ( ( ) = > "Cannot be executed on this server." ) ;
return false ;
}
if ( ! Player . hasProgram ( Programs . FTPCrackProgram . name ) ) {
throw ctx . makeRuntimeErrorMsg ( "You do not have the FTPCrack.exe program!" ) ;
}
if ( ! server . ftpPortOpen ) {
ctx . log ( ( ) = > ` Executed FTPCrack.exe on ' ${ server . hostname } ' to open FTP port (21). ` ) ;
server . ftpPortOpen = true ;
++ server . openPortCount ;
2021-09-05 01:09:30 +02:00
} else {
2022-05-25 02:16:39 +02:00
ctx . log ( ( ) = > ` FTP Port (21) already opened on ' ${ server . hostname } '. ` ) ;
}
return true ;
} ,
relaysmtp :
( ctx : NetscriptContext ) = >
( _hostname : unknown ) : boolean = > {
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
if ( hostname === undefined ) {
throw ctx . makeRuntimeErrorMsg ( "Takes 1 argument." ) ;
}
const server = safeGetServer ( hostname , ctx ) ;
if ( ! ( server instanceof Server ) ) {
ctx . log ( ( ) = > "Cannot be executed on this server." ) ;
return false ;
}
if ( ! Player . hasProgram ( Programs . RelaySMTPProgram . name ) ) {
throw ctx . makeRuntimeErrorMsg ( "You do not have the relaySMTP.exe program!" ) ;
}
if ( ! server . smtpPortOpen ) {
ctx . log ( ( ) = > ` Executed relaySMTP.exe on ' ${ server . hostname } ' to open SMTP port (25). ` ) ;
server . smtpPortOpen = true ;
++ server . openPortCount ;
} else {
ctx . log ( ( ) = > ` SMTP Port (25) already opened on ' ${ server . hostname } '. ` ) ;
}
return true ;
} ,
httpworm :
( ctx : NetscriptContext ) = >
( _hostname : unknown ) : boolean = > {
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
if ( hostname === undefined ) {
throw ctx . makeRuntimeErrorMsg ( "Takes 1 argument" ) ;
}
const server = safeGetServer ( hostname , ctx ) ;
if ( ! ( server instanceof Server ) ) {
ctx . log ( ( ) = > "Cannot be executed on this server." ) ;
return false ;
}
if ( ! Player . hasProgram ( Programs . HTTPWormProgram . name ) ) {
throw ctx . makeRuntimeErrorMsg ( "You do not have the HTTPWorm.exe program!" ) ;
}
if ( ! server . httpPortOpen ) {
ctx . log ( ( ) = > ` Executed HTTPWorm.exe on ' ${ server . hostname } ' to open HTTP port (80). ` ) ;
server . httpPortOpen = true ;
++ server . openPortCount ;
} else {
ctx . log ( ( ) = > ` HTTP Port (80) already opened on ' ${ server . hostname } '. ` ) ;
}
return true ;
} ,
sqlinject :
( ctx : NetscriptContext ) = >
( _hostname : unknown ) : boolean = > {
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
if ( hostname === undefined ) {
throw ctx . makeRuntimeErrorMsg ( "Takes 1 argument." ) ;
}
const server = safeGetServer ( hostname , ctx ) ;
if ( ! ( server instanceof Server ) ) {
ctx . log ( ( ) = > "Cannot be executed on this server." ) ;
return false ;
}
if ( ! Player . hasProgram ( Programs . SQLInjectProgram . name ) ) {
throw ctx . makeRuntimeErrorMsg ( "You do not have the SQLInject.exe program!" ) ;
}
if ( ! server . sqlPortOpen ) {
ctx . log ( ( ) = > ` Executed SQLInject.exe on ' ${ server . hostname } ' to open SQL port (1433). ` ) ;
server . sqlPortOpen = true ;
++ server . openPortCount ;
} else {
ctx . log ( ( ) = > ` SQL Port (1433) already opened on ' ${ server . hostname } '. ` ) ;
}
return true ;
} ,
run :
( ctx : NetscriptContext ) = >
( _scriptname : unknown , _threads : unknown = 1 , . . . args : any [ ] ) : number = > {
const scriptname = ctx . helper . string ( "scriptname" , _scriptname ) ;
const threads = ctx . helper . number ( "threads" , _threads ) ;
if ( scriptname === undefined ) {
throw ctx . makeRuntimeErrorMsg ( "Usage: run(scriptname, [numThreads], [arg1], [arg2]...)" ) ;
}
if ( isNaN ( threads ) || threads <= 0 ) {
throw ctx . makeRuntimeErrorMsg ( ` Invalid thread count. Must be numeric and > 0, is ${ threads } ` ) ;
}
const scriptServer = GetServer ( workerScript . hostname ) ;
if ( scriptServer == null ) {
throw ctx . makeRuntimeErrorMsg ( "Could not find server. This is a bug. Report to dev." ) ;
2021-09-05 01:09:30 +02:00
}
2022-05-04 17:11:08 +02:00
2022-05-25 02:16:39 +02:00
return runScriptFromScript ( Player , "run" , scriptServer , scriptname , args , workerScript , threads ) ;
} ,
exec :
( ctx : NetscriptContext ) = >
( _scriptname : unknown , _hostname : unknown , _threads : unknown = 1 , . . . args : any [ ] ) : number = > {
const scriptname = ctx . helper . string ( "scriptname" , _scriptname ) ;
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
const threads = ctx . helper . number ( "threads" , _threads ) ;
if ( scriptname === undefined || hostname === undefined ) {
throw ctx . makeRuntimeErrorMsg ( "Usage: exec(scriptname, server, [numThreads], [arg1], [arg2]...)" ) ;
}
if ( isNaN ( threads ) || threads <= 0 ) {
throw ctx . makeRuntimeErrorMsg ( ` Invalid thread count. Must be numeric and > 0, is ${ threads } ` ) ;
}
const server = safeGetServer ( hostname , ctx ) ;
return runScriptFromScript ( Player , "exec" , server , scriptname , args , workerScript , threads ) ;
} ,
spawn :
( ctx : NetscriptContext ) = >
( _scriptname : unknown , _threads : unknown = 1 , . . . args : any [ ] ) : void = > {
const scriptname = ctx . helper . string ( "scriptname" , _scriptname ) ;
const threads = ctx . helper . number ( "threads" , _threads ) ;
if ( ! scriptname || ! threads ) {
throw ctx . makeRuntimeErrorMsg ( "Usage: spawn(scriptname, threads)" ) ;
}
const spawnDelay = 10 ;
setTimeout ( ( ) = > {
if ( isNaN ( threads ) || threads <= 0 ) {
throw ctx . makeRuntimeErrorMsg ( ` Invalid thread count. Must be numeric and > 0, is ${ threads } ` ) ;
}
const scriptServer = GetServer ( workerScript . hostname ) ;
if ( scriptServer == null ) {
throw ctx . makeRuntimeErrorMsg ( "Could not find server. This is a bug. Report to dev" ) ;
}
2022-05-04 17:11:08 +02:00
2022-05-25 02:16:39 +02:00
return runScriptFromScript ( Player , "spawn" , scriptServer , scriptname , args , workerScript , threads ) ;
} , spawnDelay * 1 e3 ) ;
2021-09-05 01:09:30 +02:00
2022-05-25 02:16:39 +02:00
ctx . log ( ( ) = > ` Will execute ' ${ scriptname } ' in ${ spawnDelay } seconds ` ) ;
2019-01-03 09:39:32 +01:00
2022-05-25 02:16:39 +02:00
workerScript . running = false ; // Prevent workerScript from "finishing execution naturally"
if ( killWorkerScript ( workerScript ) ) {
ctx . log ( ( ) = > "Exiting..." ) ;
}
} ,
kill :
( ctx : NetscriptContext ) = >
( filename : any , hostname? : any , . . . scriptArgs : any [ ] ) : boolean = > {
let res ;
const killByPid = typeof filename === "number" ;
if ( killByPid ) {
// Kill by pid
res = killWorkerScript ( filename ) ;
} else {
// Kill by filename/hostname
if ( filename === undefined || hostname === undefined ) {
throw ctx . makeRuntimeErrorMsg ( "Usage: kill(scriptname, server, [arg1], [arg2]...)" ) ;
}
2019-01-03 09:39:32 +01:00
2022-05-25 02:16:39 +02:00
const server = safeGetServer ( hostname , ctx ) ;
const runningScriptObj = getRunningScript ( ctx , filename , hostname , scriptArgs ) ;
if ( runningScriptObj == null ) {
ctx . log ( ( ) = > getCannotFindRunningScriptErrorMessage ( filename , hostname , scriptArgs ) ) ;
return false ;
}
2017-07-25 03:06:40 +02:00
2022-05-25 02:16:39 +02:00
res = killWorkerScript ( runningScriptObj , server . hostname ) ;
}
2021-08-19 22:37:59 +02:00
2022-05-25 02:16:39 +02:00
if ( res ) {
if ( killByPid ) {
ctx . log ( ( ) = > ` Killing script with PID ${ filename } ` ) ;
} else {
ctx . log ( ( ) = > ` Killing ' ${ filename } ' on ' ${ hostname } ' with args: ${ arrayToString ( scriptArgs ) } . ` ) ;
}
return true ;
} else {
if ( killByPid ) {
ctx . log ( ( ) = > ` No script with PID ${ filename } ` ) ;
} else {
ctx . log ( ( ) = > ` No such script ' ${ filename } ' on ' ${ hostname } ' with args: ${ arrayToString ( scriptArgs ) } ` ) ;
}
return false ;
2021-09-05 01:09:30 +02:00
}
2022-05-25 02:16:39 +02:00
} ,
killall :
( ctx : NetscriptContext ) = >
( _hostname : unknown = workerScript . hostname , _safetyguard : unknown = true ) : boolean = > {
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
const safetyguard = helper . boolean ( _safetyguard ) ;
if ( hostname === undefined ) {
throw ctx . makeRuntimeErrorMsg ( "Usage: killall(hostname, [safetyguard boolean])" ) ;
2021-09-05 01:09:30 +02:00
}
2022-05-25 02:16:39 +02:00
const server = safeGetServer ( hostname , ctx ) ;
let scriptsKilled = 0 ;
for ( let i = server . runningScripts . length - 1 ; i >= 0 ; -- i ) {
if ( safetyguard === true && server . runningScripts [ i ] . pid == workerScript . pid ) continue ;
killWorkerScript ( server . runningScripts [ i ] , server . hostname , false ) ;
++ scriptsKilled ;
2021-09-05 01:09:30 +02:00
}
2022-05-25 02:16:39 +02:00
WorkerScriptStartStopEventEmitter . emit ( ) ;
ctx . log ( ( ) = > ` Killing all scripts on ' ${ server . hostname } '. May take a few minutes for the scripts to die. ` ) ;
return scriptsKilled > 0 ;
} ,
exit : ( ctx : NetscriptContext ) = > ( ) : void = > {
workerScript . running = false ; // Prevent workerScript from "finishing execution naturally"
if ( killWorkerScript ( workerScript ) ) {
ctx . log ( ( ) = > "Exiting..." ) ;
2021-09-05 01:09:30 +02:00
} else {
2022-05-25 02:16:39 +02:00
ctx . log ( ( ) = > "Failed. This is a bug. Report to dev." ) ;
2021-09-05 01:09:30 +02:00
}
2022-05-25 02:16:39 +02:00
} ,
scp :
( ctx : NetscriptContext ) = >
async ( scriptname : any , _hostname1 : unknown , hostname2? : any ) : Promise < boolean > = > {
const hostname1 = ctx . helper . string ( "hostname1" , _hostname1 ) ;
if ( scriptname && scriptname . constructor === Array ) {
// Recursively call scp on all elements of array
2022-05-25 17:10:25 +02:00
const scripts : string [ ] = scriptname ;
2022-05-25 02:16:39 +02:00
if ( scripts . length === 0 ) {
throw ctx . makeRuntimeErrorMsg ( "No scripts to copy" ) ;
2021-09-05 01:09:30 +02:00
}
2022-05-25 02:16:39 +02:00
let res = true ;
await Promise . all (
scripts . map ( async function ( script ) {
if ( ! ( await NetscriptFunctions ( workerScript ) . scp ( script , hostname1 , hostname2 ) ) ) {
res = false ;
}
} ) ,
) ;
return Promise . resolve ( res ) ;
2021-09-05 01:09:30 +02:00
}
2017-07-25 03:06:40 +02:00
2022-05-25 02:16:39 +02:00
// Invalid file type
if ( ! isValidFilePath ( scriptname ) ) {
throw ctx . makeRuntimeErrorMsg ( ` Invalid filename: ' ${ scriptname } ' ` ) ;
2021-09-05 01:09:30 +02:00
}
2017-07-25 03:06:40 +02:00
2022-05-25 02:16:39 +02:00
// Invalid file name
if ( ! scriptname . endsWith ( ".lit" ) && ! isScriptFilename ( scriptname ) && ! scriptname . endsWith ( "txt" ) ) {
throw ctx . makeRuntimeErrorMsg ( "Only works for scripts, .lit and .txt files" ) ;
2021-09-05 01:09:30 +02:00
}
2017-09-07 07:45:14 +02:00
2022-05-25 02:16:39 +02:00
let destServer : BaseServer | null ;
let currServ : BaseServer | null ;
if ( hostname2 != null ) {
// 3 Argument version: scriptname, source, destination
if ( scriptname === undefined || hostname1 === undefined || hostname2 === undefined ) {
throw ctx . makeRuntimeErrorMsg ( "Takes 2 or 3 arguments" ) ;
2021-09-05 01:09:30 +02:00
}
2022-05-25 02:16:39 +02:00
destServer = safeGetServer ( hostname2 , ctx ) ;
currServ = safeGetServer ( hostname1 , ctx ) ;
} else if ( hostname1 != null ) {
// 2 Argument version: scriptname, destination
if ( scriptname === undefined || hostname1 === undefined ) {
throw ctx . makeRuntimeErrorMsg ( "Takes 2 or 3 arguments" ) ;
}
destServer = safeGetServer ( hostname1 , ctx ) ;
currServ = GetServer ( workerScript . hostname ) ;
if ( currServ == null ) {
throw ctx . makeRuntimeErrorMsg (
"Could not find server hostname for this script. This is a bug. Report to dev." ,
) ;
}
} else {
throw ctx . makeRuntimeErrorMsg ( "Takes 2 or 3 arguments" ) ;
2021-09-05 01:09:30 +02:00
}
2017-07-25 03:06:40 +02:00
2022-05-25 02:16:39 +02:00
// Scp for lit files
if ( scriptname . endsWith ( ".lit" ) ) {
let found = false ;
for ( let i = 0 ; i < currServ . messages . length ; ++ i ) {
if ( currServ . messages [ i ] == scriptname ) {
found = true ;
break ;
}
}
if ( ! found ) {
ctx . log ( ( ) = > ` File ' ${ scriptname } ' does not exist. ` ) ;
return Promise . resolve ( false ) ;
2021-09-05 01:09:30 +02:00
}
2018-09-23 02:25:48 +02:00
2022-05-25 02:16:39 +02:00
for ( let i = 0 ; i < destServer . messages . length ; ++ i ) {
if ( destServer . messages [ i ] === scriptname ) {
ctx . log ( ( ) = > ` File ' ${ scriptname } ' copied over to ' ${ destServer ? . hostname } '. ` ) ;
return Promise . resolve ( true ) ; // Already exists
}
}
destServer . messages . push ( scriptname ) ;
ctx . log ( ( ) = > ` File ' ${ scriptname } ' copied over to ' ${ destServer ? . hostname } '. ` ) ;
return Promise . resolve ( true ) ;
2021-09-05 01:09:30 +02:00
}
2019-04-29 08:20:27 +02:00
2022-05-25 02:16:39 +02:00
// Scp for text files
if ( scriptname . endsWith ( ".txt" ) ) {
let txtFile ;
for ( let i = 0 ; i < currServ . textFiles . length ; ++ i ) {
if ( currServ . textFiles [ i ] . fn === scriptname ) {
txtFile = currServ . textFiles [ i ] ;
break ;
}
}
if ( txtFile === undefined ) {
ctx . log ( ( ) = > ` File ' ${ scriptname } ' does not exist. ` ) ;
return Promise . resolve ( false ) ;
}
for ( let i = 0 ; i < destServer . textFiles . length ; ++ i ) {
if ( destServer . textFiles [ i ] . fn === scriptname ) {
// Overwrite
destServer . textFiles [ i ] . text = txtFile . text ;
ctx . log ( ( ) = > ` File ' ${ scriptname } ' copied over to ' ${ destServer ? . hostname } '. ` ) ;
return Promise . resolve ( true ) ;
}
}
const newFile = new TextFile ( txtFile . fn , txtFile . text ) ;
destServer . textFiles . push ( newFile ) ;
ctx . log ( ( ) = > ` File ' ${ scriptname } ' copied over to ' ${ destServer ? . hostname } '. ` ) ;
2021-11-03 03:11:22 +01:00
return Promise . resolve ( true ) ;
2021-09-05 01:09:30 +02:00
}
2019-04-29 08:20:27 +02:00
2022-05-25 02:16:39 +02:00
// Scp for script files
let sourceScript = null ;
for ( let i = 0 ; i < currServ . scripts . length ; ++ i ) {
if ( scriptname == currServ . scripts [ i ] . filename ) {
sourceScript = currServ . scripts [ i ] ;
break ;
}
}
if ( sourceScript == null ) {
ctx . log ( ( ) = > ` File ' ${ scriptname } ' does not exist. ` ) ;
return Promise . resolve ( false ) ;
2021-11-10 13:52:26 +01:00
}
2019-04-29 08:20:27 +02:00
2022-05-25 02:16:39 +02:00
// Overwrite script if it already exists
for ( let i = 0 ; i < destServer . scripts . length ; ++ i ) {
if ( scriptname == destServer . scripts [ i ] . filename ) {
ctx . log ( ( ) = > ` WARNING: File ' ${ scriptname } ' overwritten on ' ${ destServer ? . hostname } ' ` ) ;
const oldScript = destServer . scripts [ i ] ;
// If it's the exact same file don't actually perform the
// copy to avoid recompiling uselessly. Players tend to scp
// liberally.
if ( oldScript . code === sourceScript . code ) return Promise . resolve ( true ) ;
oldScript . code = sourceScript . code ;
oldScript . ramUsage = sourceScript . ramUsage ;
oldScript . markUpdated ( ) ;
return Promise . resolve ( true ) ;
}
}
2019-01-09 11:06:49 +01:00
2022-05-25 02:16:39 +02:00
// Create new script if it does not already exist
const newScript = new Script ( Player , scriptname ) ;
newScript . code = sourceScript . code ;
newScript . ramUsage = sourceScript . ramUsage ;
newScript . server = destServer . hostname ;
destServer . scripts . push ( newScript ) ;
ctx . log ( ( ) = > ` File ' ${ scriptname } ' copied over to ' ${ destServer ? . hostname } '. ` ) ;
return new Promise ( ( resolve ) = > {
if ( destServer === null ) {
resolve ( false ) ;
return ;
}
newScript . updateRamUsage ( Player , destServer . scripts ) . then ( ( ) = > resolve ( true ) ) ;
} ) ;
} ,
ls :
( ctx : NetscriptContext ) = >
( _hostname : unknown , _grep : unknown = "" ) : string [ ] = > {
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
const grep = ctx . helper . string ( "grep" , _grep ) ;
const server = safeGetServer ( hostname , ctx ) ;
// Get the grep filter, if one exists
let filter = "" ;
2022-05-25 17:10:25 +02:00
if ( _grep !== undefined ) {
2022-05-25 02:16:39 +02:00
filter = grep . toString ( ) ;
}
const allFiles = [ ] ;
for ( let i = 0 ; i < server . programs . length ; i ++ ) {
if ( filter ) {
if ( server . programs [ i ] . includes ( filter ) ) {
allFiles . push ( server . programs [ i ] ) ;
}
} else {
2021-09-05 01:09:30 +02:00
allFiles . push ( server . programs [ i ] ) ;
}
}
2022-05-25 02:16:39 +02:00
for ( let i = 0 ; i < server . scripts . length ; i ++ ) {
if ( filter ) {
if ( server . scripts [ i ] . filename . includes ( filter ) ) {
allFiles . push ( server . scripts [ i ] . filename ) ;
}
} else {
2021-09-05 01:09:30 +02:00
allFiles . push ( server . scripts [ i ] . filename ) ;
}
}
2022-05-25 02:16:39 +02:00
for ( let i = 0 ; i < server . messages . length ; i ++ ) {
if ( filter ) {
const msg = server . messages [ i ] ;
if ( msg . includes ( filter ) ) {
allFiles . push ( msg ) ;
}
} else {
allFiles . push ( server . messages [ i ] ) ;
2021-09-05 01:09:30 +02:00
}
}
2019-06-03 05:28:02 +02:00
2022-05-25 02:16:39 +02:00
for ( let i = 0 ; i < server . textFiles . length ; i ++ ) {
if ( filter ) {
if ( server . textFiles [ i ] . fn . includes ( filter ) ) {
allFiles . push ( server . textFiles [ i ] . fn ) ;
}
} else {
2021-09-05 01:09:30 +02:00
allFiles . push ( server . textFiles [ i ] . fn ) ;
}
}
2019-06-03 05:28:02 +02:00
2022-05-25 02:16:39 +02:00
for ( let i = 0 ; i < server . contracts . length ; ++ i ) {
if ( filter ) {
if ( server . contracts [ i ] . fn . includes ( filter ) ) {
allFiles . push ( server . contracts [ i ] . fn ) ;
}
} else {
2021-09-05 01:09:30 +02:00
allFiles . push ( server . contracts [ i ] . fn ) ;
}
}
2019-06-03 05:28:02 +02:00
2022-05-25 02:16:39 +02:00
// Sort the files alphabetically then print each
allFiles . sort ( ) ;
return allFiles ;
} ,
getRecentScripts : ( ) = > ( ) : IRecentScript [ ] = > {
2022-04-12 20:45:48 +02:00
return recentScripts . map ( ( rs ) = > ( {
timeOfDeath : rs.timeOfDeath ,
. . . createPublicRunningScript ( rs . runningScript ) ,
} ) ) ;
2022-01-19 08:04:48 +01:00
} ,
2022-05-25 02:16:39 +02:00
ps :
( ctx : NetscriptContext ) = >
( _hostname : unknown = workerScript . hostname ) : ProcessInfo [ ] = > {
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
const server = safeGetServer ( hostname , ctx ) ;
const processes = [ ] ;
for ( const script of server . runningScripts ) {
processes . push ( {
filename : script.filename ,
threads : script.threads ,
args : script.args.slice ( ) ,
pid : script.pid ,
} ) ;
}
return processes ;
} ,
hasRootAccess :
( ctx : NetscriptContext ) = >
( _hostname : unknown ) : boolean = > {
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
const server = safeGetServer ( hostname , ctx ) ;
return server . hasAdminRights ;
} ,
getHostname : ( ctx : NetscriptContext ) = > ( ) : string = > {
2021-10-07 23:55:49 +02:00
const scriptServer = GetServer ( workerScript . hostname ) ;
2021-09-05 01:09:30 +02:00
if ( scriptServer == null ) {
2022-05-25 02:16:39 +02:00
throw ctx . makeRuntimeErrorMsg ( "Could not find server. This is a bug. Report to dev." ) ;
2021-09-05 01:09:30 +02:00
}
return scriptServer . hostname ;
} ,
2022-05-25 02:16:39 +02:00
getHackingLevel : ( ctx : NetscriptContext ) = > ( ) : number = > {
2021-09-05 01:09:30 +02:00
Player . updateSkillLevels ( ) ;
2022-05-25 02:16:39 +02:00
ctx . log ( ( ) = > ` returned ${ Player . hacking } ` ) ;
2021-11-05 22:12:52 +01:00
return Player . hacking ;
2021-09-05 01:09:30 +02:00
} ,
2022-05-25 02:16:39 +02:00
getHackingMultipliers : ( ) = > ( ) : HackingMultipliers = > {
2021-09-05 01:09:30 +02:00
return {
2022-07-15 00:43:33 +02:00
chance : Player.mults.hacking_chance ,
speed : Player.mults.hacking_speed ,
money : Player.mults.hacking_money ,
growth : Player.mults.hacking_grow ,
2021-09-05 01:09:30 +02:00
} ;
} ,
2022-05-25 02:16:39 +02:00
getHacknetMultipliers : ( ) = > ( ) : HacknetMultipliers = > {
2021-09-05 01:09:30 +02:00
return {
2022-07-15 00:43:33 +02:00
production : Player.mults.hacknet_node_money ,
purchaseCost : Player.mults.hacknet_node_purchase_cost ,
ramCost : Player.mults.hacknet_node_ram_cost ,
coreCost : Player.mults.hacknet_node_core_cost ,
levelCost : Player.mults.hacknet_node_level_cost ,
2021-09-05 01:09:30 +02:00
} ;
} ,
2022-05-25 02:16:39 +02:00
getBitNodeMultipliers : ( ctx : NetscriptContext ) = > ( ) : IBNMults = > {
2022-04-14 07:22:50 +02:00
if ( Player . sourceFileLvl ( 5 ) <= 0 && Player . bitNodeN !== 5 ) {
2022-05-25 02:16:39 +02:00
throw ctx . makeRuntimeErrorMsg ( "Requires Source-File 5 to run." ) ;
2021-09-05 01:09:30 +02:00
}
2021-09-25 07:26:03 +02:00
const copy = Object . assign ( { } , BitNodeMultipliers ) ;
2021-09-05 01:09:30 +02:00
return copy ;
} ,
2022-05-25 02:16:39 +02:00
getServer :
( ctx : NetscriptContext ) = >
( _hostname : unknown = workerScript . hostname ) : IServerDef = > {
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
const server = safeGetServer ( hostname , ctx ) ;
const copy = Object . assign ( { } , server ) as any ;
// These fields should be hidden.
copy . contracts = undefined ;
copy . messages = undefined ;
copy . runningScripts = undefined ;
copy . scripts = undefined ;
copy . textFiles = undefined ;
copy . programs = undefined ;
copy . serversOnNetwork = undefined ;
if ( ! copy . baseDifficulty ) copy . baseDifficulty = 0 ;
if ( ! copy . hackDifficulty ) copy . hackDifficulty = 0 ;
if ( ! copy . minDifficulty ) copy . minDifficulty = 0 ;
if ( ! copy . moneyAvailable ) copy . moneyAvailable = 0 ;
if ( ! copy . moneyMax ) copy . moneyMax = 0 ;
if ( ! copy . numOpenPortsRequired ) copy . numOpenPortsRequired = 0 ;
if ( ! copy . openPortCount ) copy . openPortCount = 0 ;
if ( ! copy . requiredHackingSkill ) copy . requiredHackingSkill = 0 ;
if ( ! copy . serverGrowth ) copy . serverGrowth = 0 ;
return copy ;
} ,
getServerMoneyAvailable :
( ctx : NetscriptContext ) = >
( _hostname : unknown ) : number = > {
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
const server = safeGetServer ( hostname , ctx ) ;
if ( ! ( server instanceof Server ) ) {
ctx . log ( ( ) = > "Cannot be executed on this server." ) ;
return 0 ;
}
if ( failOnHacknetServer ( server , "getServerMoneyAvailable" ) ) {
return 0 ;
}
if ( server . hostname == "home" ) {
// Return player's money
ctx . log ( ( ) = > ` returned player's money: ${ numeralWrapper . formatMoney ( Player . money ) } ` ) ;
return Player . money ;
}
ctx . log ( ( ) = > ` returned ${ numeralWrapper . formatMoney ( server . moneyAvailable ) } for ' ${ server . hostname } ' ` ) ;
return server . moneyAvailable ;
} ,
getServerSecurityLevel :
( ctx : NetscriptContext ) = >
( _hostname : unknown ) : number = > {
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
const server = safeGetServer ( hostname , ctx ) ;
if ( ! ( server instanceof Server ) ) {
ctx . log ( ( ) = > "Cannot be executed on this server." ) ;
return 1 ;
}
if ( failOnHacknetServer ( server , "getServerSecurityLevel" ) ) {
return 1 ;
}
ctx . log (
( ) = > ` returned ${ numeralWrapper . formatServerSecurity ( server . hackDifficulty ) } for ' ${ server . hostname } ' ` ,
2021-09-05 01:09:30 +02:00
) ;
2022-05-25 02:16:39 +02:00
return server . hackDifficulty ;
} ,
getServerBaseSecurityLevel :
( ctx : NetscriptContext ) = >
( _hostname : unknown ) : number = > {
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
ctx . log ( ( ) = > ` getServerBaseSecurityLevel is deprecated because it's not useful. ` ) ;
const server = safeGetServer ( hostname , ctx ) ;
if ( ! ( server instanceof Server ) ) {
ctx . log ( ( ) = > "Cannot be executed on this server." ) ;
return 1 ;
2021-09-05 01:09:30 +02:00
}
2022-05-25 02:16:39 +02:00
if ( failOnHacknetServer ( server , "getServerBaseSecurityLevel" ) ) {
return 1 ;
2021-09-05 01:09:30 +02:00
}
2022-05-25 02:16:39 +02:00
ctx . log (
( ) = > ` returned ${ numeralWrapper . formatServerSecurity ( server . baseDifficulty ) } for ' ${ server . hostname } ' ` ,
) ;
return server . baseDifficulty ;
} ,
getServerMinSecurityLevel :
( ctx : NetscriptContext ) = >
( _hostname : unknown ) : number = > {
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
const server = safeGetServer ( hostname , ctx ) ;
if ( ! ( server instanceof Server ) ) {
ctx . log ( ( ) = > "Cannot be executed on this server." ) ;
return 1 ;
}
if ( failOnHacknetServer ( server , "getServerMinSecurityLevel" ) ) {
return 1 ;
}
ctx . log ( ( ) = > ` returned ${ numeralWrapper . formatServerSecurity ( server . minDifficulty ) } for ${ server . hostname } ` ) ;
return server . minDifficulty ;
} ,
getServerRequiredHackingLevel :
( ctx : NetscriptContext ) = >
( _hostname : unknown ) : number = > {
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
const server = safeGetServer ( hostname , ctx ) ;
if ( ! ( server instanceof Server ) ) {
ctx . log ( ( ) = > "Cannot be executed on this server." ) ;
return 1 ;
}
if ( failOnHacknetServer ( server , "getServerRequiredHackingLevel" ) ) {
return 1 ;
}
ctx . log ( ( ) = > ` returned ${ numeralWrapper . formatSkill ( server . requiredHackingSkill ) } for ' ${ server . hostname } ' ` ) ;
return server . requiredHackingSkill ;
} ,
getServerMaxMoney :
( ctx : NetscriptContext ) = >
( _hostname : unknown ) : number = > {
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
const server = safeGetServer ( hostname , ctx ) ;
if ( ! ( server instanceof Server ) ) {
ctx . log ( ( ) = > "Cannot be executed on this server." ) ;
return 0 ;
2021-09-05 01:09:30 +02:00
}
2022-05-25 02:16:39 +02:00
if ( failOnHacknetServer ( server , "getServerMaxMoney" ) ) {
return 0 ;
}
ctx . log ( ( ) = > ` returned ${ numeralWrapper . formatMoney ( server . moneyMax ) } for ' ${ server . hostname } ' ` ) ;
return server . moneyMax ;
} ,
getServerGrowth :
( ctx : NetscriptContext ) = >
( _hostname : unknown ) : number = > {
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
const server = safeGetServer ( hostname , ctx ) ;
if ( ! ( server instanceof Server ) ) {
ctx . log ( ( ) = > "Cannot be executed on this server." ) ;
return 1 ;
}
if ( failOnHacknetServer ( server , "getServerGrowth" ) ) {
return 1 ;
}
ctx . log ( ( ) = > ` returned ${ server . serverGrowth } for ' ${ server . hostname } ' ` ) ;
return server . serverGrowth ;
} ,
getServerNumPortsRequired :
( ctx : NetscriptContext ) = >
( _hostname : unknown ) : number = > {
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
const server = safeGetServer ( hostname , ctx ) ;
if ( ! ( server instanceof Server ) ) {
ctx . log ( ( ) = > "Cannot be executed on this server." ) ;
return 5 ;
}
if ( failOnHacknetServer ( server , "getServerNumPortsRequired" ) ) {
return 5 ;
}
ctx . log ( ( ) = > ` returned ${ server . numOpenPortsRequired } for ' ${ server . hostname } ' ` ) ;
return server . numOpenPortsRequired ;
} ,
getServerRam :
( ctx : NetscriptContext ) = >
( _hostname : unknown ) : [ number , number ] = > {
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
ctx . log ( ( ) = > ` getServerRam is deprecated in favor of getServerMaxRam / getServerUsedRam ` ) ;
const server = safeGetServer ( hostname , ctx ) ;
ctx . log (
( ) = > ` returned [ ${ numeralWrapper . formatRAM ( server . maxRam ) } , ${ numeralWrapper . formatRAM ( server . ramUsed ) } ] ` ,
) ;
return [ server . maxRam , server . ramUsed ] ;
} ,
getServerMaxRam :
( ctx : NetscriptContext ) = >
( _hostname : unknown ) : number = > {
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
const server = safeGetServer ( hostname , ctx ) ;
ctx . log ( ( ) = > ` returned ${ numeralWrapper . formatRAM ( server . maxRam ) } ` ) ;
return server . maxRam ;
} ,
getServerUsedRam :
( ctx : NetscriptContext ) = >
( _hostname : unknown ) : number = > {
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
const server = safeGetServer ( hostname , ctx ) ;
ctx . log ( ( ) = > ` returned ${ numeralWrapper . formatRAM ( server . ramUsed ) } ` ) ;
return server . ramUsed ;
} ,
serverExists :
( ctx : NetscriptContext ) = >
( _hostname : unknown ) : boolean = > {
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
return GetServer ( hostname ) !== null ;
} ,
fileExists :
( ctx : NetscriptContext ) = >
( _filename : unknown , _hostname : unknown = workerScript . hostname ) : boolean = > {
const filename = ctx . helper . string ( "filename" , _filename ) ;
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
if ( filename === undefined ) {
throw ctx . makeRuntimeErrorMsg ( "Usage: fileExists(scriptname, [server])" ) ;
}
const server = safeGetServer ( hostname , ctx ) ;
for ( let i = 0 ; i < server . scripts . length ; ++ i ) {
if ( filename == server . scripts [ i ] . filename ) {
return true ;
}
}
for ( let i = 0 ; i < server . programs . length ; ++ i ) {
if ( filename . toLowerCase ( ) == server . programs [ i ] . toLowerCase ( ) ) {
return true ;
}
}
for ( let i = 0 ; i < server . messages . length ; ++ i ) {
if ( filename . toLowerCase ( ) === server . messages [ i ] . toLowerCase ( ) ) {
return true ;
}
}
const txtFile = getTextFile ( filename , server ) ;
return txtFile != null ;
} ,
isRunning :
( ctx : NetscriptContext ) = >
( fn : any , hostname : any = workerScript . hostname , . . . scriptArgs : any [ ] ) : boolean = > {
if ( fn === undefined || hostname === undefined ) {
throw ctx . makeRuntimeErrorMsg ( "Usage: isRunning(scriptname, server, [arg1], [arg2]...)" ) ;
}
if ( typeof fn === "number" ) {
return getRunningScriptByPid ( fn ) != null ;
} else {
return getRunningScript ( ctx , fn , hostname , scriptArgs ) != null ;
}
} ,
getPurchasedServerLimit : ( ) = > ( ) : number = > {
2021-09-05 01:09:30 +02:00
return getPurchaseServerLimit ( ) ;
} ,
2022-05-25 02:16:39 +02:00
getPurchasedServerMaxRam : ( ) = > ( ) : number = > {
2021-09-05 01:09:30 +02:00
return getPurchaseServerMaxRam ( ) ;
} ,
2022-05-25 02:16:39 +02:00
getPurchasedServerCost :
( ctx : NetscriptContext ) = >
( _ram : unknown ) : number = > {
const ram = ctx . helper . number ( "ram" , _ram ) ;
const cost = getPurchaseServerCost ( ram ) ;
if ( cost === Infinity ) {
ctx . log ( ( ) = > ` Invalid argument: ram=' ${ ram } ' ` ) ;
return Infinity ;
}
return cost ;
} ,
purchaseServer :
( ctx : NetscriptContext ) = >
( _name : unknown , _ram : unknown ) : string = > {
const name = ctx . helper . string ( "name" , _name ) ;
const ram = ctx . helper . number ( "ram" , _ram ) ;
let hostnameStr = String ( name ) ;
hostnameStr = hostnameStr . replace ( /\s+/g , "" ) ;
if ( hostnameStr == "" ) {
ctx . log ( ( ) = > ` Invalid argument: hostname=' ${ hostnameStr } ' ` ) ;
return "" ;
}
if ( Player . purchasedServers . length >= getPurchaseServerLimit ( ) ) {
ctx . log (
( ) = >
` You have reached the maximum limit of ${ getPurchaseServerLimit ( ) } servers. You cannot purchase any more. ` ,
2022-03-17 00:33:45 +01:00
) ;
2022-05-25 02:16:39 +02:00
return "" ;
2022-01-19 19:09:33 +01:00
}
2022-01-30 15:06:18 +01:00
2022-05-25 02:16:39 +02:00
const cost = getPurchaseServerCost ( ram ) ;
if ( cost === Infinity ) {
if ( ram > getPurchaseServerMaxRam ( ) ) {
ctx . log ( ( ) = > ` Invalid argument: ram=' ${ ram } ' must not be greater than getPurchaseServerMaxRam ` ) ;
} else {
ctx . log ( ( ) = > ` Invalid argument: ram=' ${ ram } ' must be a positive power of 2 ` ) ;
}
2018-11-01 19:18:32 +01:00
2022-05-25 02:16:39 +02:00
return "" ;
}
if ( Player . money < cost ) {
ctx . log ( ( ) = > ` Not enough money to purchase server. Need ${ numeralWrapper . formatMoney ( cost ) } ` ) ;
return "" ;
}
const newServ = safetlyCreateUniqueServer ( {
ip : createUniqueRandomIp ( ) ,
hostname : hostnameStr ,
organizationName : "" ,
isConnectedTo : false ,
adminRights : true ,
purchasedByPlayer : true ,
maxRam : ram ,
} ) ;
AddToAllServers ( newServ ) ;
Player . purchasedServers . push ( newServ . hostname ) ;
const homeComputer = Player . getHomeComputer ( ) ;
homeComputer . serversOnNetwork . push ( newServ . hostname ) ;
newServ . serversOnNetwork . push ( homeComputer . hostname ) ;
Player . loseMoney ( cost , "servers" ) ;
ctx . log (
( ) = > ` Purchased new server with hostname ' ${ newServ . hostname } ' for ${ numeralWrapper . formatMoney ( cost ) } ` ,
2021-09-05 01:09:30 +02:00
) ;
2022-05-25 02:16:39 +02:00
return newServ . hostname ;
} ,
deleteServer :
( ctx : NetscriptContext ) = >
( _name : unknown ) : boolean = > {
const name = ctx . helper . string ( "name" , _name ) ;
let hostnameStr = String ( name ) ;
hostnameStr = hostnameStr . replace ( /\s\s+/g , "" ) ;
const server = GetServer ( hostnameStr ) ;
if ( ! ( server instanceof Server ) ) {
ctx . log ( ( ) = > ` Invalid argument: hostname=' ${ hostnameStr } ' ` ) ;
return false ;
}
2018-07-20 04:21:11 +02:00
2022-05-25 02:16:39 +02:00
if ( ! server . purchasedByPlayer || server . hostname === "home" ) {
ctx . log ( ( ) = > "Cannot delete non-purchased server." ) ;
return false ;
}
2018-07-20 04:21:11 +02:00
2022-05-25 02:16:39 +02:00
const hostname = server . hostname ;
2018-06-20 18:43:05 +02:00
2022-05-25 02:16:39 +02:00
// Can't delete server you're currently connected to
if ( server . isConnectedTo ) {
ctx . log ( ( ) = > "You are currently connected to the server you are trying to delete." ) ;
return false ;
}
2018-06-20 18:43:05 +02:00
2022-05-25 02:16:39 +02:00
// A server cannot delete itself
if ( hostname === workerScript . hostname ) {
ctx . log ( ( ) = > "Cannot delete the server this script is running on." ) ;
return false ;
}
2017-07-25 03:06:40 +02:00
2022-05-25 02:16:39 +02:00
// Delete all scripts running on server
if ( server . runningScripts . length > 0 ) {
ctx . log ( ( ) = > ` Cannot delete server ' ${ hostname } ' because it still has scripts running. ` ) ;
return false ;
}
2017-07-27 04:56:14 +02:00
2022-05-25 02:16:39 +02:00
// Delete from player's purchasedServers array
let found = false ;
for ( let i = 0 ; i < Player . purchasedServers . length ; ++ i ) {
if ( hostname == Player . purchasedServers [ i ] ) {
found = true ;
Player . purchasedServers . splice ( i , 1 ) ;
break ;
}
2021-09-05 01:09:30 +02:00
}
2017-07-25 03:06:40 +02:00
2022-05-25 02:16:39 +02:00
if ( ! found ) {
ctx . log ( ( ) = > ` Could not identify server ${ hostname } as a purchased server. This is a bug. Report to dev. ` ) ;
return false ;
}
2017-07-27 04:56:14 +02:00
2022-05-25 02:16:39 +02:00
// Delete from all servers
DeleteServer ( hostname ) ;
2021-09-05 01:09:30 +02:00
2022-05-25 02:16:39 +02:00
// Delete from home computer
found = false ;
const homeComputer = Player . getHomeComputer ( ) ;
for ( let i = 0 ; i < homeComputer . serversOnNetwork . length ; ++ i ) {
if ( hostname == homeComputer . serversOnNetwork [ i ] ) {
homeComputer . serversOnNetwork . splice ( i , 1 ) ;
ctx . log ( ( ) = > ` Deleted server ' ${ hostnameStr } ` ) ;
return true ;
}
2021-09-05 01:09:30 +02:00
}
2022-05-25 02:16:39 +02:00
// Wasn't found on home computer
ctx . log ( ( ) = > ` Could not find server ${ hostname } as a purchased server. This is a bug. Report to dev. ` ) ;
return false ;
} ,
getPurchasedServers : ( ) = > ( ) : string [ ] = > {
2021-09-25 07:26:03 +02:00
const res : string [ ] = [ ] ;
2021-10-19 16:13:19 +02:00
Player . purchasedServers . forEach ( function ( hostname ) {
2021-11-03 03:11:22 +01:00
res . push ( hostname ) ;
2021-09-05 01:09:30 +02:00
} ) ;
return res ;
} ,
2022-05-25 02:16:39 +02:00
writePort :
( ctx : NetscriptContext ) = >
( _port : unknown , data : any = "" ) : Promise < any > = > {
const port = ctx . helper . number ( "port" , _port ) ;
if ( typeof data !== "string" && typeof data !== "number" ) {
throw ctx . makeRuntimeErrorMsg ( ` Trying to write invalid data to a port: only strings and numbers are valid. ` ) ;
}
const iport = helper . getValidPort ( "writePort" , port ) ;
return Promise . resolve ( iport . write ( data ) ) ;
} ,
write :
( ctx : NetscriptContext ) = >
( _port : unknown , data : any = "" , _mode : unknown = "a" ) : Promise < void > = > {
const port = ctx . helper . string ( "port" , _port ) ;
const mode = ctx . helper . string ( "mode" , _mode ) ;
if ( isString ( port ) ) {
// Write to script or text file
let fn = port ;
if ( ! isValidFilePath ( fn ) ) {
throw ctx . makeRuntimeErrorMsg ( ` Invalid filepath: ${ fn } ` ) ;
2021-09-05 01:09:30 +02:00
}
2022-05-25 02:16:39 +02:00
if ( fn . lastIndexOf ( "/" ) === 0 ) {
fn = removeLeadingSlash ( fn ) ;
2021-09-05 01:09:30 +02:00
}
2022-05-25 02:16:39 +02:00
// Coerce 'data' to be a string
try {
data = String ( data ) ;
2022-07-15 07:51:30 +02:00
} catch ( e : unknown ) {
2022-07-19 20:21:12 +02:00
throw ctx . makeRuntimeErrorMsg (
` Invalid data ( ${ String ( e ) } ). Data being written must be convertible to a string ` ,
) ;
2022-05-25 02:16:39 +02:00
}
const server = workerScript . getServer ( ) ;
if ( server == null ) {
throw ctx . makeRuntimeErrorMsg ( "Error getting Server. This is a bug. Report to dev." ) ;
}
if ( isScriptFilename ( fn ) ) {
// Write to script
let script = workerScript . getScriptOnServer ( fn , server ) ;
if ( script == null ) {
// Create a new script
script = new Script ( Player , fn , data , server . hostname , server . scripts ) ;
server . scripts . push ( script ) ;
return script . updateRamUsage ( Player , server . scripts ) ;
}
mode === "w" ? ( script . code = data ) : ( script . code += data ) ;
return script . updateRamUsage ( Player , server . scripts ) ;
2021-09-05 01:09:30 +02:00
} else {
2022-05-25 02:16:39 +02:00
// Write to text file
const txtFile = getTextFile ( fn , server ) ;
if ( txtFile == null ) {
createTextFile ( fn , data , server ) ;
return Promise . resolve ( ) ;
}
if ( mode === "w" ) {
txtFile . write ( data ) ;
} else {
txtFile . append ( data ) ;
}
2021-09-05 01:09:30 +02:00
}
2022-05-25 02:16:39 +02:00
return Promise . resolve ( ) ;
} else {
throw ctx . makeRuntimeErrorMsg ( ` Invalid argument: ${ port } ` ) ;
}
} ,
tryWritePort :
( ctx : NetscriptContext ) = >
( _port : unknown , data : any = "" ) : Promise < any > = > {
let port = ctx . helper . number ( "port" , _port ) ;
if ( typeof data !== "string" && typeof data !== "number" ) {
2021-09-05 01:09:30 +02:00
throw makeRuntimeErrorMsg (
2021-11-12 21:42:57 +01:00
"tryWritePort" ,
2022-05-25 02:16:39 +02:00
` Trying to write invalid data to a port: only strings and numbers are valid. ` ,
2021-09-05 01:09:30 +02:00
) ;
}
2022-05-25 02:16:39 +02:00
if ( ! isNaN ( port ) ) {
port = Math . round ( port ) ;
if ( port < 1 || port > CONSTANTS . NumNetscriptPorts ) {
throw makeRuntimeErrorMsg (
"tryWritePort" ,
` Invalid port: ${ port } . Only ports 1- ${ CONSTANTS . NumNetscriptPorts } are valid. ` ,
) ;
}
const iport = NetscriptPorts [ port - 1 ] ;
if ( iport == null || ! ( iport instanceof Object ) ) {
throw ctx . makeRuntimeErrorMsg ( ` Could not find port: ${ port } . This is a bug. Report to dev. ` ) ;
2021-09-05 01:09:30 +02:00
}
2022-05-25 02:16:39 +02:00
return Promise . resolve ( iport . tryWrite ( data ) ) ;
2021-09-05 01:09:30 +02:00
} else {
2022-05-25 02:16:39 +02:00
throw ctx . makeRuntimeErrorMsg ( ` Invalid argument: ${ port } ` ) ;
}
} ,
readPort :
( ctx : NetscriptContext ) = >
( _port : unknown ) : any = > {
const port = ctx . helper . number ( "port" , _port ) ;
// Read from port
const iport = helper . getValidPort ( "readPort" , port ) ;
const x = iport . read ( ) ;
return x ;
} ,
read :
( ctx : NetscriptContext ) = >
( _port : unknown ) : string = > {
const port = ctx . helper . string ( "port" , _port ) ;
if ( isString ( port ) ) {
// Read from script or text file
const fn = port ;
const server = GetServer ( workerScript . hostname ) ;
if ( server == null ) {
throw ctx . makeRuntimeErrorMsg ( "Error getting Server. This is a bug. Report to dev." ) ;
}
if ( isScriptFilename ( fn ) ) {
// Read from script
const script = workerScript . getScriptOnServer ( fn , server ) ;
if ( script == null ) {
return "" ;
}
return script . code ;
2021-09-05 01:09:30 +02:00
} else {
2022-05-25 02:16:39 +02:00
// Read from text file
const txtFile = getTextFile ( fn , server ) ;
if ( txtFile !== null ) {
return txtFile . text ;
} else {
return "" ;
}
}
} else {
throw ctx . makeRuntimeErrorMsg ( ` Invalid argument: ${ port } ` ) ;
}
} ,
peek :
( ctx : NetscriptContext ) = >
( _port : unknown ) : any = > {
const port = ctx . helper . number ( "port" , _port ) ;
const iport = helper . getValidPort ( "peek" , port ) ;
const x = iport . peek ( ) ;
return x ;
} ,
clear :
( ctx : NetscriptContext ) = >
( _file : unknown ) : void = > {
const file = ctx . helper . string ( "file" , _file ) ;
if ( isString ( file ) ) {
// Clear text file
const fn = file ;
const server = GetServer ( workerScript . hostname ) ;
if ( server == null ) {
throw ctx . makeRuntimeErrorMsg ( "Error getting Server. This is a bug. Report to dev." ) ;
}
const txtFile = getTextFile ( fn , server ) ;
if ( txtFile != null ) {
txtFile . write ( "" ) ;
}
} else {
throw ctx . makeRuntimeErrorMsg ( ` Invalid argument: ${ file } ` ) ;
}
} ,
clearPort :
( ctx : NetscriptContext ) = >
( _port : unknown ) : void = > {
const port = ctx . helper . number ( "port" , _port ) ;
// Clear port
const iport = helper . getValidPort ( "clearPort" , port ) ;
iport . clear ( ) ;
} ,
getPortHandle :
( ctx : NetscriptContext ) = >
( _port : unknown ) : IPort = > {
const port = ctx . helper . number ( "port" , _port ) ;
const iport = helper . getValidPort ( "getPortHandle" , port ) ;
return iport ;
} ,
rm :
( ctx : NetscriptContext ) = >
( _fn : unknown , hostname : any ) : boolean = > {
const fn = ctx . helper . string ( "fn" , _fn ) ;
if ( hostname == null || hostname === "" ) {
hostname = workerScript . hostname ;
}
const s = safeGetServer ( hostname , ctx ) ;
const status = s . removeFile ( fn ) ;
if ( ! status . res ) {
ctx . log ( ( ) = > status . msg + "" ) ;
}
return status . res ;
} ,
scriptRunning :
( ctx : NetscriptContext ) = >
( _scriptname : unknown , _hostname : unknown ) : boolean = > {
const scriptname = ctx . helper . string ( "scriptname" , _scriptname ) ;
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
const server = safeGetServer ( hostname , ctx ) ;
for ( let i = 0 ; i < server . runningScripts . length ; ++ i ) {
if ( server . runningScripts [ i ] . filename == scriptname ) {
return true ;
2021-09-05 01:09:30 +02:00
}
}
2022-05-25 02:16:39 +02:00
return false ;
} ,
scriptKill :
( ctx : NetscriptContext ) = >
( _scriptname : unknown , _hostname : unknown ) : boolean = > {
const scriptname = ctx . helper . string ( "scriptname" , _scriptname ) ;
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
const server = safeGetServer ( hostname , ctx ) ;
let suc = false ;
for ( let i = 0 ; i < server . runningScripts . length ; i ++ ) {
if ( server . runningScripts [ i ] . filename == scriptname ) {
killWorkerScript ( server . runningScripts [ i ] , server . hostname ) ;
suc = true ;
i -- ;
}
2021-09-05 01:09:30 +02:00
}
2022-05-25 02:16:39 +02:00
return suc ;
} ,
getScriptName : ( ) = > ( ) : string = > {
return workerScript . name ;
2021-09-05 01:09:30 +02:00
} ,
2022-05-25 02:16:39 +02:00
getScriptRam :
( ctx : NetscriptContext ) = >
( _scriptname : unknown , _hostname : unknown = workerScript . hostname ) : number = > {
const scriptname = ctx . helper . string ( "scriptname" , _scriptname ) ;
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
const server = safeGetServer ( hostname , ctx ) ;
for ( let i = 0 ; i < server . scripts . length ; ++ i ) {
if ( server . scripts [ i ] . filename == scriptname ) {
return server . scripts [ i ] . ramUsage ;
}
2021-09-05 01:09:30 +02:00
}
2022-05-25 02:16:39 +02:00
return 0 ;
} ,
getRunningScript :
( ctx : NetscriptContext ) = >
( fn : any , hostname : any , . . . args : any [ ] ) : IRunningScriptDef | null = > {
let runningScript ;
if ( fn === undefined && hostname === undefined && args . length === 0 ) {
runningScript = workerScript . scriptRef ;
} else if ( typeof fn === "number" ) {
runningScript = getRunningScriptByPid ( fn ) ;
} else {
runningScript = getRunningScript ( ctx , fn , hostname , args ) ;
}
if ( runningScript === null ) return null ;
return createPublicRunningScript ( runningScript ) ;
} ,
getHackTime :
( ctx : NetscriptContext ) = >
( _hostname : unknown = workerScript . hostname ) : number = > {
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
const server = safeGetServer ( hostname , ctx ) ;
if ( ! ( server instanceof Server ) ) {
ctx . log ( ( ) = > "invalid for this kind of server" ) ;
return Infinity ;
2021-09-05 01:09:30 +02:00
}
2022-05-25 02:16:39 +02:00
if ( failOnHacknetServer ( server , "getHackTime" ) ) {
return Infinity ;
2021-09-05 01:09:30 +02:00
}
2018-01-27 07:52:39 +01:00
2022-05-25 02:16:39 +02:00
return calculateHackingTime ( server , Player ) * 1000 ;
} ,
getGrowTime :
( ctx : NetscriptContext ) = >
( _hostname : unknown = workerScript . hostname ) : number = > {
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
const server = safeGetServer ( hostname , ctx ) ;
if ( ! ( server instanceof Server ) ) {
ctx . log ( ( ) = > "invalid for this kind of server" ) ;
return Infinity ;
}
if ( failOnHacknetServer ( server , "getGrowTime" ) ) {
return Infinity ;
2021-09-05 01:09:30 +02:00
}
2022-05-25 02:16:39 +02:00
return calculateGrowTime ( server , Player ) * 1000 ;
} ,
getWeakenTime :
( ctx : NetscriptContext ) = >
( _hostname : unknown = workerScript . hostname ) : number = > {
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
const server = safeGetServer ( hostname , ctx ) ;
if ( ! ( server instanceof Server ) ) {
ctx . log ( ( ) = > "invalid for this kind of server" ) ;
return Infinity ;
2021-09-05 01:09:30 +02:00
}
2022-05-25 02:16:39 +02:00
if ( failOnHacknetServer ( server , "getWeakenTime" ) ) {
return Infinity ;
2021-09-05 01:09:30 +02:00
}
2019-04-10 08:07:12 +02:00
2022-05-25 02:16:39 +02:00
return calculateWeakenTime ( server , Player ) * 1000 ;
} ,
getScriptIncome :
( ctx : NetscriptContext ) = >
( scriptname? : any , hostname? : any , . . . args : any [ ] ) : any = > {
2022-05-25 17:10:25 +02:00
if ( scriptname === undefined ) {
2022-05-25 02:16:39 +02:00
const res = [ ] ;
// First element is total income of all currently running scripts
let total = 0 ;
for ( const script of workerScripts . values ( ) ) {
total += script . scriptRef . onlineMoneyMade / script . scriptRef . onlineRunningTime ;
}
res . push ( total ) ;
// Second element is total income you've earned from scripts since you installed Augs
res . push ( Player . scriptProdSinceLastAug / ( Player . playtimeSinceLastAug / 1000 ) ) ;
return res ;
} else {
// Get income for a particular script
const server = safeGetServer ( hostname , ctx ) ;
const runningScriptObj = findRunningScript ( scriptname , args , server ) ;
if ( runningScriptObj == null ) {
ctx . log ( ( ) = > ` No such script ' ${ scriptname } ' on ' ${ server . hostname } ' with args: ${ arrayToString ( args ) } ` ) ;
return - 1 ;
}
return runningScriptObj . onlineMoneyMade / runningScriptObj . onlineRunningTime ;
}
} ,
getScriptExpGain :
( ctx : NetscriptContext ) = >
( scriptname? : any , hostname? : any , . . . args : any [ ] ) : number = > {
2022-05-25 17:10:25 +02:00
if ( scriptname === undefined ) {
2022-05-25 02:16:39 +02:00
let total = 0 ;
for ( const ws of workerScripts . values ( ) ) {
total += ws . scriptRef . onlineExpGained / ws . scriptRef . onlineRunningTime ;
}
return total ;
} else {
// Get income for a particular script
const server = safeGetServer ( hostname , ctx ) ;
const runningScriptObj = findRunningScript ( scriptname , args , server ) ;
if ( runningScriptObj == null ) {
ctx . log ( ( ) = > ` No such script ' ${ scriptname } ' on ' ${ server . hostname } ' with args: ${ arrayToString ( args ) } ` ) ;
return - 1 ;
}
return runningScriptObj . onlineExpGained / runningScriptObj . onlineRunningTime ;
}
} ,
nFormat :
( ctx : NetscriptContext ) = >
( _n : unknown , _format : unknown ) : string = > {
const n = ctx . helper . number ( "n" , _n ) ;
const format = ctx . helper . string ( "format" , _format ) ;
if ( isNaN ( n ) ) {
return "" ;
}
return numeralWrapper . format ( n , format ) ;
} ,
tFormat :
( ctx : NetscriptContext ) = >
( _milliseconds : unknown , _milliPrecision : unknown = false ) : string = > {
const milliseconds = ctx . helper . number ( "milliseconds" , _milliseconds ) ;
const milliPrecision = helper . boolean ( _milliPrecision ) ;
return convertTimeMsToTimeElapsedString ( milliseconds , milliPrecision ) ;
} ,
getTimeSinceLastAug : ( ) = > ( ) : number = > {
2021-09-05 01:09:30 +02:00
return Player . playtimeSinceLastAug ;
} ,
2022-05-25 02:16:39 +02:00
alert :
( ctx : NetscriptContext ) = >
( _message : unknown ) : void = > {
const message = ctx . helper . string ( "message" , _message ) ;
dialogBoxCreate ( message ) ;
} ,
toast :
( ctx : NetscriptContext ) = >
( _message : unknown , _variant : unknown = ToastVariant . SUCCESS , duration : any = 2000 ) : void = > {
const message = ctx . helper . string ( "message" , _message ) ;
const variant = ctx . helper . string ( "variant" , _variant ) ;
if ( ! checkEnum ( ToastVariant , variant ) )
throw new Error ( ` variant must be one of ${ Object . values ( ToastVariant ) . join ( ", " ) } ` ) ;
SnackbarEvents . emit ( message , variant , duration ) ;
} ,
prompt :
( ctx : NetscriptContext ) = >
( _txt : unknown , options ? : { type ? : string ; options? : string [ ] } ) : Promise < boolean | string > = > {
const txt = ctx . helper . string ( "txt" , _txt ) ;
return new Promise ( function ( resolve ) {
PromptEvent . emit ( {
txt : txt ,
options ,
resolve : resolve ,
} ) ;
2021-09-05 01:09:30 +02:00
} ) ;
2022-05-25 02:16:39 +02:00
} ,
wget :
( ctx : NetscriptContext ) = >
async ( _url : unknown , _target : unknown , _hostname : unknown = workerScript . hostname ) : Promise < boolean > = > {
const url = ctx . helper . string ( "url" , _url ) ;
const target = ctx . helper . string ( "target" , _target ) ;
const hostname = ctx . helper . string ( "hostname" , _hostname ) ;
if ( ! isScriptFilename ( target ) && ! target . endsWith ( ".txt" ) ) {
ctx . log ( ( ) = > ` Invalid target file: ' ${ target } '. Must be a script or text file. ` ) ;
return Promise . resolve ( false ) ;
}
const s = safeGetServer ( hostname , ctx ) ;
return new Promise ( function ( resolve ) {
$ . get (
url ,
function ( data ) {
let res ;
if ( isScriptFilename ( target ) ) {
res = s . writeToScriptFile ( Player , target , data ) ;
} else {
res = s . writeToTextFile ( target , data ) ;
}
if ( ! res . success ) {
ctx . log ( ( ) = > "Failed." ) ;
return resolve ( false ) ;
}
if ( res . overwritten ) {
ctx . log ( ( ) = > ` Successfully retrieved content and overwrote ' ${ target } ' on ' ${ hostname } ' ` ) ;
return resolve ( true ) ;
}
ctx . log ( ( ) = > ` Successfully retrieved content to new file ' ${ target } ' on ' ${ hostname } ' ` ) ;
2021-09-05 01:09:30 +02:00
return resolve ( true ) ;
2022-05-25 02:16:39 +02:00
} ,
"text" ,
) . fail ( function ( e ) {
ctx . log ( ( ) = > JSON . stringify ( e ) ) ;
return resolve ( false ) ;
} ) ;
2021-09-05 01:09:30 +02:00
} ) ;
2022-05-25 02:16:39 +02:00
} ,
getFavorToDonate : ( ) = > ( ) : number = > {
2021-09-09 05:47:34 +02:00
return Math . floor ( CONSTANTS . BaseFavorToDonate * BitNodeMultipliers . RepToDonateToFaction ) ;
2021-09-05 01:09:30 +02:00
} ,
2022-05-25 02:16:39 +02:00
getOwnedSourceFiles : ( ) = > ( ) : SourceFileLvl [ ] = > {
2021-12-02 18:32:10 +01:00
const res : SourceFileLvl [ ] = [ ] ;
2021-12-02 18:17:33 +01:00
for ( let i = 0 ; i < Player . sourceFiles . length ; ++ i ) {
res . push ( {
n : Player.sourceFiles [ i ] . n ,
lvl : Player.sourceFiles [ i ] . lvl ,
2022-05-25 02:16:39 +02:00
} ) ;
2021-12-02 18:17:33 +01:00
}
return res ;
} ,
2022-05-25 02:16:39 +02:00
getPlayer : ( ) = > ( ) : INetscriptPlayer = > {
2021-09-05 01:09:30 +02:00
const data = {
2021-11-05 22:12:52 +01:00
hacking : Player.hacking ,
2021-09-05 01:09:30 +02:00
hp : Player.hp ,
max_hp : Player.max_hp ,
strength : Player.strength ,
defense : Player.defense ,
dexterity : Player.dexterity ,
agility : Player.agility ,
charisma : Player.charisma ,
intelligence : Player.intelligence ,
hacking_exp : Player.hacking_exp ,
strength_exp : Player.strength_exp ,
defense_exp : Player.defense_exp ,
dexterity_exp : Player.dexterity_exp ,
agility_exp : Player.agility_exp ,
charisma_exp : Player.charisma_exp ,
2022-07-15 00:43:33 +02:00
hacking_chance_mult : Player.mults.hacking_chance ,
mults : JSON.parse ( JSON . stringify ( Player . mults ) ) ,
2021-09-05 01:09:30 +02:00
numPeopleKilled : Player.numPeopleKilled ,
2021-11-12 02:09:38 +01:00
money : Player.money ,
2021-09-05 01:09:30 +02:00
city : Player.city ,
location : Player.location ,
hasWseAccount : Player.hasWseAccount ,
hasTixApiAccess : Player.hasTixApiAccess ,
has4SData : Player.has4SData ,
has4SDataTixApi : Player.has4SDataTixApi ,
bitNodeN : Player.bitNodeN ,
totalPlaytime : Player.totalPlaytime ,
playtimeSinceLastAug : Player.playtimeSinceLastAug ,
playtimeSinceLastBitnode : Player.playtimeSinceLastBitnode ,
jobs : { } ,
factions : Player.factions.slice ( ) ,
2021-10-07 23:55:49 +02:00
tor : Player.hasTorRouter ( ) ,
2022-03-12 05:36:47 +01:00
inBladeburner : Player.inBladeburner ( ) ,
2022-01-11 21:08:14 +01:00
hasCorporation : Player.hasCorporation ( ) ,
2022-03-29 20:09:17 +02:00
entropy : Player.entropy ,
2021-09-05 01:09:30 +02:00
} ;
Object . assign ( data . jobs , Player . jobs ) ;
return data ;
} ,
2022-05-25 02:16:39 +02:00
atExit :
( ctx : NetscriptContext ) = >
( f : any ) : void = > {
if ( typeof f !== "function" ) {
throw ctx . makeRuntimeErrorMsg ( "argument should be function" ) ;
}
workerScript . atExit = ( ) = > {
f ( ) ;
} ; // Wrap the user function to prevent WorkerScript leaking as 'this'
} ,
mv :
( ctx : NetscriptContext ) = >
( _host : unknown , _source : unknown , _destination : unknown ) : void = > {
const host = ctx . helper . string ( "host" , _host ) ;
const source = ctx . helper . string ( "source" , _source ) ;
const destination = ctx . helper . string ( "destination" , _destination ) ;
if ( ! isValidFilePath ( source ) ) throw ctx . makeRuntimeErrorMsg ( ` Invalid filename: ' ${ source } ' ` ) ;
if ( ! isValidFilePath ( destination ) ) throw ctx . makeRuntimeErrorMsg ( ` Invalid filename: ' ${ destination } ' ` ) ;
const source_is_txt = source . endsWith ( ".txt" ) ;
const dest_is_txt = destination . endsWith ( ".txt" ) ;
if ( ! isScriptFilename ( source ) && ! source_is_txt )
throw ctx . makeRuntimeErrorMsg ( ` 'mv' can only be used on scripts and text files (.txt) ` ) ;
if ( source_is_txt != dest_is_txt )
throw ctx . makeRuntimeErrorMsg ( ` Source and destination files must have the same type ` ) ;
if ( source === destination ) {
return ;
}
2022-01-12 18:53:54 +01:00
2022-05-25 02:16:39 +02:00
// This will throw if the server is not found, we do not need to validate result.
const destServer : BaseServer | null = safeGetServer ( host , ctx ) ;
2022-01-12 18:53:54 +01:00
2022-05-25 02:16:39 +02:00
if ( ! source_is_txt && destServer . isRunning ( source ) )
throw ctx . makeRuntimeErrorMsg ( ` Cannot use 'mv' on a script that is running ` ) ;
2022-01-12 18:53:54 +01:00
2022-05-25 02:16:39 +02:00
interface File {
filename : string ;
}
2022-01-12 18:53:54 +01:00
2022-05-25 02:16:39 +02:00
const files = source_is_txt ? destServer.textFiles : destServer.scripts ;
let source_file : File | null = null ;
let dest_file : File | null = null ;
2022-01-12 18:53:54 +01:00
2022-05-25 02:16:39 +02:00
for ( let i = 0 ; i < files . length ; ++ i ) {
const file = files [ i ] ;
if ( file . filename === source ) {
source_file = file ;
} else if ( file . filename === destination ) {
dest_file = file ;
}
2022-01-12 18:53:54 +01:00
}
2022-05-25 02:16:39 +02:00
if ( source_file == null ) throw ctx . makeRuntimeErrorMsg ( ` Source file ${ source } does not exist ` ) ;
2022-01-12 18:53:54 +01:00
2022-05-25 02:16:39 +02:00
if ( dest_file != null ) {
if ( dest_file instanceof TextFile && source_file instanceof TextFile ) {
dest_file . text = source_file . text ;
} else if ( dest_file instanceof Script && source_file instanceof Script ) {
dest_file . code = source_file . code ;
dest_file . markUpdated ( ) ;
}
2022-01-12 18:53:54 +01:00
2022-05-25 02:16:39 +02:00
destServer . removeFile ( source ) ;
} else {
source_file . filename = destination ;
if ( source_file instanceof Script ) {
source_file . markUpdated ( ) ;
}
2022-01-12 18:53:54 +01:00
}
2022-05-25 02:16:39 +02:00
} ,
2022-07-15 07:51:30 +02:00
flags : Flags ( workerScript . args . map ( ( a ) = > String ( a ) ) ) ,
2021-09-05 01:09:30 +02:00
} ;
2021-11-04 01:19:52 +01:00
// add undocumented functions
const ns = {
. . . base ,
2022-05-25 02:16:39 +02:00
. . . NetscriptExtra ( Player ) ,
2021-11-04 01:19:52 +01:00
} ;
2021-12-29 08:04:24 +01:00
function getFunctionNames ( obj : any , prefix : string ) : string [ ] {
2021-09-25 03:49:49 +02:00
const functionNames : string [ ] = [ ] ;
2021-09-05 01:09:30 +02:00
for ( const [ key , value ] of Object . entries ( obj ) ) {
2021-12-29 08:04:24 +01:00
if ( key === "args" ) {
continue ;
} else if ( typeof value == "function" ) {
2021-10-11 19:31:12 +02:00
functionNames . push ( prefix + key ) ;
2021-09-05 01:09:30 +02:00
} else if ( typeof value == "object" ) {
2021-10-11 19:31:12 +02:00
functionNames . push ( . . . getFunctionNames ( value , key + "." ) ) ;
2021-09-05 01:09:30 +02:00
}
2021-05-12 21:10:36 +02:00
}
2021-09-05 01:09:30 +02:00
return functionNames ;
}
2021-05-12 21:10:36 +02:00
2021-11-04 01:19:52 +01:00
const possibleLogs = Object . fromEntries ( [ . . . getFunctionNames ( ns , "" ) ] . map ( ( a ) = > [ a , true ] ) ) ;
2017-08-30 19:44:29 +02:00
2022-05-25 02:16:39 +02:00
const wrappedNS = wrapAPI ( helper , { } , workerScript , ns ) as unknown as INS ;
return wrappedNS ;
2021-11-04 01:19:52 +01:00
}