From 427cdb48ba5afe1b7b2db0c9b1db08563ed38a5e Mon Sep 17 00:00:00 2001 From: danielyxie Date: Thu, 27 Sep 2018 16:49:23 -0500 Subject: [PATCH] Initial commit for implemeenting wget and refactoring some Server-related code --- doc/source/netscriptfunctions.rst | 97 +++++-------------------------- src/NetscriptFunctions.js | 28 +++++++++ src/Server.js | 56 +++++++++++++++++- src/Terminal.js | 62 ++------------------ 4 files changed, 105 insertions(+), 138 deletions(-) diff --git a/doc/source/netscriptfunctions.rst b/doc/source/netscriptfunctions.rst index df05c1fc9..25086bf05 100644 --- a/doc/source/netscriptfunctions.rst +++ b/doc/source/netscriptfunctions.rst @@ -1023,92 +1023,27 @@ prompt Prompts the player with a dialog box with two options: "Yes" and "No". This function will return true if the player click "Yes" and false if the player clicks "No". The script's execution is halted until the player selects one of the options. +wget +^^^^ -Defining your own Functions ---------------------------- +.. js:function:: wget(url, target[, hostname/ip=current ip]) -Note that the following information is only applicable for Netscript 1.0. -:doc:`netscriptjs` allows you to define your functions using native Javascript -techniques. + :param string url: URL to pull data from + :param string target: Filename to write data to. Must be script or text file + :param string ip: Optional hostname/ip of server for target file. -You can define your own functions in Netscript 1.0 using the following syntax:: + Retrieves data from a URL and downloads it to a file on the specified server. The data can only + be downloaded to a script (.script, .ns, .js) or a text file (.txt). If the file already exists, + it will be overwritten by this command. - function name(args...) { - function code here... - return some_value - } + Note that it will not be possible to download data from many websites because they do not allow + cross-origin resource sharing (CORS). Example:: -Functions should have some return value. Here is an example of defining and using a function:: + wget("https://raw.githubusercontent.com/danielyxie/bitburner/master/README.md", "game_readme.txt"); - function sum(values) { - res = 0; - for (i = 0; i < values.length; ++i) { - res += values[i]; - } - return res; - } + Returns a boolean indicating whether or not the data was successfully downloaded. - print(sum([1, 2, 3, 4, 5])); //Prints 15 - print(sum([1, 10])); //Prints 11 +getFavorToDonate +^^^^^^^^^^^^^^^^ -For those with experience in other languages, especially Javascript, it may be important to note that -function declarations are not hoisted and must be declared BEFORE you use them. -For example, the following will cause an error saying `variable hello not defined`:: - - print(hello()); - - function hello() { - return "world"; - } - -The following will work fine:: - - function hello() { - return "world"; - } - - print(hello()); //Prints out "world" - -**Note about variable scope in functions:** - -Functions can access "global" variables declared outside of the function's scope. However, they cannot change the value of any "global" variables. -Any changes to "global" variables will only be applied locally to the function. - -The following example shows that any change to a "global" variable -from inside a function only applies in the function's local scope:: - - function foo() { - i = 5; - return "foo"; - } - - i = 0; - print(i); //Prints 0 - foo(); - print(i); //Prints 0 - -Furthermore, this also means that any variable that is first defined inside a -function will NOT be accessible outside of the function as shown in the following example:: - - function sum(values) { - res = 0; - for (i = 0; i < values.length; ++i) { - res += values[i]; - } - return res; - } - print(res); - -results in the following runtime error:: - - Script runtime error: - Server Ip: 75.7.4.1 - Script name: test.script - Args:[] - variable res not defined - - -**Other Notes about creating your own functions:** - -Defining a function does not create a Javascript function object in the underlying game code. This means that you cannot use any function -you create in functions such as `Array.sort() `_ (not yet at least, I'll try to make it work in the future). + Returns the amount of Faction favor required to be able to donate to a faction. diff --git a/src/NetscriptFunctions.js b/src/NetscriptFunctions.js index 02015b587..3c873fd21 100644 --- a/src/NetscriptFunctions.js +++ b/src/NetscriptFunctions.js @@ -2261,6 +2261,34 @@ function NetscriptFunctions(workerScript) { yesNoBoxCreate(txt); }); }, + wget : async function(url, target, ip=workerScript.serverIp) { + if (!isScriptFilename(target) && !target.endsWith(".txt")) { + workerSript.log(`ERROR: wget() failed because of an invalid target file: ${target}. Target file must be a script or text file`); + return false; + } + var s = safeGetServer(ip, "wget"); + $.get(url, function(data) { + let res; + if (isScriptFilename(target)) { + res = s.writeToScriptFile(target, data); + } else { + res = s.writeToTextFile(target, data); + } + if (!res.success) { + workerScript.log("ERROR: wget() failed"); + return false; + } + if (res.overwritten) { + workerScript.log(`wget() successfully retrieved content and overwrote ${target} on ${ip}`); + return true; + } + workerScript.log(`wget successfully retrieved content to new file ${target} on ${ip}`); + return true; + }, 'text').fail(function(e) { + workerScript.log("ERROR: wget() failed: " + JSON.stringify(e)); + return false; + }); + }, getFavorToDonate: function() { if (workerScript.checkingRam) { return updateStaticRam("getFavorToDonate", CONSTANTS.ScriptGetFavorToDonate); diff --git a/src/Server.js b/src/Server.js index 35e8d943b..fa8e423a3 100644 --- a/src/Server.js +++ b/src/Server.js @@ -1,9 +1,11 @@ import {BitNodeMultipliers} from "./BitNodeMultipliers"; import {CodingContract, ContractTypes} from "./CodingContracts"; import {CONSTANTS} from "./Constants"; +import {Script, isScriptFilename} from "./Script"; import {Programs} from "./CreateProgram"; import {Player} from "./Player"; import {SpecialServerIps} from "./SpecialServerIps"; +import {TextFile} from "./TextFile"; import {getRandomInt} from "../utils/helpers/getRandomInt"; import {createRandomIp, ipExists} from "../utils/IPAddress"; import {serverMetadata} from "./data/servers"; @@ -115,7 +117,59 @@ Server.prototype.weaken = function(amt) { this.capDifficulty(); } -// Coding Contracts +// Write to a script file +// Overwrites existing files. Creates new files if the script does not eixst +Server.prototype.writeToScriptFile = function(fn, code) { + var ret = {success: false, overwritten: false}; + if (!isScriptFilename(fn)) { return ret; } + + //Check if the script already exists, and overwrite it if it does + for (let i = 0; i < this.scripts.length; ++i) { + if (fn === this.scripts[i].filename) { + let script = this.scripts[i]; + script.code = code; + script.updateRamUsage(); + script.module = ""; + ret.overwritten = true; + ret.success = true; + return ret; + } + } + + //Otherwise, create a new script + var newScript = new Script(); + newScript.filename = fn; + newScript.code = code; + newScript.updateRamUsage(); + newScript.server = this.ip; + this.scripts.push(newScript); + ret.success = true; + return ret; +} + +// Write to a text file +// Overwrites existing files. Creates new files if the text file does not exist +Server.prototype.writeToTextFile = function(fn, txt) { + var ret = {success: false, overwritten: false}; + if (!fn.endsWith("txt")) { return ret; } + + //Check if the text file already exists, and overwrite if it does + for (let i = 0; i < this.textFiles.length; ++i) { + if (this.textFiles[i].fn === fn) { + ret.overwritten = true; + this.textFiles[i].text = txt; + ret.success = true; + return ret; + } + } + + //Otherwise create a new text file + var newFile = new TextFile(fn, txt); + this.textFiles.push(newFile); + ret.success = true; + return ret; +} + Server.prototype.addContract = function(contract) { this.contracts.push(contract); } diff --git a/src/Terminal.js b/src/Terminal.js index 1849023e6..8c32db86e 100644 --- a/src/Terminal.js +++ b/src/Terminal.js @@ -27,14 +27,13 @@ import {killWorkerScript, addWorkerScript} from "./NetscriptWorker"; import {Player} from "./Player"; import {hackWorldDaemon} from "./RedPill"; import {findRunningScript, RunningScript, - AllServersMap, Script, - isScriptFilename} from "./Script"; + AllServersMap, isScriptFilename} from "./Script"; import {AllServers, GetServerByHostname, getServer, Server} from "./Server"; import {Settings} from "./Settings"; import {SpecialServerIps, SpecialServerNames} from "./SpecialServerIps"; -import {TextFile, getTextFile} from "./TextFile"; +import {getTextFile} from "./TextFile"; import {containsAllStrings, longestCommonStart} from "../utils/StringHelperFunctions"; import {Page, routing} from "./ui/navigationTracking"; @@ -783,55 +782,6 @@ let Terminal = { $('input[class=terminal-input]').prop('disabled', false); }, - writeToScriptFile : function(server, fn, code) { - var ret = {success: false, overwritten: false}; - if (!isScriptFilename(fn) || !(server instanceof Server)) { return ret; } - - //Check if the script already exists, and overwrite it if it does - for (let i = 0; i < server.scripts.length; ++i) { - if (fn === server.scripts[i].filename) { - let script = server.scripts[i]; - script.code = code; - script.updateRamUsage(); - script.module = ""; - ret.overwritten = true; - ret.success = true; - return ret; - } - } - - //Otherwise, create a new script - var newScript = new Script(); - newScript.filename = fn; - newScript.code = code; - newScript.updateRamUsage(); - newScript.server = server.ip; - server.scripts.push(newScript); - ret.success = true; - return ret; - }, - - writeToTextFile : function(server, fn, txt) { - var ret = {success: false, overwritten: false}; - if (!fn.endsWith("txt") || !(server instanceof Server)) { return ret; } - - //Check if the text file already exists, and overwrite if it does - for (let i = 0; i < server.textFiles.length; ++i) { - if (server.textFiles[i].fn === fn) { - ret.overwritten = true; - server.textFiles[i].text = txt; - ret.success = true; - return ret; - } - } - - //Otherwise create a new text file - var newFile = new TextFile(fn, txt); - server.textFiles.push(newFile); - ret.success = true; - return ret; - }, - executeCommand : function(command) { command = command.trim(); //Replace all extra whitespace in command with a single space @@ -1480,7 +1430,7 @@ let Terminal = { if (!found) {return post("Error: no such file exists!");} - let tRes = Terminal.writeToTextFile(destServer, txtFile.fn, txtFile.text); + let tRes = destServer.writeToTextFile(txtFile.fn, txtFile.text); if (!tRes.success) { return post("Error: scp failed"); } @@ -1504,7 +1454,7 @@ let Terminal = { return; } - let sRes = Terminal.writeToScriptFile(destServer, scriptname, sourceScript.code); + let sRes = destServer.writeToScriptFile(scriptname, sourceScript.code); if (!sRes.success) { return post(`Error: scp failed`); } @@ -1658,9 +1608,9 @@ let Terminal = { $.get(url, function(data) { let res; if (isScriptFilename(target)) { - res = Terminal.writeToScriptFile(s, target, data); + res = s.writeToScriptFile(target, data); } else { - res = Terminal.writeToTextFile(s, target, data); + res = s.writeToTextFile(target, data); } if (!res.success) { return post("wget failed");