2019-01-15 14:11:14 +01:00
import { BitNodeMultipliers } from "./BitNode/BitNodeMultipliers" ;
import { CONSTANTS } from "./Constants" ;
import { Player } from "./Player" ;
import { Environment } from "./NetscriptEnvironment" ;
import { WorkerScript , addWorkerScript } from "./NetscriptWorker" ;
2019-03-05 02:40:28 +01:00
import { Server } from "./Server/Server" ;
import { getServer } from "./Server/ServerHelpers" ;
2019-01-27 23:08:45 +01:00
import { Settings } from "./Settings/Settings" ;
2019-03-05 02:40:28 +01:00
import { RunningScript } from "./Script/RunningScript" ;
import { Script } from "./Script/Script" ;
import { findRunningScript } from "./Script/ScriptHelpers" ;
2017-08-30 19:44:29 +02:00
2019-02-20 09:42:27 +01:00
import { setTimeoutRef } from "./utils/SetTimeoutRef" ;
2018-06-26 18:34:11 +02:00
import { parse , Node } from "../utils/acorn" ;
2018-07-05 20:12:20 +02:00
import { arrayToString } from "../utils/helpers/arrayToString" ;
2018-07-05 03:30:50 +02:00
import { isValidIPAddress } from "../utils/helpers/isValidIPAddress" ;
2018-07-04 06:33:55 +02:00
import { isString } from "../utils/helpers/isString" ;
2017-08-30 19:44:29 +02:00
2019-02-06 08:06:48 +01:00
export function evaluateImport ( exp , workerScript , checkingRam = false ) {
2018-03-03 22:05:33 +01:00
//When its checking RAM, it exports an array of nodes for each imported function
var ramCheckRes = [ ] ;
var env = workerScript . env ;
if ( env . stopFlag ) {
if ( checkingRam ) { return ramCheckRes ; }
return Promise . reject ( workerScript ) ;
}
//Get source script and name of all functions to import
var scriptName = exp . source . value ;
var namespace , namespaceObj , allFns = false , fnNames = [ ] ;
if ( exp . specifiers . length === 1 && exp . specifiers [ 0 ] . type === "ImportNamespaceSpecifier" ) {
allFns = true ;
namespace = exp . specifiers [ 0 ] . local . name ;
} else {
for ( var i = 0 ; i < exp . specifiers . length ; ++ i ) {
fnNames . push ( exp . specifiers [ i ] . local . name ) ;
}
}
//Get the code
var server = getServer ( workerScript . serverIp ) , code = "" ;
if ( server == null ) {
if ( checkingRam ) { return ramCheckRes ; }
return Promise . reject ( makeRuntimeRejectMsg ( workerScript , "Failed to identify server. This is a bug please report to dev" , exp ) ) ;
}
for ( var i = 0 ; i < server . scripts . length ; ++ i ) {
if ( server . scripts [ i ] . filename === scriptName ) {
code = server . scripts [ i ] . code ;
break ;
2017-11-01 23:56:30 +01:00
}
}
2018-03-03 22:05:33 +01:00
if ( code === "" ) {
if ( checkingRam ) { return ramCheckRes ; }
return Promise . reject ( makeRuntimeRejectMsg ( workerScript , "Could not find script " + scriptName + " to import" , exp ) ) ;
}
//Create the AST
try {
var ast = parse ( code , { sourceType : "module" } ) ;
} catch ( e ) {
console . log ( "Failed to parse import script" ) ;
if ( checkingRam ) { return ramCheckRes ; }
return Promise . reject ( makeRuntimeRejectMsg ( workerScript , "Failed to import functions from " + scriptName +
" This is most likely due to a syntax error in the imported script" , exp ) ) ;
}
if ( allFns ) {
//A namespace is implemented as a JS obj
env . set ( namespace , { } ) ;
namespaceObj = env . get ( namespace ) ;
}
//Search through the AST for all imported functions
var queue = [ ast ] ;
while ( queue . length != 0 ) {
var node = queue . shift ( ) ;
switch ( node . type ) {
case "BlockStatement" :
case "Program" :
for ( var i = 0 ; i < node . body . length ; ++ i ) {
if ( node . body [ i ] instanceof Node ) {
queue . push ( node . body [ i ] ) ;
}
}
break ;
case "FunctionDeclaration" :
if ( node . id && node . id . name ) {
if ( allFns ) {
//Import all functions under this namespace
if ( checkingRam ) {
ramCheckRes . push ( node ) ;
} else {
namespaceObj [ node . id . name ] = node ;
}
} else {
//Only import specified functions
if ( fnNames . includes ( node . id . name ) ) {
if ( checkingRam ) {
ramCheckRes . push ( node ) ;
} else {
env . set ( node . id . name , node ) ;
}
}
}
} else {
if ( checkingRam ) { return ramCheckRes ; }
return Promise . reject ( makeRuntimeRejectMsg ( workerScript , "Invalid function declaration in imported script " + scriptName , exp ) ) ;
}
break ;
default :
break ;
}
for ( var prop in node ) {
if ( node . hasOwnProperty ( prop ) ) {
if ( node [ prop ] instanceof Node ) {
queue . push ( node [ prop ] ) ;
}
}
}
}
if ( ! checkingRam ) { workerScript . scriptRef . log ( "Imported functions from " + scriptName ) ; }
if ( checkingRam ) { return ramCheckRes ; }
return Promise . resolve ( true ) ;
}
2019-02-06 08:06:48 +01:00
export function killNetscriptDelay ( workerScript ) {
2017-11-02 22:47:09 +01:00
if ( workerScript instanceof WorkerScript ) {
if ( workerScript . delay ) {
clearTimeout ( workerScript . delay ) ;
workerScript . delayResolve ( ) ;
}
}
2016-11-30 00:07:24 +01:00
}
2019-02-06 08:06:48 +01:00
export function netscriptDelay ( time , workerScript ) {
2017-11-02 22:47:09 +01:00
return new Promise ( function ( resolve , reject ) {
2019-02-20 09:42:27 +01:00
workerScript . delay = setTimeoutRef ( ( ) => {
2017-11-02 22:47:09 +01:00
workerScript . delay = null ;
resolve ( ) ;
} , time ) ;
workerScript . delayResolve = resolve ;
} ) ;
2017-06-05 06:48:37 +02:00
}
2019-02-06 08:06:48 +01:00
export function makeRuntimeRejectMsg ( workerScript , msg , exp = null ) {
2018-03-03 22:05:33 +01:00
var lineNum = "" ;
if ( exp != null ) {
var num = getErrorLineNumber ( exp , workerScript ) ;
lineNum = " (Line " + num + ")"
2016-11-17 23:25:40 +01:00
}
2018-03-03 22:05:33 +01:00
return "|" + workerScript . serverIp + "|" + workerScript . name + "|" + msg + lineNum ;
2017-05-15 08:35:09 +02:00
}
//Run a script from inside a script using run() command
2019-02-06 08:06:48 +01:00
export function runScriptFromScript ( server , scriptname , args , workerScript , threads = 1 ) {
2017-07-13 18:54:29 +02:00
//Check if the script is already running
var runningScriptObj = findRunningScript ( scriptname , args , server ) ;
if ( runningScriptObj != null ) {
workerScript . scriptRef . log ( scriptname + " is already running on " + server . hostname ) ;
return Promise . resolve ( false ) ;
}
2017-06-28 11:47:42 +02:00
2018-02-24 23:55:06 +01:00
//'null/undefined' arguments are not allowed
for ( var i = 0 ; i < args . length ; ++ i ) {
if ( args [ i ] == null ) {
workerScript . scriptRef . log ( "ERROR: Cannot execute a script with null/undefined as an argument" ) ;
return Promise . resolve ( false ) ;
}
}
2017-07-13 18:54:29 +02:00
//Check if the script exists and if it does run it
for ( var i = 0 ; i < server . scripts . length ; ++ i ) {
if ( server . scripts [ i ] . filename == scriptname ) {
//Check for admin rights and that there is enough RAM availble to run
var script = server . scripts [ i ] ;
var ramUsage = script . ramUsage ;
2017-09-13 16:22:22 +02:00
threads = Math . round ( Number ( threads ) ) ; //Convert to number and round
2019-01-29 01:17:04 +01:00
if ( threads === 0 ) { return Promise . resolve ( false ) ; }
2018-07-03 05:35:12 +02:00
ramUsage = ramUsage * threads ;
2017-07-13 18:54:29 +02:00
var ramAvailable = server . maxRam - server . ramUsed ;
2017-06-28 11:47:42 +02:00
2017-07-13 18:54:29 +02:00
if ( server . hasAdminRights == false ) {
workerScript . scriptRef . log ( "Cannot run script " + scriptname + " on " + server . hostname + " because you do not have root access!" ) ;
return Promise . resolve ( false ) ;
} else if ( ramUsage > ramAvailable ) {
workerScript . scriptRef . log ( "Cannot run script " + scriptname + "(t=" + threads + ") on " + server . hostname + " because there is not enough available RAM!" ) ;
return Promise . resolve ( false ) ;
} else {
//Able to run script
2018-06-01 04:36:01 +02:00
if ( workerScript . disableLogs . ALL == null && workerScript . disableLogs . exec == null && workerScript . disableLogs . run == null && workerScript . disableLogs . spawn == null ) {
2018-07-05 20:12:20 +02:00
workerScript . scriptRef . log ( "Running script: " + scriptname + " on " + server . hostname + " with " + threads + " threads and args: " + arrayToString ( args ) + ". May take a few seconds to start up..." ) ;
2018-06-01 04:36:01 +02:00
}
2017-07-13 18:54:29 +02:00
var runningScriptObj = new RunningScript ( script , args ) ;
runningScriptObj . threads = threads ;
2019-03-25 04:03:24 +01:00
server . runScript ( runningScriptObj , Player ) ; // Push onto runningScripts
2017-07-13 18:54:29 +02:00
addWorkerScript ( runningScriptObj , server ) ;
return Promise . resolve ( true ) ;
2017-05-15 08:35:09 +02:00
}
2017-06-28 11:47:42 +02:00
}
2017-07-13 18:54:29 +02:00
}
workerScript . scriptRef . log ( "Could not find script " + scriptname + " on " + server . hostname ) ;
return Promise . resolve ( false ) ;
2017-05-15 08:35:09 +02:00
}
2016-12-14 00:52:32 +01:00
2019-02-06 08:06:48 +01:00
export function getErrorLineNumber ( exp , workerScript ) {
var code = workerScript . scriptRef . codeCode ( ) ;
2017-09-05 03:03:29 +02:00
//Split code up to the start of the node
2018-03-03 22:05:33 +01:00
try {
code = code . substring ( 0 , exp . start ) ;
return ( code . match ( /\n/g ) || [ ] ) . length + 1 ;
} catch ( e ) {
return - 1 ;
}
2017-09-05 03:03:29 +02:00
}
2019-02-06 08:06:48 +01:00
export function isScriptErrorMessage ( msg ) {
2017-08-30 19:44:29 +02:00
if ( ! isString ( msg ) ) { return false ; }
let splitMsg = msg . split ( "|" ) ;
2017-05-01 07:39:48 +02:00
if ( splitMsg . length != 4 ) {
return false ;
}
var ip = splitMsg [ 1 ] ;
if ( ! isValidIPAddress ( ip ) ) {
return false ;
}
return true ;
}