+
-
-
diff --git a/src/Script.js b/src/Script.js
index 6e5e00c86..11a95ef44 100644
--- a/src/Script.js
+++ b/src/Script.js
@@ -1,14 +1,77 @@
/* Script.js
* Script object
*/
+
+//Define commands in script editor (ctrl x to close, etc.)
+$(document).keydown(function(e) {
+ if (Engine.currentPage == Engine.Page.ScriptEditor) {
+ if (e.keyCode == 88 && e.ctrlKey) {
+ var filename = document.getElementById("script-editor-filename").value;
+
+ if (checkValidFilename(filename) == false) {
+ postScriptEditorStatus("Script filename can contain only alphanumerics, hyphens, and underscores");
+ return;
+ }
+
+ filename += ".script";
+
+ //If the current script matches one thats currently running, throw an error
+ for (var i = 0; i < Player.currentServer.runningScripts.length; i++) {
+ if (filename == Player.currentServer.runningScripts[i].filename) {
+ postScriptEditorStatus("Cannot write to script that is currently running!");
+ return;
+ }
+ }
+
+ //If the current script already exists on the server, overwrite it
+ for (var i = 0; i < Player.currentServer.scripts.length; i++) {
+ if (filename == Player.currentServer.scripts[i].filename) {
+ Player.currentServer.scripts[i].saveScript();
+ Engine.loadTerminalContent();
+ return;
+ }
+ }
+
+ //If the current script does NOT exist, create a new one
+ var script = new Script();
+ script.saveScript();
+ Player.currentServer.scripts.push(script);
+ Engine.loadTerminalContent();
+ }
+ }
+});
+
+//Checks that the string contains only valid characters for a filename, which are alphanumeric,
+// underscores and hyphens
+function checkValidFilename(filename) {
+ var regex = /^[a-zA-Z0-9_-]+$/;
+
+ if (filename.match(regex)) {
+ return true;
+ }
+ return false;
+}
+
+var ScriptEditorLastStatus = null;
+function postScriptEditorStatus(text) {
+ document.getElementById("script-editor-status").innerHTML = text;
+
+ clearTimeout(ScriptEditorLastStatus);
+ ScriptEditorLastStatus = setTimeout(function() {
+ document.getElementById("script-editor-status").innerHTML = "";
+ }, 3000);
+}
+
function Script() {
//Function queue that holds the next functions to be
//executed in this script. A function from this queue
//is executed every second (this may change)
this.functionQueue = [];
+ this.filename = "";
this.code = "";
this.ramUsage = 0;
+ this.server = null; //Which server this script is on
/* Properties to calculate offline progress. Only applies for infinitely looping scripts */
@@ -22,18 +85,31 @@ function Script() {
//Which servers are hacked in one iteration of the script. May contain duplicates
this.serversHacked = [];
-}
+};
//Execute the next function in the Script's function queue
-Script.prototype.executeNext() {
+Script.prototype.executeNext = function() {
if (this.functionQueue.length <= 0) {return;}
//Shift the next element off ths function queue and then execute it
(this.functionQueue.shift())();
}
-Script.prototype.setCode(code) {
- this.code = code;
+//Get the script data from the Script Editor and save it to the object
+Script.prototype.saveScript = function() {
+ if (Engine.currentPage == Engine.Page.ScriptEditor) {
+ //Update code and filename
+ var code = document.getElementById("script-editor-text").value;
+ this.code = code;
+
+ var filename = document.getElementById("script-editor-filename").value + ".script";
+ this.filename = filename;
+
+ //Server
+ this.server = Player.currentServer;
+
+ //TODO Calculate/update number of instructions, ram usage, execution time, etc.
+ }
}
/* Wrapper object that wraps a function with its arguments.
@@ -51,7 +127,7 @@ Script.prototype.setCode(code) {
* fooObj();
*
*/
-function functionObject = function(fn, context, params) {
+function functionObject(fn, context, params) {
return function() {
fn.apply(context, params);
}
diff --git a/src/Server.js b/src/Server.js
index c7d2ec07d..38846bb4c 100644
--- a/src/Server.js
+++ b/src/Server.js
@@ -19,7 +19,6 @@ function Server() {
this.scripts = [];
this.runningScripts = []; //Scripts currently being run
- this.scriptEnvs = []; //The environment for all of the running scripts. Matched by index number
this.programs = [];
/* Hacking information (only valid for "foreign" aka non-purchased servers) */
diff --git a/src/Terminal.js b/src/Terminal.js
index 56b932995..e3a12ee70 100644
--- a/src/Terminal.js
+++ b/src/Terminal.js
@@ -19,20 +19,35 @@ var postNetburnerText = function() {
post("Netburner v1.0");
}
-//command is checked on enter key press
+//Defines what happens when enter is pressed (keycode 13)
$(document).keyup(function(event) {
- if (event.keyCode == 13) {
- var command = $('input[class=terminal-input]').val();
- if (command.length > 0) {
- post("> " + command);
-
- //TODO Do i have to switch the order of these two?
- Terminal.executeCommand(command);
- $('input[class=terminal-input]').val("");
+ //Terminal
+ if (Engine.currentPage == Engine.Page.Terminal) {
+ if (event.keyCode == 13) {
+ var command = $('input[class=terminal-input]').val();
+ if (command.length > 0) {
+ post("> " + command);
+
+ //TODO Do i have to switch the order of these two?
+ Terminal.executeCommand(command);
+ $('input[class=terminal-input]').val("");
+ }
}
}
});
+//Keep terminal in focus
+$(document).ready(function() {
+ if (Engine.currentPage == Engine.Page.Terminal) {
+ $('.terminal-input').focus();
+ }
+});
+$(document).keydown(function() {
+ if (Engine.currentPage == Engine.Page.Terminal) {
+ $('.terminal-input').focus();
+ }
+})
+
var Terminal = {
//Flags to determine whether the player is currently running a hack or an analyze
hackFlag: false,
@@ -136,6 +151,9 @@ var Terminal = {
switch (commandArray[0]) {
case "analyze":
+ if (commandArray.length != 1) {
+ post("Incorrect usage of analyze command. Usage: analyze"); return;
+ }
//Analyze the current server for information
console.log("analyze terminal command called");
Terminal.analyzeFlag = true;
@@ -151,6 +169,9 @@ var Terminal = {
break;
case "clear":
case "cls":
+ if (commandArray.length != 1) {
+ post("Incorrect usage of clear/cls command. Usage: clear/cls"); return;
+ }
console.log("cls/clear terminal command called");
$("#terminal tr:not(:last)").remove();
postNetburnerText();
@@ -177,12 +198,18 @@ var Terminal = {
post("Host not found");
break;
case "df":
+ if (commandArray.length != 1) {
+ post("Incorrect usage of df command. Usage: df"); return;
+ }
console.log("df terminal command called");
post("Total: " + Player.currentServer.maxRam.toString() + " GB");
post("Used: " + Player.currentServer.ramUsed.toString() + " GB");
post("Available: " + (Player.currentServer.maxRam - Player.currentServer.ramUsed).toString() + " GB");
break;
case "hack":
+ if (commandArray.length != 1) {
+ post("Incorrect usage of hack command. Usage: hack"); return;
+ }
//Hack the current PC (usually for money)
//You can't hack your home pc or servers you purchased
if (Player.currentServer.purchasedByPlayer) {
@@ -207,10 +234,16 @@ var Terminal = {
//TODO
break;
case "hostname":
+ if (commandArray.length != 1) {
+ post("Incorrect usage of hostname command. Usage: hostname"); return;
+ }
//Print the hostname of current system
post(Player.currentServer.hostname);
break;
case "ifconfig":
+ if (commandArray.length != 1) {
+ post("Incorrect usage of ifconfig command. Usage: ifconfig"); return;
+ }
//Print the IP address of the current system
post(Player.currentServer.ip);
break;
@@ -218,6 +251,10 @@ var Terminal = {
//TODO
break;
case "ls":
+ if (commandArray.length != 1) {
+ post("Incorrect usage of ls command. Usage: ls"); return;
+ }
+
//Display all programs and scripts
var allFiles = [];
@@ -226,7 +263,7 @@ var Terminal = {
allFiles.push(Player.currentServer.programs[i]);
}
for (var i = 0; i < Player.currentServer.scripts.length; i++) {
- allFiles.push(Player.currentServer.scripts[i]);
+ allFiles.push(Player.currentServer.scripts[i].filename);
}
//Sort the files alphabetically then print each
@@ -236,11 +273,41 @@ var Terminal = {
post(allFiles[i]);
}
break;
+ case "nano":
+ if (commandArray.length != 2) {
+ post("Incorrect usage of nano command. Usage: nano [scriptname]"); return;
+ }
+
+ var filename = commandArray[1];
+
+ //Can only edit script files
+ if (filename.endsWith(".script") == false) {
+ post("Error: Only .script files are editable with nano (filename must end with .scrip)"); return;
+ }
+
+ //Script name is the filename without the .script at the end
+ var scriptname = filename.substr(0, filename.indexOf(".script"));
+
+ //Cannot edit scripts that are currently running
+ for (var i = 0; i < Player.currentServer.runningScripts.length; i++) {
+ if (filename == Player.currentServer.runningScripts[i].filename) {
+ post("Cannot open/edit scripts that are currently running!"); return;
+ }
+ }
+
+ //Check if the script already exists
+ for (var i = 0; i < Player.currentServer.scripts.length; i++) {
+ if (filename == Player.currentServer.scripts[i].filename) {
+ Engine.loadScriptEditorContent(scriptname, Player.currentServer.scripts[i].code);
+ return;
+ }
+ }
+ Engine.loadScriptEditorContent(scriptname, "");
+ break;
case "netstat":
case "scan":
if (commandArray.length != 1) {
- post("Incorrect usage of netstat/scan command. Usage: netstat/scan");
- return;
+ post("Incorrect usage of netstat/scan command. Usage: netstat/scan"); return;
}
//Displays available network connections using TCP
console.log("netstat/scan terminal command called");
@@ -268,6 +335,7 @@ var Terminal = {
entry += hasRoot;
post(entry);
}
+ break;
case "ps":
//TODO
break;
diff --git a/src/engine.js b/src/engine.js
index e71eb00e2..4bd170730 100644
--- a/src/engine.js
+++ b/src/engine.js
@@ -17,35 +17,52 @@ var Engine = {
//Main menu buttons
terminalMainMenuButton: null,
characterMainMenuButton: null,
+ scriptEditorMainMenuButton: null,
},
//Display objects
Display: {
//Progress bar
- progress: null,
+ progress: null,
//Display for status text (such as "Saved" or "Loaded")
- statusText: null,
-
- hacking_skill: null,
+ statusText: null,
+ hacking_skill: null,
+
//Main menu content
- terminalContent: null,
- characterContent: null,
+ terminalContent: null,
+ characterContent: null,
+ scriptEditorContent: null,
//Character info
- characterInfo: null,
+ characterInfo: null,
+
+ //Script editor text
+ scriptEditorText: null,
},
+ //Current page status
+ Page: {
+ Terminal: "Terminal",
+ CharacterInfo: "CharacterInfo",
+ ScriptEditor: "ScriptEditor",
+ },
+ currentPage: null,
+
+
//Time variables (milliseconds unix epoch time)
_lastUpdate: new Date().getTime(),
_idleSpeed: 200, //Speed (in ms) at which the main loop is updated
//Save function
- saveFile: function() {
- var tempSaveFile = JSON.stringify(Player);
+ saveGame: function() {
+ var PlayerSave = JSON.stringify(Player);
+ var ForeignServersSave = JSON.stringify(ForeignServers);
+ //TODO Add factions + companies here when they're done
- window.localStorage.setItem("netburnerSave", tempSaveFile);
+ window.localStorage.setItem("netburnerPlayerSave", PlayerSave);
+ window.localStorage.setItem("netburnerForeignServersSave", ForeignServersSave)
Engine.displayStatusText("Saved!");
},
@@ -53,11 +70,16 @@ var Engine = {
//Load saved game function
loadSave: function() {
//Check to see if file exists
- if (!window.localStorage.getItem("netburnerSave")) {
- Engine.displayStatusText("No save file present for load!");
- } else {
- var tempSaveFile = window.localStorage.getItem("netburnerSave");
- Player = JSON.parse(tempSaveFile);
+ if (!window.localStorage.getItem("netburnerPlayerSave")) {
+ //TODO Add this displayStatusText function
+ Engine.displayStatusText("No Player save file present for load!");
+ } else if (!window.localStorage.getItem("netburnerForeignServersSave")) {
+ Engine.displayStatusText("No Foreign Serverssave file present for load!");
+ } else {
+ var PlayerSave = window.localStorage.getItem("netburnerPlayerSave");
+ var ForeignServersSave = window.localStorage.getItem("netburnerForeignServersSave");
+ Player = JSON.parse(PlayerSave);
+ ForeignServers = JSON.parse(ForeignServersSave);
Engine.displayStatusText("Loaded successfully!");
}
},
@@ -76,18 +98,33 @@ var Engine = {
loadTerminalContent: function() {
Engine.hideAllContent();
Engine.Display.terminalContent.style.visibility = "visible";
+ Engine.currentPage = Engine.Page.Terminal;
},
loadCharacterContent: function() {
Engine.hideAllContent();
Engine.Display.characterContent.style.visibility = "visible";
Engine.displayCharacterInfo();
+ Engine.currentPage = Engine.Page.CharacterInfo;
},
+
+ loadScriptEditorContent: function(filename = "", code = "") {
+ Engine.hideAllContent();
+ Engine.Display.scriptEditorContent.style.visibility = "visible";
+ if (filename == "") {
+ document.getElementById("script-editor-filename").value = "untitled";
+ } else {
+ document.getElementById("script-editor-filename").value = filename;
+ }
+ document.getElementById("script-editor-text").value = code;
+ Engine.currentPage = Engine.Page.ScriptEditor;
+ },
//Helper function that hides all content
hideAllContent: function() {
Engine.Display.terminalContent.style.visibility = "hidden";
Engine.Display.characterContent.style.visibility = "hidden";
+ Engine.Display.scriptEditorContent.style.visibility = "hidden";
},
/* Display character info */
@@ -178,6 +215,9 @@ var Engine = {
/* Initialization */
init: function() {
//Initialization functions
+ //TODO Might need to move these into a new "BeginGame()" function. init() is called
+ //every time the window is opened and we don't want to do these init() functions every
+ //time
Player.init();
ForeignServers.init();
@@ -216,14 +256,26 @@ var Engine = {
Engine.loadCharacterContent();
return false;
});
+
+ Engine.Clickables.scriptEditorMainMenuButton = document.getElementById("create-script-menu-link");
+ Engine.Clickables.scriptEditorMainMenuButton.addEventListener("click", function() {
+ Engine.loadScriptEditorContent();
+ return false;
+ });
Engine.Display.terminalContent = document.getElementById("terminal-container");
+ Engine.currentPage = Engine.Page.Terminal;
Engine.Display.characterContent = document.getElementById("character-container");
- Engine.Display.characterContent.style.visibility = "hidden";
+ Engine.Display.characterContent.style.visibility = "hidden";
+ Engine.Display.scriptEditorContent = document.getElementById("script-editor-container");
+ Engine.Display.scriptEditorContent.style.visibility = "hidden";
//Character info
Engine.Display.characterInfo = document.getElementById("character-info");
- Engine.displayCharacterInfo();
+ //Engine.displayCharacterInfo(); - Don't think I need this
+
+ //Script editor
+ Engine.Display.scriptEditorText = document.getElementById("script-editor-text");
//Message at the top of terminal
postNetburnerText();