Initial commit for implemeenting wget and refactoring some Server-related code

This commit is contained in:
danielyxie 2018-09-27 16:49:23 -05:00
parent 62672a4e2a
commit 427cdb48ba
4 changed files with 105 additions and 138 deletions

@ -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 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. 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. :param string url: URL to pull data from
:doc:`netscriptjs` allows you to define your functions using native Javascript :param string target: Filename to write data to. Must be script or text file
techniques. :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...) { Note that it will not be possible to download data from many websites because they do not allow
function code here... cross-origin resource sharing (CORS). Example::
return some_value
}
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) { Returns a boolean indicating whether or not the data was successfully downloaded.
res = 0;
for (i = 0; i < values.length; ++i) {
res += values[i];
}
return res;
}
print(sum([1, 2, 3, 4, 5])); //Prints 15 getFavorToDonate
print(sum([1, 10])); //Prints 11 ^^^^^^^^^^^^^^^^
For those with experience in other languages, especially Javascript, it may be important to note that Returns the amount of Faction favor required to be able to donate to a faction.
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() <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort>`_ (not yet at least, I'll try to make it work in the future).

@ -2261,6 +2261,34 @@ function NetscriptFunctions(workerScript) {
yesNoBoxCreate(txt); 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() { getFavorToDonate: function() {
if (workerScript.checkingRam) { if (workerScript.checkingRam) {
return updateStaticRam("getFavorToDonate", CONSTANTS.ScriptGetFavorToDonate); return updateStaticRam("getFavorToDonate", CONSTANTS.ScriptGetFavorToDonate);

@ -1,9 +1,11 @@
import {BitNodeMultipliers} from "./BitNodeMultipliers"; import {BitNodeMultipliers} from "./BitNodeMultipliers";
import {CodingContract, ContractTypes} from "./CodingContracts"; import {CodingContract, ContractTypes} from "./CodingContracts";
import {CONSTANTS} from "./Constants"; import {CONSTANTS} from "./Constants";
import {Script, isScriptFilename} from "./Script";
import {Programs} from "./CreateProgram"; import {Programs} from "./CreateProgram";
import {Player} from "./Player"; import {Player} from "./Player";
import {SpecialServerIps} from "./SpecialServerIps"; import {SpecialServerIps} from "./SpecialServerIps";
import {TextFile} from "./TextFile";
import {getRandomInt} from "../utils/helpers/getRandomInt"; import {getRandomInt} from "../utils/helpers/getRandomInt";
import {createRandomIp, ipExists} from "../utils/IPAddress"; import {createRandomIp, ipExists} from "../utils/IPAddress";
import {serverMetadata} from "./data/servers"; import {serverMetadata} from "./data/servers";
@ -115,7 +117,59 @@ Server.prototype.weaken = function(amt) {
this.capDifficulty(); 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) { Server.prototype.addContract = function(contract) {
this.contracts.push(contract); this.contracts.push(contract);
} }

@ -27,14 +27,13 @@ import {killWorkerScript, addWorkerScript} from "./NetscriptWorker";
import {Player} from "./Player"; import {Player} from "./Player";
import {hackWorldDaemon} from "./RedPill"; import {hackWorldDaemon} from "./RedPill";
import {findRunningScript, RunningScript, import {findRunningScript, RunningScript,
AllServersMap, Script, AllServersMap, isScriptFilename} from "./Script";
isScriptFilename} from "./Script";
import {AllServers, GetServerByHostname, import {AllServers, GetServerByHostname,
getServer, Server} from "./Server"; getServer, Server} from "./Server";
import {Settings} from "./Settings"; import {Settings} from "./Settings";
import {SpecialServerIps, import {SpecialServerIps,
SpecialServerNames} from "./SpecialServerIps"; SpecialServerNames} from "./SpecialServerIps";
import {TextFile, getTextFile} from "./TextFile"; import {getTextFile} from "./TextFile";
import {containsAllStrings, import {containsAllStrings,
longestCommonStart} from "../utils/StringHelperFunctions"; longestCommonStart} from "../utils/StringHelperFunctions";
import {Page, routing} from "./ui/navigationTracking"; import {Page, routing} from "./ui/navigationTracking";
@ -783,55 +782,6 @@ let Terminal = {
$('input[class=terminal-input]').prop('disabled', false); $('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) { executeCommand : function(command) {
command = command.trim(); command = command.trim();
//Replace all extra whitespace in command with a single space //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!");} 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) { if (!tRes.success) {
return post("Error: scp failed"); return post("Error: scp failed");
} }
@ -1504,7 +1454,7 @@ let Terminal = {
return; return;
} }
let sRes = Terminal.writeToScriptFile(destServer, scriptname, sourceScript.code); let sRes = destServer.writeToScriptFile(scriptname, sourceScript.code);
if (!sRes.success) { if (!sRes.success) {
return post(`Error: scp failed`); return post(`Error: scp failed`);
} }
@ -1658,9 +1608,9 @@ let Terminal = {
$.get(url, function(data) { $.get(url, function(data) {
let res; let res;
if (isScriptFilename(target)) { if (isScriptFilename(target)) {
res = Terminal.writeToScriptFile(s, target, data); res = s.writeToScriptFile(target, data);
} else { } else {
res = Terminal.writeToTextFile(s, target, data); res = s.writeToTextFile(target, data);
} }
if (!res.success) { if (!res.success) {
return post("wget failed"); return post("wget failed");