bitburner-src/src/Terminal.jsx

2481 lines
102 KiB
React
Raw Normal View History

import {
evaluateDirectoryPath,
evaluateFilePath,
getFirstParentDirectory,
isInRootDirectory,
isValidDirectoryPath,
removeLeadingSlash,
2021-04-30 05:52:56 +02:00
removeTrailingSlash,
} from "./Terminal/DirectoryHelpers";
import { determineAllPossibilitiesForTabCompletion } from "./Terminal/determineAllPossibilitiesForTabCompletion";
import { TerminalHelpText, HelpTexts } from "./Terminal/HelpText";
import { tabCompletion } from "./Terminal/tabCompletion";
import { createFconf } from "./Fconf/Fconf";
import {
parseAliasDeclaration,
printAliases,
removeAlias,
2021-04-30 05:52:56 +02:00
substituteAliases,
} from "./Alias";
import { BitNodeMultipliers } from "./BitNode/BitNodeMultipliers";
import {
CodingContractResult,
} from "./CodingContracts";
import { CONSTANTS } from "./Constants";
import { Programs } from "./Programs/Programs";
import {
executeDarkwebTerminalCommand,
2021-04-30 05:52:56 +02:00
checkIfConnectedToDarkweb,
} from "./DarkWeb/DarkWeb";
import { Engine } from "./engine";
import { FconfSettings } from "./Fconf/FconfSettings";
import {
calculateHackingChance,
calculateHackingExpGain,
calculatePercentMoneyHacked,
calculateHackingTime,
calculateGrowTime,
2021-04-30 05:52:56 +02:00
calculateWeakenTime,
} from "./Hacking";
import { HacknetServer } from "./Hacknet/HacknetServer";
import {
iTutorialNextStep,
iTutorialSteps,
2021-04-30 05:52:56 +02:00
ITutorial,
} from "./InteractiveTutorial";
2021-03-14 07:08:24 +01:00
import { showLiterature } from "./Literature/LiteratureHelpers";
import { Message } from "./Message/Message";
import { showMessage } from "./Message/MessageHelpers";
import { startWorkerScript } from "./NetscriptWorker";
import { killWorkerScript } from "./Netscript/killWorkerScript";
import { WorkerScriptStartStopEventEmitter } from "./Netscript/WorkerScriptStartStopEventEmitter";
import { Player } from "./Player";
import { hackWorldDaemon } from "./RedPill";
import { RunningScript } from "./Script/RunningScript";
2021-06-12 11:42:18 +02:00
import { compareArrays } from "../utils/helpers/compareArrays";
import { getRamUsageFromRunningScript } from "./Script/RunningScriptHelpers";
2021-05-02 05:33:44 +02:00
import {
findRunningScript,
findRunningScriptByPid,
} from "./Script/ScriptHelpers";
import { isScriptFilename } from "./Script/ScriptHelpersTS";
import { AllServers } from "./Server/AllServers";
import {
GetServerByHostname,
getServer,
2021-04-30 05:52:56 +02:00
getServerOnNetwork,
} from "./Server/ServerHelpers";
import {
SpecialServerIps,
2021-04-30 05:52:56 +02:00
SpecialServerNames,
} from "./Server/SpecialServerIps";
import { setTimeoutRef } from "./utils/SetTimeoutRef";
import { Page, routing } from "./ui/navigationTracking";
import { numeralWrapper } from "./ui/numeralFormat";
import { KEY } from "../utils/helpers/keyCodes";
import { arrayToString } from "../utils/helpers/arrayToString";
import { getTimestamp } from "../utils/helpers/getTimestamp";
import { logBoxCreate } from "../utils/LogBox";
import {
yesNoBoxCreate,
yesNoBoxGetYesButton,
yesNoBoxGetNoButton,
2021-04-30 05:52:56 +02:00
yesNoBoxClose,
} from "../utils/YesNoBox";
import {
post,
postElement,
postContent,
postError,
hackProgressBarPost,
2021-04-30 05:52:56 +02:00
hackProgressPost,
} from "./ui/postToTerminal";
import { convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions";
import { Money } from "./ui/React/Money";
import autosize from "autosize";
import * as JSZip from "jszip";
import * as FileSaver from "file-saver";
2021-08-19 22:37:59 +02:00
import * as libarg from 'arg';
import React from "react";
2021-08-20 07:21:37 +02:00
import ReactDOM from 'react-dom';
2018-03-12 20:39:04 +01:00
function postNetburnerText() {
post("Bitburner v" + CONSTANTS.Version);
2016-10-20 23:11:01 +02:00
}
// Helper function that checks if an argument (which is a string) is a valid number
function isNumber(str) {
if (typeof str != "string") { return false; } // Only process strings
return !isNaN(str) && !isNaN(parseFloat(str));
}
function getTerminalInput() {
return document.getElementById("terminal-input-text-box").value;
}
// Defines key commands in terminal
$(document).keydown(function(event) {
// Terminal
if (routing.isOn(Page.Terminal)) {
var terminalInput = document.getElementById("terminal-input-text-box");
if (terminalInput != null && !event.ctrlKey && !event.shiftKey && !Terminal.contractOpen) {terminalInput.focus();}
if (event.keyCode === KEY.ENTER) {
event.preventDefault(); // Prevent newline from being entered in Script Editor
const command = getTerminalInput();
const dir = Terminal.currDir;
post(
"<span class='prompt'>[" +
2018-08-02 17:04:21 +02:00
(FconfSettings.ENABLE_TIMESTAMPS ? getTimestamp() + " " : "") +
Player.getCurrentServer().hostname +
2021-04-30 05:52:56 +02:00
` ~${dir}]&gt;</span> ${command}`,
);
if (command.length > 0) {
Terminal.resetTerminalInput(); // Clear input first
Terminal.executeCommands(command);
}
}
if (event.keyCode === KEY.C && event.ctrlKey) {
2018-03-12 20:39:04 +01:00
if (Engine._actionInProgress) {
// Cancel action
2018-03-12 20:39:04 +01:00
post("Cancelling...");
Engine._actionInProgress = false;
Terminal.finishAction(true);
2018-03-12 20:39:04 +01:00
} else if (FconfSettings.ENABLE_BASH_HOTKEYS) {
// Dont prevent default so it still copies
Terminal.resetTerminalInput(); // Clear Terminal
2018-03-12 20:39:04 +01:00
}
}
2018-03-12 20:39:04 +01:00
if (event.keyCode === KEY.L && event.ctrlKey) {
event.preventDefault();
Terminal.executeCommand("clear"); // Clear screen
2018-03-12 20:39:04 +01:00
}
// Ctrl p same as up arrow
// Ctrl n same as down arrow
2018-03-12 20:39:04 +01:00
if (event.keyCode === KEY.UPARROW ||
(FconfSettings.ENABLE_BASH_HOTKEYS && event.keyCode === KEY.P && event.ctrlKey)) {
if (FconfSettings.ENABLE_BASH_HOTKEYS) {event.preventDefault();}
// Cycle through past commands
if (terminalInput == null) {return;}
var i = Terminal.commandHistoryIndex;
var len = Terminal.commandHistory.length;
if (len == 0) {return;}
if (i < 0 || i > len) {
Terminal.commandHistoryIndex = len;
}
if (i != 0) {
--Terminal.commandHistoryIndex;
}
var prevCommand = Terminal.commandHistory[Terminal.commandHistoryIndex];
terminalInput.value = prevCommand;
setTimeoutRef(function(){terminalInput.selectionStart = terminalInput.selectionEnd = 10000; }, 10);
}
2018-03-12 20:39:04 +01:00
if (event.keyCode === KEY.DOWNARROW ||
(FconfSettings.ENABLE_BASH_HOTKEYS && event.keyCode === KEY.M && event.ctrlKey)) {
if (FconfSettings.ENABLE_BASH_HOTKEYS) {event.preventDefault();}
// Cycle through past commands
if (terminalInput == null) {return;}
var i = Terminal.commandHistoryIndex;
var len = Terminal.commandHistory.length;
if (len == 0) {return;}
if (i < 0 || i > len) {
Terminal.commandHistoryIndex = len;
}
// Latest command, put nothing
if (i == len || i == len-1) {
Terminal.commandHistoryIndex = len;
terminalInput.value = "";
} else {
++Terminal.commandHistoryIndex;
var prevCommand = Terminal.commandHistory[Terminal.commandHistoryIndex];
terminalInput.value = prevCommand;
}
}
2018-03-12 20:39:04 +01:00
if (event.keyCode === KEY.TAB) {
event.preventDefault();
// Autocomplete
if (terminalInput == null) {return;}
2019-04-20 07:27:33 +02:00
let input = terminalInput.value;
if (input == "") { return; }
const semiColonIndex = input.lastIndexOf(";");
if(semiColonIndex !== -1) {
2019-02-09 03:46:30 +01:00
input = input.slice(semiColonIndex + 1);
}
input = input.trim();
input = input.replace(/\s\s+/g, ' ');
2019-04-20 07:27:33 +02:00
const commandArray = input.split(" ");
let index = commandArray.length - 2;
if (index < -1) { index = 0; }
const allPos = determineAllPossibilitiesForTabCompletion(Player, input, index, Terminal.currDir);
if (allPos.length == 0) {return;}
2019-04-20 07:27:33 +02:00
let arg = "";
let command = "";
if (commandArray.length == 0) {return;}
if (commandArray.length == 1) {command = commandArray[0];}
else if (commandArray.length == 2) {
command = commandArray[0];
arg = commandArray[1];
} else if (commandArray.length == 3) {
command = commandArray[0] + " " + commandArray[1];
arg = commandArray[2];
} else {
arg = commandArray.pop();
command = commandArray.join(" ");
}
tabCompletion(command, arg, allPos);
terminalInput.focus();
}
2018-03-12 20:39:04 +01:00
// Extra Bash Emulation Hotkeys, must be enabled through .fconf
2018-03-12 20:39:04 +01:00
if (FconfSettings.ENABLE_BASH_HOTKEYS) {
if (event.keyCode === KEY.A && event.ctrlKey) {
event.preventDefault();
Terminal.moveTextCursor("home");
}
if (event.keyCode === KEY.E && event.ctrlKey) {
event.preventDefault();
Terminal.moveTextCursor("end");
}
if (event.keyCode === KEY.B && event.ctrlKey) {
event.preventDefault();
Terminal.moveTextCursor("prevchar");
}
if (event.keyCode === KEY.B && event.altKey) {
event.preventDefault();
Terminal.moveTextCursor("prevword");
}
if (event.keyCode === KEY.F && event.ctrlKey) {
event.preventDefault();
Terminal.moveTextCursor("nextchar");
}
if (event.keyCode === KEY.F && event.altKey) {
event.preventDefault();
Terminal.moveTextCursor("nextword");
}
if ((event.keyCode === KEY.H || event.keyCode === KEY.D) && event.ctrlKey) {
Terminal.modifyInput("backspace");
event.preventDefault();
}
// TODO AFTER THIS:
// alt + d deletes word after cursor
// ^w deletes word before cursor
// ^k clears line after cursor
// ^u clears line before cursor
2018-03-12 20:39:04 +01:00
}
}
});
// Keep terminal in focus
let terminalCtrlPressed = false, shiftKeyPressed = false;
2016-11-24 23:30:33 +01:00
$(document).ready(function() {
if (routing.isOn(Page.Terminal)) {
$('.terminal-input').focus();
}
2016-11-24 23:30:33 +01:00
});
$(document).keydown(function(e) {
if (routing.isOn(Page.Terminal)) {
if (e.which == KEY.CTRL) {
terminalCtrlPressed = true;
} else if (e.shiftKey) {
shiftKeyPressed = true;
} else if (terminalCtrlPressed || shiftKeyPressed || Terminal.contractOpen) {
// Don't focus
} else {
var inputTextBox = document.getElementById("terminal-input-text-box");
if (inputTextBox != null) {inputTextBox.focus();}
terminalCtrlPressed = false;
shiftKeyPressed = false;
}
}
});
$(document).keyup(function(e) {
if (routing.isOn(Page.Terminal)) {
if (e.which == KEY.CTRL) {
terminalCtrlPressed = false;
}
if (e.shiftKey) {
shiftKeyPressed = false;
}
}
});
let Terminal = {
// Flags to determine whether the player is currently running a hack or an analyze
hackFlag: false,
v0.51.6 (#905) * Make command `cd` without arguments an alias for `cd /` (#853) In most shells `cd` without arguments takes you to the home directory of the current user. I keep trying to do this due to muscle memory from working in terminals, so I figured I'd make it do something useful. There is no home directory in the game, but going to / is the closest thing we have, since that is the starting point for the user in the game. * Add new `backdoor` terminal command (#852) * Add the backdoor command to the terminal This command will perform a manual hack without rewarding money. It will be used for the story, mainly for faction hacking tests * Add tab completion for backdoor command * Add help text for backdoor command * Change condition syntax to be more consistent with others * Extract reused code block so it is always called after actions * Update documentation for new backdoor command Modified references to manual hack as it isn't for factions anymore * Remove extra parenthesis * Rename manuallyHacked to backdoorInstalled * Fix typo * Change faction test messages to use backdoor instad of hack * Rename more instances of manuallyHacked * fixed typo in helptext of darkweb buy (#858) * Fix typos and unify descriptions of augmentations (#859) Made an attempt to... - give all "+rep% company/faction" the same text - make all augmentations with a single effect use a single line to describe the effect - make all effects end with a period * Made Cashroot starter kit display its tooltip with the money formatted properly and in gold * fix typo in docs (#860) * Initial code for Casino Card Deck implementation * Casino Blackjack Implementation * Update some tools (eslint, typescript) * Blackjack code cleanup * Update README_contribution * Update ScriptHelpers.js (#861) expand error message * More augmentation typo fixes (#862) * Add Netscript function getCurrentScript (#856) Add netscript function that returns the current script. * Added milestones menu to guide new players. (#865) Milestone menu * fix typos in milestones (#866) Co-authored-by: sschmidTU <s.schmid@phonicscore.com> * Corrupt location title when backdoor is installed (#864) * Add corruptableText component * Corrupt location title if backdoor is installed * Formatting * Add helper to check value of backdoorInstalled Helper could be oneline but it would make it less readable * Fix some formatting * Add settings option to disable text effects * Import useState * getRunningScript (#867) * Replaced getCurrentScript with getRunningScript * Bunch of smaller fixes (#904) Fix #884 Fix #879 Fix #878 Fix #876 Fix #874 Fix #873 Fix #887 Fix #891 Fix #895 * rework the early servers to be more noob friendly (#903) * v0.51.6 Co-authored-by: Andreas Eriksson <2691182+AndreasTPC@users.noreply.github.com> Co-authored-by: Jack <jackdewinter1@gmail.com> Co-authored-by: Teun Pronk <5228255+Crownie88@users.noreply.github.com> Co-authored-by: Pimvgd <Pimvgd@gmail.com> Co-authored-by: Daniel Xie <daniel.xie@flockfreight.com> Co-authored-by: Simon <33069673+sschmidTU@users.noreply.github.com> Co-authored-by: sschmidTU <s.schmid@phonicscore.com>
2021-04-29 02:07:26 +02:00
backdoorFlag: false,
analyzeFlag: false,
actionStarted: false,
actionTime: 0,
commandHistory: [],
commandHistoryIndex: 0,
// True if a Coding Contract prompt is opened
contractOpen: false,
// Full Path of current directory
// Excludes the trailing forward slash
currDir: "/",
resetTerminalInput: function(keepInput=false) {
let input = "";
if(keepInput) {
input = getTerminalInput();
}
const dir = Terminal.currDir;
if (FconfSettings.WRAP_INPUT) {
document.getElementById("terminal-input-td").innerHTML =
`<div id='terminal-input-header' class='prompt'>[${Player.getCurrentServer().hostname} ~${dir}]$ </div>` +
`<textarea type="text" id="terminal-input-text-box" class="terminal-input" tabindex="1" value=\"${input}\" autocomplete="off" />`;
// Auto re-size the line element as it wraps
autosize(document.getElementById("terminal-input-text-box"));
} else {
document.getElementById("terminal-input-td").innerHTML =
`<div id='terminal-input-header' class='prompt'>[${Player.getCurrentServer().hostname} ~${dir}]$ </div>` +
`<input type="text" id="terminal-input-text-box" class="terminal-input" tabindex="1" value=\"${input}\" autocomplete="off" />`;
}
const hdr = document.getElementById("terminal-input-header");
2017-09-13 16:22:22 +02:00
hdr.style.display = "inline";
const terminalInput = document.getElementById("terminal-input-text-box");
if (typeof terminalInput.selectionStart == "number") {
terminalInput.selectionStart = terminalInput.selectionEnd = terminalInput.value.length;
} else if (typeof terminalInput.createTextRange != "undefined") {
terminalInput.focus();
var range = el.createTextRange();
range.collapse(false);
range.select();
}
2018-03-12 20:39:04 +01:00
},
modifyInput: function(mod) {
try {
var terminalInput = document.getElementById("terminal-input-text-box");
if (terminalInput == null) {return;}
terminalInput.focus();
var inputLength = terminalInput.value.length;
var start = terminalInput.selectionStart;
var inputText = terminalInput.value;
switch(mod.toLowerCase()) {
case "backspace":
if (start > 0 && start <= inputLength+1) {
terminalInput.value = inputText.substr(0, start-1) + inputText.substr(start);
}
break;
case "deletewordbefore": // Delete rest of word before the cursor
2018-03-12 20:39:04 +01:00
for (var delStart = start-1; delStart > 0; --delStart) {
if (inputText.charAt(delStart) === " ") {
terminalInput.value = inputText.substr(0, delStart) + inputText.substr(start);
return;
}
}
break;
case "deletewordafter": // Delete rest of word after the cursor
2018-03-12 20:39:04 +01:00
for (var delStart = start+1; delStart <= text.length+1; ++delStart) {
if (inputText.charAt(delStart) === " ") {
terminalInput.value = inputText.substr(0, start) + inputText.substr(delStart);
return;
}
}
break;
case "clearafter": // Deletes everything after cursor
2018-03-12 20:39:04 +01:00
break;
case "clearbefore:": // Deleetes everything before cursor
2018-03-12 20:39:04 +01:00
break;
}
} catch(e) {
2019-02-12 01:23:46 +01:00
console.error("Exception in Terminal.modifyInput: " + e);
2018-03-12 20:39:04 +01:00
}
},
moveTextCursor: function(loc) {
try {
var terminalInput = document.getElementById("terminal-input-text-box");
if (terminalInput == null) {return;}
terminalInput.focus();
var inputLength = terminalInput.value.length;
var start = terminalInput.selectionStart;
switch(loc.toLowerCase()) {
case "home":
terminalInput.setSelectionRange(0,0);
break;
case "end":
terminalInput.setSelectionRange(inputLength, inputLength);
break;
case "prevchar":
if (start > 0) {terminalInput.setSelectionRange(start-1, start-1);}
break;
case "prevword":
for (var i = start-2; i >= 0; --i) {
if (terminalInput.value.charAt(i) === " ") {
terminalInput.setSelectionRange(i+1, i+1);
return;
}
}
terminalInput.setSelectionRange(0, 0);
break;
case "nextchar":
terminalInput.setSelectionRange(start+1, start+1);
break;
case "nextword":
for (var i = start+1; i <= inputLength; ++i) {
if (terminalInput.value.charAt(i) === " ") {
terminalInput.setSelectionRange(i, i);
return;
}
}
terminalInput.setSelectionRange(inputLength, inputLength);
break;
default:
2019-02-12 01:23:46 +01:00
console.warn("Invalid loc argument in Terminal.moveTextCursor()");
2018-03-12 20:39:04 +01:00
break;
}
} catch(e) {
2019-02-12 01:23:46 +01:00
console.error("Exception in Terminal.moveTextCursor: " + e);
2018-03-12 20:39:04 +01:00
}
},
startHack: function() {
Terminal.hackFlag = true;
// Hacking through Terminal should be faster than hacking through a script
Terminal.actionTime = calculateHackingTime(Player.getCurrentServer(), Player) / 4;
Terminal.startAction();
},
v0.51.6 (#905) * Make command `cd` without arguments an alias for `cd /` (#853) In most shells `cd` without arguments takes you to the home directory of the current user. I keep trying to do this due to muscle memory from working in terminals, so I figured I'd make it do something useful. There is no home directory in the game, but going to / is the closest thing we have, since that is the starting point for the user in the game. * Add new `backdoor` terminal command (#852) * Add the backdoor command to the terminal This command will perform a manual hack without rewarding money. It will be used for the story, mainly for faction hacking tests * Add tab completion for backdoor command * Add help text for backdoor command * Change condition syntax to be more consistent with others * Extract reused code block so it is always called after actions * Update documentation for new backdoor command Modified references to manual hack as it isn't for factions anymore * Remove extra parenthesis * Rename manuallyHacked to backdoorInstalled * Fix typo * Change faction test messages to use backdoor instad of hack * Rename more instances of manuallyHacked * fixed typo in helptext of darkweb buy (#858) * Fix typos and unify descriptions of augmentations (#859) Made an attempt to... - give all "+rep% company/faction" the same text - make all augmentations with a single effect use a single line to describe the effect - make all effects end with a period * Made Cashroot starter kit display its tooltip with the money formatted properly and in gold * fix typo in docs (#860) * Initial code for Casino Card Deck implementation * Casino Blackjack Implementation * Update some tools (eslint, typescript) * Blackjack code cleanup * Update README_contribution * Update ScriptHelpers.js (#861) expand error message * More augmentation typo fixes (#862) * Add Netscript function getCurrentScript (#856) Add netscript function that returns the current script. * Added milestones menu to guide new players. (#865) Milestone menu * fix typos in milestones (#866) Co-authored-by: sschmidTU <s.schmid@phonicscore.com> * Corrupt location title when backdoor is installed (#864) * Add corruptableText component * Corrupt location title if backdoor is installed * Formatting * Add helper to check value of backdoorInstalled Helper could be oneline but it would make it less readable * Fix some formatting * Add settings option to disable text effects * Import useState * getRunningScript (#867) * Replaced getCurrentScript with getRunningScript * Bunch of smaller fixes (#904) Fix #884 Fix #879 Fix #878 Fix #876 Fix #874 Fix #873 Fix #887 Fix #891 Fix #895 * rework the early servers to be more noob friendly (#903) * v0.51.6 Co-authored-by: Andreas Eriksson <2691182+AndreasTPC@users.noreply.github.com> Co-authored-by: Jack <jackdewinter1@gmail.com> Co-authored-by: Teun Pronk <5228255+Crownie88@users.noreply.github.com> Co-authored-by: Pimvgd <Pimvgd@gmail.com> Co-authored-by: Daniel Xie <daniel.xie@flockfreight.com> Co-authored-by: Simon <33069673+sschmidTU@users.noreply.github.com> Co-authored-by: sschmidTU <s.schmid@phonicscore.com>
2021-04-29 02:07:26 +02:00
startBackdoor: function() {
Terminal.backdoorFlag = true;
// Backdoor should take the same amount of time as hack
Terminal.actionTime = calculateHackingTime(Player.getCurrentServer(), Player) / 4;
Terminal.startAction();
},
startAnalyze: function() {
Terminal.analyzeFlag = true;
Terminal.actionTime = 1;
post("Analyzing system...");
Terminal.startAction();
},
startAction: function() {
Terminal.actionStarted = true;
hackProgressPost("Time left:");
hackProgressBarPost("[");
// Disable terminal
document.getElementById("terminal-input-td").innerHTML = '<input type="text" class="terminal-input"/>';
$('input[class=terminal-input]').prop('disabled', true);
},
2018-03-12 20:39:04 +01:00
finishAction: function(cancelled = false) {
if (Terminal.hackFlag) {
Terminal.finishHack(cancelled);
v0.51.6 (#905) * Make command `cd` without arguments an alias for `cd /` (#853) In most shells `cd` without arguments takes you to the home directory of the current user. I keep trying to do this due to muscle memory from working in terminals, so I figured I'd make it do something useful. There is no home directory in the game, but going to / is the closest thing we have, since that is the starting point for the user in the game. * Add new `backdoor` terminal command (#852) * Add the backdoor command to the terminal This command will perform a manual hack without rewarding money. It will be used for the story, mainly for faction hacking tests * Add tab completion for backdoor command * Add help text for backdoor command * Change condition syntax to be more consistent with others * Extract reused code block so it is always called after actions * Update documentation for new backdoor command Modified references to manual hack as it isn't for factions anymore * Remove extra parenthesis * Rename manuallyHacked to backdoorInstalled * Fix typo * Change faction test messages to use backdoor instad of hack * Rename more instances of manuallyHacked * fixed typo in helptext of darkweb buy (#858) * Fix typos and unify descriptions of augmentations (#859) Made an attempt to... - give all "+rep% company/faction" the same text - make all augmentations with a single effect use a single line to describe the effect - make all effects end with a period * Made Cashroot starter kit display its tooltip with the money formatted properly and in gold * fix typo in docs (#860) * Initial code for Casino Card Deck implementation * Casino Blackjack Implementation * Update some tools (eslint, typescript) * Blackjack code cleanup * Update README_contribution * Update ScriptHelpers.js (#861) expand error message * More augmentation typo fixes (#862) * Add Netscript function getCurrentScript (#856) Add netscript function that returns the current script. * Added milestones menu to guide new players. (#865) Milestone menu * fix typos in milestones (#866) Co-authored-by: sschmidTU <s.schmid@phonicscore.com> * Corrupt location title when backdoor is installed (#864) * Add corruptableText component * Corrupt location title if backdoor is installed * Formatting * Add helper to check value of backdoorInstalled Helper could be oneline but it would make it less readable * Fix some formatting * Add settings option to disable text effects * Import useState * getRunningScript (#867) * Replaced getCurrentScript with getRunningScript * Bunch of smaller fixes (#904) Fix #884 Fix #879 Fix #878 Fix #876 Fix #874 Fix #873 Fix #887 Fix #891 Fix #895 * rework the early servers to be more noob friendly (#903) * v0.51.6 Co-authored-by: Andreas Eriksson <2691182+AndreasTPC@users.noreply.github.com> Co-authored-by: Jack <jackdewinter1@gmail.com> Co-authored-by: Teun Pronk <5228255+Crownie88@users.noreply.github.com> Co-authored-by: Pimvgd <Pimvgd@gmail.com> Co-authored-by: Daniel Xie <daniel.xie@flockfreight.com> Co-authored-by: Simon <33069673+sschmidTU@users.noreply.github.com> Co-authored-by: sschmidTU <s.schmid@phonicscore.com>
2021-04-29 02:07:26 +02:00
} else if (Terminal.backdoorFlag) {
Terminal.finishBackdoor(cancelled);
2018-03-12 20:39:04 +01:00
} else if (Terminal.analyzeFlag) {
Terminal.finishAnalyze(cancelled);
}
v0.51.6 (#905) * Make command `cd` without arguments an alias for `cd /` (#853) In most shells `cd` without arguments takes you to the home directory of the current user. I keep trying to do this due to muscle memory from working in terminals, so I figured I'd make it do something useful. There is no home directory in the game, but going to / is the closest thing we have, since that is the starting point for the user in the game. * Add new `backdoor` terminal command (#852) * Add the backdoor command to the terminal This command will perform a manual hack without rewarding money. It will be used for the story, mainly for faction hacking tests * Add tab completion for backdoor command * Add help text for backdoor command * Change condition syntax to be more consistent with others * Extract reused code block so it is always called after actions * Update documentation for new backdoor command Modified references to manual hack as it isn't for factions anymore * Remove extra parenthesis * Rename manuallyHacked to backdoorInstalled * Fix typo * Change faction test messages to use backdoor instad of hack * Rename more instances of manuallyHacked * fixed typo in helptext of darkweb buy (#858) * Fix typos and unify descriptions of augmentations (#859) Made an attempt to... - give all "+rep% company/faction" the same text - make all augmentations with a single effect use a single line to describe the effect - make all effects end with a period * Made Cashroot starter kit display its tooltip with the money formatted properly and in gold * fix typo in docs (#860) * Initial code for Casino Card Deck implementation * Casino Blackjack Implementation * Update some tools (eslint, typescript) * Blackjack code cleanup * Update README_contribution * Update ScriptHelpers.js (#861) expand error message * More augmentation typo fixes (#862) * Add Netscript function getCurrentScript (#856) Add netscript function that returns the current script. * Added milestones menu to guide new players. (#865) Milestone menu * fix typos in milestones (#866) Co-authored-by: sschmidTU <s.schmid@phonicscore.com> * Corrupt location title when backdoor is installed (#864) * Add corruptableText component * Corrupt location title if backdoor is installed * Formatting * Add helper to check value of backdoorInstalled Helper could be oneline but it would make it less readable * Fix some formatting * Add settings option to disable text effects * Import useState * getRunningScript (#867) * Replaced getCurrentScript with getRunningScript * Bunch of smaller fixes (#904) Fix #884 Fix #879 Fix #878 Fix #876 Fix #874 Fix #873 Fix #887 Fix #891 Fix #895 * rework the early servers to be more noob friendly (#903) * v0.51.6 Co-authored-by: Andreas Eriksson <2691182+AndreasTPC@users.noreply.github.com> Co-authored-by: Jack <jackdewinter1@gmail.com> Co-authored-by: Teun Pronk <5228255+Crownie88@users.noreply.github.com> Co-authored-by: Pimvgd <Pimvgd@gmail.com> Co-authored-by: Daniel Xie <daniel.xie@flockfreight.com> Co-authored-by: Simon <33069673+sschmidTU@users.noreply.github.com> Co-authored-by: sschmidTU <s.schmid@phonicscore.com>
2021-04-29 02:07:26 +02:00
// Rename the progress bar so that the next hacks dont trigger it. Re-enable terminal
$("#hack-progress-bar").attr('id', "old-hack-progress-bar");
$("#hack-progress").attr('id', "old-hack-progress");
Terminal.resetTerminalInput();
$('input[class=terminal-input]').prop('disabled', false);
2017-09-13 16:22:22 +02:00
},
// Complete the hack/analyze command
v0.51.6 (#905) * Make command `cd` without arguments an alias for `cd /` (#853) In most shells `cd` without arguments takes you to the home directory of the current user. I keep trying to do this due to muscle memory from working in terminals, so I figured I'd make it do something useful. There is no home directory in the game, but going to / is the closest thing we have, since that is the starting point for the user in the game. * Add new `backdoor` terminal command (#852) * Add the backdoor command to the terminal This command will perform a manual hack without rewarding money. It will be used for the story, mainly for faction hacking tests * Add tab completion for backdoor command * Add help text for backdoor command * Change condition syntax to be more consistent with others * Extract reused code block so it is always called after actions * Update documentation for new backdoor command Modified references to manual hack as it isn't for factions anymore * Remove extra parenthesis * Rename manuallyHacked to backdoorInstalled * Fix typo * Change faction test messages to use backdoor instad of hack * Rename more instances of manuallyHacked * fixed typo in helptext of darkweb buy (#858) * Fix typos and unify descriptions of augmentations (#859) Made an attempt to... - give all "+rep% company/faction" the same text - make all augmentations with a single effect use a single line to describe the effect - make all effects end with a period * Made Cashroot starter kit display its tooltip with the money formatted properly and in gold * fix typo in docs (#860) * Initial code for Casino Card Deck implementation * Casino Blackjack Implementation * Update some tools (eslint, typescript) * Blackjack code cleanup * Update README_contribution * Update ScriptHelpers.js (#861) expand error message * More augmentation typo fixes (#862) * Add Netscript function getCurrentScript (#856) Add netscript function that returns the current script. * Added milestones menu to guide new players. (#865) Milestone menu * fix typos in milestones (#866) Co-authored-by: sschmidTU <s.schmid@phonicscore.com> * Corrupt location title when backdoor is installed (#864) * Add corruptableText component * Corrupt location title if backdoor is installed * Formatting * Add helper to check value of backdoorInstalled Helper could be oneline but it would make it less readable * Fix some formatting * Add settings option to disable text effects * Import useState * getRunningScript (#867) * Replaced getCurrentScript with getRunningScript * Bunch of smaller fixes (#904) Fix #884 Fix #879 Fix #878 Fix #876 Fix #874 Fix #873 Fix #887 Fix #891 Fix #895 * rework the early servers to be more noob friendly (#903) * v0.51.6 Co-authored-by: Andreas Eriksson <2691182+AndreasTPC@users.noreply.github.com> Co-authored-by: Jack <jackdewinter1@gmail.com> Co-authored-by: Teun Pronk <5228255+Crownie88@users.noreply.github.com> Co-authored-by: Pimvgd <Pimvgd@gmail.com> Co-authored-by: Daniel Xie <daniel.xie@flockfreight.com> Co-authored-by: Simon <33069673+sschmidTU@users.noreply.github.com> Co-authored-by: sschmidTU <s.schmid@phonicscore.com>
2021-04-29 02:07:26 +02:00
finishHack: function(cancelled = false) {
if (!cancelled) {
var server = Player.getCurrentServer();
// Calculate whether hack was successful
var hackChance = calculateHackingChance(server, Player);
var rand = Math.random();
var expGainedOnSuccess = calculateHackingExpGain(server, Player);
var expGainedOnFailure = (expGainedOnSuccess / 4);
if (rand < hackChance) { // Success!
2017-07-22 00:54:55 +02:00
if (SpecialServerIps[SpecialServerNames.WorldDaemon] &&
SpecialServerIps[SpecialServerNames.WorldDaemon] == server.ip) {
2017-08-13 07:01:33 +02:00
if (Player.bitNodeN == null) {
Player.bitNodeN = 1;
}
hackWorldDaemon(Player.bitNodeN);
Terminal.hackFlag = false;
2017-07-22 00:54:55 +02:00
return;
}
v0.51.6 (#905) * Make command `cd` without arguments an alias for `cd /` (#853) In most shells `cd` without arguments takes you to the home directory of the current user. I keep trying to do this due to muscle memory from working in terminals, so I figured I'd make it do something useful. There is no home directory in the game, but going to / is the closest thing we have, since that is the starting point for the user in the game. * Add new `backdoor` terminal command (#852) * Add the backdoor command to the terminal This command will perform a manual hack without rewarding money. It will be used for the story, mainly for faction hacking tests * Add tab completion for backdoor command * Add help text for backdoor command * Change condition syntax to be more consistent with others * Extract reused code block so it is always called after actions * Update documentation for new backdoor command Modified references to manual hack as it isn't for factions anymore * Remove extra parenthesis * Rename manuallyHacked to backdoorInstalled * Fix typo * Change faction test messages to use backdoor instad of hack * Rename more instances of manuallyHacked * fixed typo in helptext of darkweb buy (#858) * Fix typos and unify descriptions of augmentations (#859) Made an attempt to... - give all "+rep% company/faction" the same text - make all augmentations with a single effect use a single line to describe the effect - make all effects end with a period * Made Cashroot starter kit display its tooltip with the money formatted properly and in gold * fix typo in docs (#860) * Initial code for Casino Card Deck implementation * Casino Blackjack Implementation * Update some tools (eslint, typescript) * Blackjack code cleanup * Update README_contribution * Update ScriptHelpers.js (#861) expand error message * More augmentation typo fixes (#862) * Add Netscript function getCurrentScript (#856) Add netscript function that returns the current script. * Added milestones menu to guide new players. (#865) Milestone menu * fix typos in milestones (#866) Co-authored-by: sschmidTU <s.schmid@phonicscore.com> * Corrupt location title when backdoor is installed (#864) * Add corruptableText component * Corrupt location title if backdoor is installed * Formatting * Add helper to check value of backdoorInstalled Helper could be oneline but it would make it less readable * Fix some formatting * Add settings option to disable text effects * Import useState * getRunningScript (#867) * Replaced getCurrentScript with getRunningScript * Bunch of smaller fixes (#904) Fix #884 Fix #879 Fix #878 Fix #876 Fix #874 Fix #873 Fix #887 Fix #891 Fix #895 * rework the early servers to be more noob friendly (#903) * v0.51.6 Co-authored-by: Andreas Eriksson <2691182+AndreasTPC@users.noreply.github.com> Co-authored-by: Jack <jackdewinter1@gmail.com> Co-authored-by: Teun Pronk <5228255+Crownie88@users.noreply.github.com> Co-authored-by: Pimvgd <Pimvgd@gmail.com> Co-authored-by: Daniel Xie <daniel.xie@flockfreight.com> Co-authored-by: Simon <33069673+sschmidTU@users.noreply.github.com> Co-authored-by: sschmidTU <s.schmid@phonicscore.com>
2021-04-29 02:07:26 +02:00
server.backdoorInstalled = true;
var moneyGained = calculatePercentMoneyHacked(server, Player);
moneyGained = Math.floor(server.moneyAvailable * moneyGained);
if (moneyGained <= 0) {moneyGained = 0;} // Safety check
server.moneyAvailable -= moneyGained;
Player.gainMoney(moneyGained);
Player.recordMoneySource(moneyGained, "hacking");
Player.gainHackingExp(expGainedOnSuccess)
2017-09-15 16:06:59 +02:00
Player.gainIntelligenceExp(expGainedOnSuccess / CONSTANTS.IntelligenceTerminalHackBaseExpGain);
server.fortify(CONSTANTS.ServerFortifyAmount);
2021-09-04 20:03:19 +02:00
postElement(<>Hack successful! Gained <Money money={moneyGained} /> and {numeralWrapper.formatExp(expGainedOnSuccess)} hacking exp</>);
} else { // Failure
// Player only gains 25% exp for failure? TODO Can change this later to balance
Player.gainHackingExp(expGainedOnFailure)
v0.51.6 (#905) * Make command `cd` without arguments an alias for `cd /` (#853) In most shells `cd` without arguments takes you to the home directory of the current user. I keep trying to do this due to muscle memory from working in terminals, so I figured I'd make it do something useful. There is no home directory in the game, but going to / is the closest thing we have, since that is the starting point for the user in the game. * Add new `backdoor` terminal command (#852) * Add the backdoor command to the terminal This command will perform a manual hack without rewarding money. It will be used for the story, mainly for faction hacking tests * Add tab completion for backdoor command * Add help text for backdoor command * Change condition syntax to be more consistent with others * Extract reused code block so it is always called after actions * Update documentation for new backdoor command Modified references to manual hack as it isn't for factions anymore * Remove extra parenthesis * Rename manuallyHacked to backdoorInstalled * Fix typo * Change faction test messages to use backdoor instad of hack * Rename more instances of manuallyHacked * fixed typo in helptext of darkweb buy (#858) * Fix typos and unify descriptions of augmentations (#859) Made an attempt to... - give all "+rep% company/faction" the same text - make all augmentations with a single effect use a single line to describe the effect - make all effects end with a period * Made Cashroot starter kit display its tooltip with the money formatted properly and in gold * fix typo in docs (#860) * Initial code for Casino Card Deck implementation * Casino Blackjack Implementation * Update some tools (eslint, typescript) * Blackjack code cleanup * Update README_contribution * Update ScriptHelpers.js (#861) expand error message * More augmentation typo fixes (#862) * Add Netscript function getCurrentScript (#856) Add netscript function that returns the current script. * Added milestones menu to guide new players. (#865) Milestone menu * fix typos in milestones (#866) Co-authored-by: sschmidTU <s.schmid@phonicscore.com> * Corrupt location title when backdoor is installed (#864) * Add corruptableText component * Corrupt location title if backdoor is installed * Formatting * Add helper to check value of backdoorInstalled Helper could be oneline but it would make it less readable * Fix some formatting * Add settings option to disable text effects * Import useState * getRunningScript (#867) * Replaced getCurrentScript with getRunningScript * Bunch of smaller fixes (#904) Fix #884 Fix #879 Fix #878 Fix #876 Fix #874 Fix #873 Fix #887 Fix #891 Fix #895 * rework the early servers to be more noob friendly (#903) * v0.51.6 Co-authored-by: Andreas Eriksson <2691182+AndreasTPC@users.noreply.github.com> Co-authored-by: Jack <jackdewinter1@gmail.com> Co-authored-by: Teun Pronk <5228255+Crownie88@users.noreply.github.com> Co-authored-by: Pimvgd <Pimvgd@gmail.com> Co-authored-by: Daniel Xie <daniel.xie@flockfreight.com> Co-authored-by: Simon <33069673+sschmidTU@users.noreply.github.com> Co-authored-by: sschmidTU <s.schmid@phonicscore.com>
2021-04-29 02:07:26 +02:00
post(`Failed to hack ${server.hostname}. Gained ${numeralWrapper.formatExp(expGainedOnFailure)} hacking exp`);
}
}
Terminal.hackFlag = false;
},
v0.51.6 (#905) * Make command `cd` without arguments an alias for `cd /` (#853) In most shells `cd` without arguments takes you to the home directory of the current user. I keep trying to do this due to muscle memory from working in terminals, so I figured I'd make it do something useful. There is no home directory in the game, but going to / is the closest thing we have, since that is the starting point for the user in the game. * Add new `backdoor` terminal command (#852) * Add the backdoor command to the terminal This command will perform a manual hack without rewarding money. It will be used for the story, mainly for faction hacking tests * Add tab completion for backdoor command * Add help text for backdoor command * Change condition syntax to be more consistent with others * Extract reused code block so it is always called after actions * Update documentation for new backdoor command Modified references to manual hack as it isn't for factions anymore * Remove extra parenthesis * Rename manuallyHacked to backdoorInstalled * Fix typo * Change faction test messages to use backdoor instad of hack * Rename more instances of manuallyHacked * fixed typo in helptext of darkweb buy (#858) * Fix typos and unify descriptions of augmentations (#859) Made an attempt to... - give all "+rep% company/faction" the same text - make all augmentations with a single effect use a single line to describe the effect - make all effects end with a period * Made Cashroot starter kit display its tooltip with the money formatted properly and in gold * fix typo in docs (#860) * Initial code for Casino Card Deck implementation * Casino Blackjack Implementation * Update some tools (eslint, typescript) * Blackjack code cleanup * Update README_contribution * Update ScriptHelpers.js (#861) expand error message * More augmentation typo fixes (#862) * Add Netscript function getCurrentScript (#856) Add netscript function that returns the current script. * Added milestones menu to guide new players. (#865) Milestone menu * fix typos in milestones (#866) Co-authored-by: sschmidTU <s.schmid@phonicscore.com> * Corrupt location title when backdoor is installed (#864) * Add corruptableText component * Corrupt location title if backdoor is installed * Formatting * Add helper to check value of backdoorInstalled Helper could be oneline but it would make it less readable * Fix some formatting * Add settings option to disable text effects * Import useState * getRunningScript (#867) * Replaced getCurrentScript with getRunningScript * Bunch of smaller fixes (#904) Fix #884 Fix #879 Fix #878 Fix #876 Fix #874 Fix #873 Fix #887 Fix #891 Fix #895 * rework the early servers to be more noob friendly (#903) * v0.51.6 Co-authored-by: Andreas Eriksson <2691182+AndreasTPC@users.noreply.github.com> Co-authored-by: Jack <jackdewinter1@gmail.com> Co-authored-by: Teun Pronk <5228255+Crownie88@users.noreply.github.com> Co-authored-by: Pimvgd <Pimvgd@gmail.com> Co-authored-by: Daniel Xie <daniel.xie@flockfreight.com> Co-authored-by: Simon <33069673+sschmidTU@users.noreply.github.com> Co-authored-by: sschmidTU <s.schmid@phonicscore.com>
2021-04-29 02:07:26 +02:00
finishBackdoor: function(cancelled = false) {
if(!cancelled){
2021-05-04 01:00:01 +02:00
const server = Player.getCurrentServer();
if (SpecialServerIps[SpecialServerNames.WorldDaemon] &&
SpecialServerIps[SpecialServerNames.WorldDaemon] == server.ip) {
if (Player.bitNodeN == null) {
Player.bitNodeN = 1;
}
hackWorldDaemon(Player.bitNodeN);
Terminal.backdoorFlag = false;
2021-05-04 01:00:01 +02:00
return;
}
v0.51.6 (#905) * Make command `cd` without arguments an alias for `cd /` (#853) In most shells `cd` without arguments takes you to the home directory of the current user. I keep trying to do this due to muscle memory from working in terminals, so I figured I'd make it do something useful. There is no home directory in the game, but going to / is the closest thing we have, since that is the starting point for the user in the game. * Add new `backdoor` terminal command (#852) * Add the backdoor command to the terminal This command will perform a manual hack without rewarding money. It will be used for the story, mainly for faction hacking tests * Add tab completion for backdoor command * Add help text for backdoor command * Change condition syntax to be more consistent with others * Extract reused code block so it is always called after actions * Update documentation for new backdoor command Modified references to manual hack as it isn't for factions anymore * Remove extra parenthesis * Rename manuallyHacked to backdoorInstalled * Fix typo * Change faction test messages to use backdoor instad of hack * Rename more instances of manuallyHacked * fixed typo in helptext of darkweb buy (#858) * Fix typos and unify descriptions of augmentations (#859) Made an attempt to... - give all "+rep% company/faction" the same text - make all augmentations with a single effect use a single line to describe the effect - make all effects end with a period * Made Cashroot starter kit display its tooltip with the money formatted properly and in gold * fix typo in docs (#860) * Initial code for Casino Card Deck implementation * Casino Blackjack Implementation * Update some tools (eslint, typescript) * Blackjack code cleanup * Update README_contribution * Update ScriptHelpers.js (#861) expand error message * More augmentation typo fixes (#862) * Add Netscript function getCurrentScript (#856) Add netscript function that returns the current script. * Added milestones menu to guide new players. (#865) Milestone menu * fix typos in milestones (#866) Co-authored-by: sschmidTU <s.schmid@phonicscore.com> * Corrupt location title when backdoor is installed (#864) * Add corruptableText component * Corrupt location title if backdoor is installed * Formatting * Add helper to check value of backdoorInstalled Helper could be oneline but it would make it less readable * Fix some formatting * Add settings option to disable text effects * Import useState * getRunningScript (#867) * Replaced getCurrentScript with getRunningScript * Bunch of smaller fixes (#904) Fix #884 Fix #879 Fix #878 Fix #876 Fix #874 Fix #873 Fix #887 Fix #891 Fix #895 * rework the early servers to be more noob friendly (#903) * v0.51.6 Co-authored-by: Andreas Eriksson <2691182+AndreasTPC@users.noreply.github.com> Co-authored-by: Jack <jackdewinter1@gmail.com> Co-authored-by: Teun Pronk <5228255+Crownie88@users.noreply.github.com> Co-authored-by: Pimvgd <Pimvgd@gmail.com> Co-authored-by: Daniel Xie <daniel.xie@flockfreight.com> Co-authored-by: Simon <33069673+sschmidTU@users.noreply.github.com> Co-authored-by: sschmidTU <s.schmid@phonicscore.com>
2021-04-29 02:07:26 +02:00
server.backdoorInstalled = true;
postElement(<>Backdoor successful!</>);
}
Terminal.backdoorFlag = false;
},
finishAnalyze: function(cancelled = false) {
v0.51.6 (#905) * Make command `cd` without arguments an alias for `cd /` (#853) In most shells `cd` without arguments takes you to the home directory of the current user. I keep trying to do this due to muscle memory from working in terminals, so I figured I'd make it do something useful. There is no home directory in the game, but going to / is the closest thing we have, since that is the starting point for the user in the game. * Add new `backdoor` terminal command (#852) * Add the backdoor command to the terminal This command will perform a manual hack without rewarding money. It will be used for the story, mainly for faction hacking tests * Add tab completion for backdoor command * Add help text for backdoor command * Change condition syntax to be more consistent with others * Extract reused code block so it is always called after actions * Update documentation for new backdoor command Modified references to manual hack as it isn't for factions anymore * Remove extra parenthesis * Rename manuallyHacked to backdoorInstalled * Fix typo * Change faction test messages to use backdoor instad of hack * Rename more instances of manuallyHacked * fixed typo in helptext of darkweb buy (#858) * Fix typos and unify descriptions of augmentations (#859) Made an attempt to... - give all "+rep% company/faction" the same text - make all augmentations with a single effect use a single line to describe the effect - make all effects end with a period * Made Cashroot starter kit display its tooltip with the money formatted properly and in gold * fix typo in docs (#860) * Initial code for Casino Card Deck implementation * Casino Blackjack Implementation * Update some tools (eslint, typescript) * Blackjack code cleanup * Update README_contribution * Update ScriptHelpers.js (#861) expand error message * More augmentation typo fixes (#862) * Add Netscript function getCurrentScript (#856) Add netscript function that returns the current script. * Added milestones menu to guide new players. (#865) Milestone menu * fix typos in milestones (#866) Co-authored-by: sschmidTU <s.schmid@phonicscore.com> * Corrupt location title when backdoor is installed (#864) * Add corruptableText component * Corrupt location title if backdoor is installed * Formatting * Add helper to check value of backdoorInstalled Helper could be oneline but it would make it less readable * Fix some formatting * Add settings option to disable text effects * Import useState * getRunningScript (#867) * Replaced getCurrentScript with getRunningScript * Bunch of smaller fixes (#904) Fix #884 Fix #879 Fix #878 Fix #876 Fix #874 Fix #873 Fix #887 Fix #891 Fix #895 * rework the early servers to be more noob friendly (#903) * v0.51.6 Co-authored-by: Andreas Eriksson <2691182+AndreasTPC@users.noreply.github.com> Co-authored-by: Jack <jackdewinter1@gmail.com> Co-authored-by: Teun Pronk <5228255+Crownie88@users.noreply.github.com> Co-authored-by: Pimvgd <Pimvgd@gmail.com> Co-authored-by: Daniel Xie <daniel.xie@flockfreight.com> Co-authored-by: Simon <33069673+sschmidTU@users.noreply.github.com> Co-authored-by: sschmidTU <s.schmid@phonicscore.com>
2021-04-29 02:07:26 +02:00
if (!cancelled) {
let currServ = Player.getCurrentServer();
2019-03-25 04:03:24 +01:00
const isHacknet = currServ instanceof HacknetServer;
post(currServ.hostname + ": ");
const org = currServ.organizationName
post("Organization name: " + (!isHacknet ? org : "Player"));
let hasAdminRights = !isHacknet && currServ.hasAdminRights || isHacknet;
post("Root Access: " + (hasAdminRights ? "YES" : "NO"));
const hackingSkill = currServ.requiredHackingSkill
post("Required hacking skill: " + (!isHacknet ? hackingSkill : "N/A"));
const security = currServ.hackDifficulty;
post("Server security level: " + (!isHacknet ? numeralWrapper.formatServerSecurity(security) : "N/A"));
const hackingChance = calculateHackingChance(currServ, Player)
post("Chance to hack: " + (!isHacknet ? numeralWrapper.formatPercentage(hackingChance) : "N/A"));
const hackingTime = calculateHackingTime(currServ, Player)*1000;
post("Time to hack: " + (!isHacknet ? convertTimeMsToTimeElapsedString(hackingTime, true) : "N/A"));
2021-09-04 20:03:19 +02:00
postElement(<>Total money available on server: {!isHacknet ? <Money money={currServ.moneyAvailable} /> : "N/A"}</>);
const numPort = currServ.numOpenPortsRequired;
post("Required number of open ports for NUKE: " + (!isHacknet ? numPort : "N/A"));
post("SSH port: "+ (currServ.sshPortOpen ? "Open" : "Closed"))
post("FTP port: "+ (currServ.ftpPortOpen ? "Open" : "Closed"))
post("SMTP port: "+ (currServ.smtpPortOpen ? "Open" : "Closed"))
post("HTTP port: "+ (currServ.httpPortOpen ? "Open" : "Closed"))
post("SQL port: "+ (currServ.sqlPortOpen ? "Open" : "Closed"))
}
Terminal.analyzeFlag = false;
},
executeCommands : function(commands) {
// Sanitize input
commands = commands.trim();
commands = commands.replace(/\s\s+/g, ' '); // Replace all extra whitespace in command with a single space
// Handle Terminal History - multiple commands should be saved as one
if (Terminal.commandHistory[Terminal.commandHistory.length-1] != commands) {
Terminal.commandHistory.push(commands);
if (Terminal.commandHistory.length > 50) {
Terminal.commandHistory.splice(0, 1);
}
}
Terminal.commandHistoryIndex = Terminal.commandHistory.length;
// Split commands and execute sequentially
2021-05-08 18:44:21 +02:00
commands = commands
.match(/(?:'[^']*'|"[^"]*"|[^;"])*/g)
.map(substituteAliases)
.map(c => c.match(/(?:'[^']*'|"[^"]*"|[^;"])*/g))
.flat();
for (let i = 0; i < commands.length; i++) {
if(commands[i].match(/^\s*$/)) { continue; } // Don't run commands that only have whitespace
Terminal.executeCommand(commands[i].trim());
}
},
parseCommandArguments : function(command) {
// This will be used to keep track of whether we're in a quote. This is for situations
// like the alias command:
// alias run="run NUKE.exe"
// We want the run="run NUKE.exe" to be parsed as a single command, so this flag
// will keep track of whether we have a quote in
let inQuote = ``;
// Returns an array with the command and its arguments in each index
// Properly handles quotation marks (e.g. `run foo.script "the sun"` will return [run, foo.script, the sun])
const args = [];
let start = 0, i = 0;
let prevChar = ''; // Previous character
while (i < command.length) {
let escaped = false; // Check for escaped quotation marks
if (i >= 1) {
prevChar = command.charAt(i - 1);
if (prevChar === "\\") { escaped = true; }
}
const c = command.charAt(i);
if (c === '"') { // Double quotes
if (!escaped && prevChar === " ") {
const endQuote = command.indexOf('"', i+1);
if (endQuote !== -1 && (endQuote === command.length-1 || command.charAt(endQuote+1) === " ")) {
args.push(command.substr(i+1, (endQuote - i - 1)));
if (endQuote === command.length-1) {
start = i = endQuote+1;
} else {
start = i = endQuote+2; // Skip the space
}
continue;
}
} else {
if (inQuote === ``) {
inQuote = `"`;
} else if (inQuote === `"`) {
inQuote = ``;
}
}
} else if (c === "'") { // Single quotes, same thing as above
if (!escaped && prevChar === " ") {
const endQuote = command.indexOf("'", i+1);
if (endQuote !== -1 && (endQuote === command.length-1 || command.charAt(endQuote+1) === " ")) {
args.push(command.substr(i+1, (endQuote - i - 1)));
if (endQuote === command.length-1) {
start = i = endQuote+1;
} else {
start = i = endQuote+2; // Skip the space
}
continue;
}
} else {
if (inQuote === ``) {
inQuote = `'`;
} else if (inQuote === `'`) {
inQuote = ``;
}
}
} else if (c === " " && inQuote === ``) {
let arg = command.substr(start, i-start);
// If this is a number, convert it from a string to number
if (isNumber(arg)) {
args.push(parseFloat(arg));
} else {
args.push(arg);
}
start = i+1;
}
++i;
}
// Add the last argument
if (start !== i) {
let arg = command.substr(start, i-start);
// If this is a number, convert it from string to number
if (isNumber(arg)) {
args.push(parseFloat(arg));
} else {
args.push(arg);
}
}
2019-02-12 01:23:46 +01:00
return args;
},
v0.51.6 (#905) * Make command `cd` without arguments an alias for `cd /` (#853) In most shells `cd` without arguments takes you to the home directory of the current user. I keep trying to do this due to muscle memory from working in terminals, so I figured I'd make it do something useful. There is no home directory in the game, but going to / is the closest thing we have, since that is the starting point for the user in the game. * Add new `backdoor` terminal command (#852) * Add the backdoor command to the terminal This command will perform a manual hack without rewarding money. It will be used for the story, mainly for faction hacking tests * Add tab completion for backdoor command * Add help text for backdoor command * Change condition syntax to be more consistent with others * Extract reused code block so it is always called after actions * Update documentation for new backdoor command Modified references to manual hack as it isn't for factions anymore * Remove extra parenthesis * Rename manuallyHacked to backdoorInstalled * Fix typo * Change faction test messages to use backdoor instad of hack * Rename more instances of manuallyHacked * fixed typo in helptext of darkweb buy (#858) * Fix typos and unify descriptions of augmentations (#859) Made an attempt to... - give all "+rep% company/faction" the same text - make all augmentations with a single effect use a single line to describe the effect - make all effects end with a period * Made Cashroot starter kit display its tooltip with the money formatted properly and in gold * fix typo in docs (#860) * Initial code for Casino Card Deck implementation * Casino Blackjack Implementation * Update some tools (eslint, typescript) * Blackjack code cleanup * Update README_contribution * Update ScriptHelpers.js (#861) expand error message * More augmentation typo fixes (#862) * Add Netscript function getCurrentScript (#856) Add netscript function that returns the current script. * Added milestones menu to guide new players. (#865) Milestone menu * fix typos in milestones (#866) Co-authored-by: sschmidTU <s.schmid@phonicscore.com> * Corrupt location title when backdoor is installed (#864) * Add corruptableText component * Corrupt location title if backdoor is installed * Formatting * Add helper to check value of backdoorInstalled Helper could be oneline but it would make it less readable * Fix some formatting * Add settings option to disable text effects * Import useState * getRunningScript (#867) * Replaced getCurrentScript with getRunningScript * Bunch of smaller fixes (#904) Fix #884 Fix #879 Fix #878 Fix #876 Fix #874 Fix #873 Fix #887 Fix #891 Fix #895 * rework the early servers to be more noob friendly (#903) * v0.51.6 Co-authored-by: Andreas Eriksson <2691182+AndreasTPC@users.noreply.github.com> Co-authored-by: Jack <jackdewinter1@gmail.com> Co-authored-by: Teun Pronk <5228255+Crownie88@users.noreply.github.com> Co-authored-by: Pimvgd <Pimvgd@gmail.com> Co-authored-by: Daniel Xie <daniel.xie@flockfreight.com> Co-authored-by: Simon <33069673+sschmidTU@users.noreply.github.com> Co-authored-by: sschmidTU <s.schmid@phonicscore.com>
2021-04-29 02:07:26 +02:00
executeCommand : function(command) {
if (Terminal.hackFlag || Terminal.backdoorFlag || Terminal.analyzeFlag) {
2019-07-16 06:40:13 +02:00
postError(`Cannot execute command (${command}) while an action is in progress`);
return;
}
// Allow usage of ./
2017-07-22 00:54:55 +02:00
if (command.startsWith("./")) {
command = "run " + command.slice(2);
2017-07-22 00:54:55 +02:00
}
// Only split the first space
var commandArray = Terminal.parseCommandArguments(command);
if (commandArray.length == 0) { return; }
2017-05-06 08:24:01 +02:00
/****************** Interactive Tutorial Terminal Commands ******************/
if (ITutorial.isRunning) {
2021-06-12 10:23:15 +02:00
var n00dlesServ = GetServerByHostname("n00dles");
if (n00dlesServ == null) {throw new Error("Could not get n00dles server"); return;}
switch(ITutorial.currStep) {
2017-05-06 08:24:01 +02:00
case iTutorialSteps.TerminalHelp:
if (commandArray.length === 1 && commandArray[0] == "help") {
2017-07-22 00:54:55 +02:00
post(TerminalHelpText);
2017-05-06 08:24:01 +02:00
iTutorialNextStep();
2017-05-16 05:31:05 +02:00
} else {post("Bad command. Please follow the tutorial");}
2017-05-06 08:24:01 +02:00
break;
case iTutorialSteps.TerminalLs:
if (commandArray.length === 1 && commandArray[0] == "ls") {
2017-05-06 08:24:01 +02:00
Terminal.executeListCommand(commandArray);
iTutorialNextStep();
2017-05-16 05:31:05 +02:00
} else {post("Bad command. Please follow the tutorial");}
2017-05-06 08:24:01 +02:00
break;
case iTutorialSteps.TerminalScan:
if (commandArray.length === 1 && commandArray[0] == "scan") {
2017-05-06 08:24:01 +02:00
Terminal.executeScanCommand(commandArray);
iTutorialNextStep();
2017-05-16 05:31:05 +02:00
} else {post("Bad command. Please follow the tutorial");}
2017-05-06 08:24:01 +02:00
break;
case iTutorialSteps.TerminalScanAnalyze1:
if (commandArray.length == 1 && commandArray[0] == "scan-analyze") {
Terminal.executeScanAnalyzeCommand(1);
iTutorialNextStep();
} else {post("Bad command. Please follow the tutorial");}
break;
case iTutorialSteps.TerminalScanAnalyze2:
if (commandArray.length == 2 && commandArray[0] == "scan-analyze" &&
commandArray[1] === 2) {
Terminal.executeScanAnalyzeCommand(2);
iTutorialNextStep();
} else {post("Bad command. Please follow the tutorial");}
break;
2017-05-06 08:24:01 +02:00
case iTutorialSteps.TerminalConnect:
if (commandArray.length == 2) {
if ((commandArray[0] == "connect") &&
2021-06-12 10:23:15 +02:00
(commandArray[1] == "n00dles" || commandArray[1] == n00dlesServ.ip)) {
2017-05-06 08:24:01 +02:00
Player.getCurrentServer().isConnectedTo = false;
2021-06-12 10:23:15 +02:00
Player.currentServer = n00dlesServ.ip;
2017-05-06 08:24:01 +02:00
Player.getCurrentServer().isConnectedTo = true;
2021-06-12 10:23:15 +02:00
post("Connected to n00dles");
2017-05-06 08:24:01 +02:00
iTutorialNextStep();
} else {post("Wrong command! Try again!"); return;}
2017-05-16 05:31:05 +02:00
} else {post("Bad command. Please follow the tutorial");}
2017-05-06 08:24:01 +02:00
break;
case iTutorialSteps.TerminalAnalyze:
if (commandArray.length === 1 && commandArray[0] === "analyze") {
if (commandArray.length !== 1) {
post("Incorrect usage of analyze command. Usage: analyze");
return;
2017-05-06 08:24:01 +02:00
}
Terminal.startAnalyze();
2017-05-06 08:24:01 +02:00
iTutorialNextStep();
} else {
2017-05-16 05:31:05 +02:00
post("Bad command. Please follow the tutorial");
2017-05-06 08:24:01 +02:00
}
break;
case iTutorialSteps.TerminalNuke:
if (commandArray.length == 2 &&
2017-05-06 08:24:01 +02:00
commandArray[0] == "run" && commandArray[1] == "NUKE.exe") {
2021-06-12 10:23:15 +02:00
n00dlesServ.hasAdminRights = true;
post("NUKE successful! Gained root access to n00dles");
2017-05-06 08:24:01 +02:00
iTutorialNextStep();
2017-05-16 05:31:05 +02:00
} else {post("Bad command. Please follow the tutorial");}
2017-05-06 08:24:01 +02:00
break;
case iTutorialSteps.TerminalManualHack:
if (commandArray.length == 1 && commandArray[0] == "hack") {
Terminal.startHack();
2017-05-06 08:24:01 +02:00
iTutorialNextStep();
2017-05-16 05:31:05 +02:00
} else {post("Bad command. Please follow the tutorial");}
break;
2017-05-06 08:24:01 +02:00
case iTutorialSteps.TerminalCreateScript:
if (commandArray.length == 2 &&
2021-06-12 10:23:15 +02:00
commandArray[0] == "nano" && commandArray[1] == "n00dles.script") {
Engine.loadScriptEditorContent("n00dles.script", "");
2017-05-06 08:24:01 +02:00
iTutorialNextStep();
2017-05-16 05:31:05 +02:00
} else {post("Bad command. Please follow the tutorial");}
break;
2017-05-06 08:24:01 +02:00
case iTutorialSteps.TerminalFree:
if (commandArray.length == 1 && commandArray[0] == "free") {
Terminal.executeFreeCommand(commandArray);
iTutorialNextStep();
} else {post("Bad command. Please follow the tutorial");}
2017-05-06 08:24:01 +02:00
break;
case iTutorialSteps.TerminalRunScript:
if (commandArray.length == 2 &&
2021-06-12 10:23:15 +02:00
commandArray[0] == "run" && commandArray[1] == "n00dles.script") {
2019-02-12 01:23:46 +01:00
Terminal.runScript(commandArray);
2017-05-06 08:24:01 +02:00
iTutorialNextStep();
2017-05-16 05:31:05 +02:00
} else {post("Bad command. Please follow the tutorial");}
2017-05-06 08:24:01 +02:00
break;
case iTutorialSteps.ActiveScriptsToTerminal:
if (commandArray.length == 2 &&
2021-06-12 10:23:15 +02:00
commandArray[0] == "tail" && commandArray[1] == "n00dles.script") {
// Check that the script exists on this machine
2021-06-12 10:23:15 +02:00
var runningScript = findRunningScript("n00dles.script", [], Player.getCurrentServer());
2017-06-18 23:01:23 +02:00
if (runningScript == null) {
post("Error: No such script exists");
return;
2017-05-06 08:24:01 +02:00
}
2017-06-18 23:01:23 +02:00
logBoxCreate(runningScript);
2017-05-06 08:24:01 +02:00
iTutorialNextStep();
2017-05-16 05:31:05 +02:00
} else {post("Bad command. Please follow the tutorial");}
2017-05-06 08:24:01 +02:00
break;
default:
2017-05-06 08:24:01 +02:00
post("Please follow the tutorial, or click 'Exit Tutorial' if you'd like to skip it");
return;
}
return;
}
2017-05-06 08:24:01 +02:00
/****************** END INTERACTIVE TUTORIAL ******************/
2017-05-06 08:24:01 +02:00
/* Command parser */
var s = Player.getCurrentServer();
switch (commandArray[0].toLowerCase()) {
2017-05-23 05:50:06 +02:00
case "alias":
if (commandArray.length === 1) {
2017-05-23 05:50:06 +02:00
printAliases();
return;
}
if (commandArray.length === 2) {
if (parseAliasDeclaration(commandArray[1])) {
post(`Set alias ${commandArray[1]}`);
return;
}
}
if (commandArray.length === 3) {
if (commandArray[1] === "-g") {
if (parseAliasDeclaration(commandArray[2], true)) {
2021-05-08 18:44:21 +02:00
post(`Set global alias ${commandArray[2]}`);
return;
}
}
2017-05-23 05:50:06 +02:00
}
postError('Incorrect usage of alias command. Usage: alias [-g] [aliasname="value"]');
2017-05-23 05:50:06 +02:00
break;
case "analyze":
if (commandArray.length !== 1) {
post("Incorrect usage of analyze command. Usage: analyze");
return;
}
Terminal.startAnalyze();
v0.51.6 (#905) * Make command `cd` without arguments an alias for `cd /` (#853) In most shells `cd` without arguments takes you to the home directory of the current user. I keep trying to do this due to muscle memory from working in terminals, so I figured I'd make it do something useful. There is no home directory in the game, but going to / is the closest thing we have, since that is the starting point for the user in the game. * Add new `backdoor` terminal command (#852) * Add the backdoor command to the terminal This command will perform a manual hack without rewarding money. It will be used for the story, mainly for faction hacking tests * Add tab completion for backdoor command * Add help text for backdoor command * Change condition syntax to be more consistent with others * Extract reused code block so it is always called after actions * Update documentation for new backdoor command Modified references to manual hack as it isn't for factions anymore * Remove extra parenthesis * Rename manuallyHacked to backdoorInstalled * Fix typo * Change faction test messages to use backdoor instad of hack * Rename more instances of manuallyHacked * fixed typo in helptext of darkweb buy (#858) * Fix typos and unify descriptions of augmentations (#859) Made an attempt to... - give all "+rep% company/faction" the same text - make all augmentations with a single effect use a single line to describe the effect - make all effects end with a period * Made Cashroot starter kit display its tooltip with the money formatted properly and in gold * fix typo in docs (#860) * Initial code for Casino Card Deck implementation * Casino Blackjack Implementation * Update some tools (eslint, typescript) * Blackjack code cleanup * Update README_contribution * Update ScriptHelpers.js (#861) expand error message * More augmentation typo fixes (#862) * Add Netscript function getCurrentScript (#856) Add netscript function that returns the current script. * Added milestones menu to guide new players. (#865) Milestone menu * fix typos in milestones (#866) Co-authored-by: sschmidTU <s.schmid@phonicscore.com> * Corrupt location title when backdoor is installed (#864) * Add corruptableText component * Corrupt location title if backdoor is installed * Formatting * Add helper to check value of backdoorInstalled Helper could be oneline but it would make it less readable * Fix some formatting * Add settings option to disable text effects * Import useState * getRunningScript (#867) * Replaced getCurrentScript with getRunningScript * Bunch of smaller fixes (#904) Fix #884 Fix #879 Fix #878 Fix #876 Fix #874 Fix #873 Fix #887 Fix #891 Fix #895 * rework the early servers to be more noob friendly (#903) * v0.51.6 Co-authored-by: Andreas Eriksson <2691182+AndreasTPC@users.noreply.github.com> Co-authored-by: Jack <jackdewinter1@gmail.com> Co-authored-by: Teun Pronk <5228255+Crownie88@users.noreply.github.com> Co-authored-by: Pimvgd <Pimvgd@gmail.com> Co-authored-by: Daniel Xie <daniel.xie@flockfreight.com> Co-authored-by: Simon <33069673+sschmidTU@users.noreply.github.com> Co-authored-by: sschmidTU <s.schmid@phonicscore.com>
2021-04-29 02:07:26 +02:00
break;
case "backdoor":
if (commandArray.length !== 1) {
post("Incorrect usage of backdoor command. Usage: backdoor");
return;
}
if (s.purchasedByPlayer) {
postError("Cannot use backdoor on your own machines! You are currently connected to your home PC or one of your purchased servers");
} else if (!s.hasAdminRights) {
postError("You do not have admin rights for this machine! Cannot backdoor");
} else if (s.requiredHackingSkill > Player.hacking_skill) {
postError("Your hacking skill is not high enough to use backdoor on this machine. Try analyzing the machine to determine the required hacking skill");
} else if (s instanceof HacknetServer) {
postError("Cannot use backdoor on this type of Server")
} else {
Terminal.startBackdoor();
}
break;
2017-05-05 17:50:55 +02:00
case "buy":
if (SpecialServerIps.hasOwnProperty("Darkweb Server")) {
executeDarkwebTerminalCommand(commandArray);
} else {
postError("You need to be able to connect to the Dark Web to use the buy command. (Maybe there's a TOR router you can buy somewhere)");
}
break;
case "cat": {
try {
if (commandArray.length !== 2) {
postError("Incorrect usage of cat command. Usage: cat [file]");
return;
}
const filename = Terminal.getFilepath(commandArray[1]);
if (!filename.endsWith(".msg") && !filename.endsWith(".lit") && !filename.endsWith(".txt")) {
postError("Only .msg, .txt, and .lit files are viewable with cat (filename must end with .msg, .txt, or .lit)");
return;
}
if (filename.endsWith(".msg") || filename.endsWith(".lit")) {
for (let i = 0; i < s.messages.length; ++i) {
if (filename.endsWith(".lit") && s.messages[i] === filename) {
showLiterature(s.messages[i]);
return;
} else if (filename.endsWith(".msg") && s.messages[i].filename === filename) {
showMessage(s.messages[i]);
return;
}
}
} else if (filename.endsWith(".txt")) {
const txt = Terminal.getTextFile(filename);
if (txt != null) {
txt.show();
return;
}
}
postError(`No such file ${filename}`);
} catch(e) {
Terminal.postThrownError(e);
}
break;
}
case "cd": {
v0.51.6 (#905) * Make command `cd` without arguments an alias for `cd /` (#853) In most shells `cd` without arguments takes you to the home directory of the current user. I keep trying to do this due to muscle memory from working in terminals, so I figured I'd make it do something useful. There is no home directory in the game, but going to / is the closest thing we have, since that is the starting point for the user in the game. * Add new `backdoor` terminal command (#852) * Add the backdoor command to the terminal This command will perform a manual hack without rewarding money. It will be used for the story, mainly for faction hacking tests * Add tab completion for backdoor command * Add help text for backdoor command * Change condition syntax to be more consistent with others * Extract reused code block so it is always called after actions * Update documentation for new backdoor command Modified references to manual hack as it isn't for factions anymore * Remove extra parenthesis * Rename manuallyHacked to backdoorInstalled * Fix typo * Change faction test messages to use backdoor instad of hack * Rename more instances of manuallyHacked * fixed typo in helptext of darkweb buy (#858) * Fix typos and unify descriptions of augmentations (#859) Made an attempt to... - give all "+rep% company/faction" the same text - make all augmentations with a single effect use a single line to describe the effect - make all effects end with a period * Made Cashroot starter kit display its tooltip with the money formatted properly and in gold * fix typo in docs (#860) * Initial code for Casino Card Deck implementation * Casino Blackjack Implementation * Update some tools (eslint, typescript) * Blackjack code cleanup * Update README_contribution * Update ScriptHelpers.js (#861) expand error message * More augmentation typo fixes (#862) * Add Netscript function getCurrentScript (#856) Add netscript function that returns the current script. * Added milestones menu to guide new players. (#865) Milestone menu * fix typos in milestones (#866) Co-authored-by: sschmidTU <s.schmid@phonicscore.com> * Corrupt location title when backdoor is installed (#864) * Add corruptableText component * Corrupt location title if backdoor is installed * Formatting * Add helper to check value of backdoorInstalled Helper could be oneline but it would make it less readable * Fix some formatting * Add settings option to disable text effects * Import useState * getRunningScript (#867) * Replaced getCurrentScript with getRunningScript * Bunch of smaller fixes (#904) Fix #884 Fix #879 Fix #878 Fix #876 Fix #874 Fix #873 Fix #887 Fix #891 Fix #895 * rework the early servers to be more noob friendly (#903) * v0.51.6 Co-authored-by: Andreas Eriksson <2691182+AndreasTPC@users.noreply.github.com> Co-authored-by: Jack <jackdewinter1@gmail.com> Co-authored-by: Teun Pronk <5228255+Crownie88@users.noreply.github.com> Co-authored-by: Pimvgd <Pimvgd@gmail.com> Co-authored-by: Daniel Xie <daniel.xie@flockfreight.com> Co-authored-by: Simon <33069673+sschmidTU@users.noreply.github.com> Co-authored-by: sschmidTU <s.schmid@phonicscore.com>
2021-04-29 02:07:26 +02:00
if (commandArray.length > 2) {
postError("Incorrect number of arguments. Usage: cd [dir]");
} else {
v0.51.6 (#905) * Make command `cd` without arguments an alias for `cd /` (#853) In most shells `cd` without arguments takes you to the home directory of the current user. I keep trying to do this due to muscle memory from working in terminals, so I figured I'd make it do something useful. There is no home directory in the game, but going to / is the closest thing we have, since that is the starting point for the user in the game. * Add new `backdoor` terminal command (#852) * Add the backdoor command to the terminal This command will perform a manual hack without rewarding money. It will be used for the story, mainly for faction hacking tests * Add tab completion for backdoor command * Add help text for backdoor command * Change condition syntax to be more consistent with others * Extract reused code block so it is always called after actions * Update documentation for new backdoor command Modified references to manual hack as it isn't for factions anymore * Remove extra parenthesis * Rename manuallyHacked to backdoorInstalled * Fix typo * Change faction test messages to use backdoor instad of hack * Rename more instances of manuallyHacked * fixed typo in helptext of darkweb buy (#858) * Fix typos and unify descriptions of augmentations (#859) Made an attempt to... - give all "+rep% company/faction" the same text - make all augmentations with a single effect use a single line to describe the effect - make all effects end with a period * Made Cashroot starter kit display its tooltip with the money formatted properly and in gold * fix typo in docs (#860) * Initial code for Casino Card Deck implementation * Casino Blackjack Implementation * Update some tools (eslint, typescript) * Blackjack code cleanup * Update README_contribution * Update ScriptHelpers.js (#861) expand error message * More augmentation typo fixes (#862) * Add Netscript function getCurrentScript (#856) Add netscript function that returns the current script. * Added milestones menu to guide new players. (#865) Milestone menu * fix typos in milestones (#866) Co-authored-by: sschmidTU <s.schmid@phonicscore.com> * Corrupt location title when backdoor is installed (#864) * Add corruptableText component * Corrupt location title if backdoor is installed * Formatting * Add helper to check value of backdoorInstalled Helper could be oneline but it would make it less readable * Fix some formatting * Add settings option to disable text effects * Import useState * getRunningScript (#867) * Replaced getCurrentScript with getRunningScript * Bunch of smaller fixes (#904) Fix #884 Fix #879 Fix #878 Fix #876 Fix #874 Fix #873 Fix #887 Fix #891 Fix #895 * rework the early servers to be more noob friendly (#903) * v0.51.6 Co-authored-by: Andreas Eriksson <2691182+AndreasTPC@users.noreply.github.com> Co-authored-by: Jack <jackdewinter1@gmail.com> Co-authored-by: Teun Pronk <5228255+Crownie88@users.noreply.github.com> Co-authored-by: Pimvgd <Pimvgd@gmail.com> Co-authored-by: Daniel Xie <daniel.xie@flockfreight.com> Co-authored-by: Simon <33069673+sschmidTU@users.noreply.github.com> Co-authored-by: sschmidTU <s.schmid@phonicscore.com>
2021-04-29 02:07:26 +02:00
let dir = commandArray.length === 2 ? commandArray[1] : "/";
let evaledDir;
if (dir === "/") {
evaledDir = "/";
} else {
// Ignore trailing slashes
dir = removeTrailingSlash(dir);
evaledDir = evaluateDirectoryPath(dir, Terminal.currDir);
if (evaledDir == null || evaledDir === "") {
postError("Invalid path. Failed to change directories");
return;
}
v0.51.6 (#905) * Make command `cd` without arguments an alias for `cd /` (#853) In most shells `cd` without arguments takes you to the home directory of the current user. I keep trying to do this due to muscle memory from working in terminals, so I figured I'd make it do something useful. There is no home directory in the game, but going to / is the closest thing we have, since that is the starting point for the user in the game. * Add new `backdoor` terminal command (#852) * Add the backdoor command to the terminal This command will perform a manual hack without rewarding money. It will be used for the story, mainly for faction hacking tests * Add tab completion for backdoor command * Add help text for backdoor command * Change condition syntax to be more consistent with others * Extract reused code block so it is always called after actions * Update documentation for new backdoor command Modified references to manual hack as it isn't for factions anymore * Remove extra parenthesis * Rename manuallyHacked to backdoorInstalled * Fix typo * Change faction test messages to use backdoor instad of hack * Rename more instances of manuallyHacked * fixed typo in helptext of darkweb buy (#858) * Fix typos and unify descriptions of augmentations (#859) Made an attempt to... - give all "+rep% company/faction" the same text - make all augmentations with a single effect use a single line to describe the effect - make all effects end with a period * Made Cashroot starter kit display its tooltip with the money formatted properly and in gold * fix typo in docs (#860) * Initial code for Casino Card Deck implementation * Casino Blackjack Implementation * Update some tools (eslint, typescript) * Blackjack code cleanup * Update README_contribution * Update ScriptHelpers.js (#861) expand error message * More augmentation typo fixes (#862) * Add Netscript function getCurrentScript (#856) Add netscript function that returns the current script. * Added milestones menu to guide new players. (#865) Milestone menu * fix typos in milestones (#866) Co-authored-by: sschmidTU <s.schmid@phonicscore.com> * Corrupt location title when backdoor is installed (#864) * Add corruptableText component * Corrupt location title if backdoor is installed * Formatting * Add helper to check value of backdoorInstalled Helper could be oneline but it would make it less readable * Fix some formatting * Add settings option to disable text effects * Import useState * getRunningScript (#867) * Replaced getCurrentScript with getRunningScript * Bunch of smaller fixes (#904) Fix #884 Fix #879 Fix #878 Fix #876 Fix #874 Fix #873 Fix #887 Fix #891 Fix #895 * rework the early servers to be more noob friendly (#903) * v0.51.6 Co-authored-by: Andreas Eriksson <2691182+AndreasTPC@users.noreply.github.com> Co-authored-by: Jack <jackdewinter1@gmail.com> Co-authored-by: Teun Pronk <5228255+Crownie88@users.noreply.github.com> Co-authored-by: Pimvgd <Pimvgd@gmail.com> Co-authored-by: Daniel Xie <daniel.xie@flockfreight.com> Co-authored-by: Simon <33069673+sschmidTU@users.noreply.github.com> Co-authored-by: sschmidTU <s.schmid@phonicscore.com>
2021-04-29 02:07:26 +02:00
const server = Player.getCurrentServer();
if(!server.scripts.some(script => script.filename.startsWith(evaledDir)) &&
!server.textFiles.some(file => file.fn.startsWith(evaledDir))) {
v0.51.6 (#905) * Make command `cd` without arguments an alias for `cd /` (#853) In most shells `cd` without arguments takes you to the home directory of the current user. I keep trying to do this due to muscle memory from working in terminals, so I figured I'd make it do something useful. There is no home directory in the game, but going to / is the closest thing we have, since that is the starting point for the user in the game. * Add new `backdoor` terminal command (#852) * Add the backdoor command to the terminal This command will perform a manual hack without rewarding money. It will be used for the story, mainly for faction hacking tests * Add tab completion for backdoor command * Add help text for backdoor command * Change condition syntax to be more consistent with others * Extract reused code block so it is always called after actions * Update documentation for new backdoor command Modified references to manual hack as it isn't for factions anymore * Remove extra parenthesis * Rename manuallyHacked to backdoorInstalled * Fix typo * Change faction test messages to use backdoor instad of hack * Rename more instances of manuallyHacked * fixed typo in helptext of darkweb buy (#858) * Fix typos and unify descriptions of augmentations (#859) Made an attempt to... - give all "+rep% company/faction" the same text - make all augmentations with a single effect use a single line to describe the effect - make all effects end with a period * Made Cashroot starter kit display its tooltip with the money formatted properly and in gold * fix typo in docs (#860) * Initial code for Casino Card Deck implementation * Casino Blackjack Implementation * Update some tools (eslint, typescript) * Blackjack code cleanup * Update README_contribution * Update ScriptHelpers.js (#861) expand error message * More augmentation typo fixes (#862) * Add Netscript function getCurrentScript (#856) Add netscript function that returns the current script. * Added milestones menu to guide new players. (#865) Milestone menu * fix typos in milestones (#866) Co-authored-by: sschmidTU <s.schmid@phonicscore.com> * Corrupt location title when backdoor is installed (#864) * Add corruptableText component * Corrupt location title if backdoor is installed * Formatting * Add helper to check value of backdoorInstalled Helper could be oneline but it would make it less readable * Fix some formatting * Add settings option to disable text effects * Import useState * getRunningScript (#867) * Replaced getCurrentScript with getRunningScript * Bunch of smaller fixes (#904) Fix #884 Fix #879 Fix #878 Fix #876 Fix #874 Fix #873 Fix #887 Fix #891 Fix #895 * rework the early servers to be more noob friendly (#903) * v0.51.6 Co-authored-by: Andreas Eriksson <2691182+AndreasTPC@users.noreply.github.com> Co-authored-by: Jack <jackdewinter1@gmail.com> Co-authored-by: Teun Pronk <5228255+Crownie88@users.noreply.github.com> Co-authored-by: Pimvgd <Pimvgd@gmail.com> Co-authored-by: Daniel Xie <daniel.xie@flockfreight.com> Co-authored-by: Simon <33069673+sschmidTU@users.noreply.github.com> Co-authored-by: sschmidTU <s.schmid@phonicscore.com>
2021-04-29 02:07:26 +02:00
postError("Invalid path. Failed to change directories");
return;
}
}
Terminal.currDir = evaledDir;
// Reset input to update current directory on UI
Terminal.resetTerminalInput();
}
break;
}
case "check": {
try {
if (commandArray.length < 2) {
postError("Incorrect number of arguments. Usage: check [script] [arg1] [arg2]...");
} else {
const scriptName = Terminal.getFilepath(commandArray[1]);
// Can only tail script files
if (!isScriptFilename(scriptName)) {
postError("tail can only be called on .script files (filename must end with .script)");
return;
}
// Get args
let args = [];
for (var i = 2; i < commandArray.length; ++i) {
args.push(commandArray[i]);
}
// Check that the script exists on this machine
var runningScript = findRunningScript(scriptName, args, s);
if (runningScript == null) {
postError("No such script exists");
return;
}
runningScript.displayLog();
}
} catch(e) {
Terminal.postThrownError(e);
}
2017-05-05 17:50:55 +02:00
break;
}
case "clear":
case "cls":
if (commandArray.length !== 1) {
postError("Incorrect usage of clear/cls command. Usage: clear/cls");
return;
}
$("#terminal tr:not(:last)").remove();
postNetburnerText();
break;
case "connect": {
// Disconnect from current server in terminal and connect to new one
if (commandArray.length !== 2) {
postError("Incorrect usage of connect command. Usage: connect [ip/hostname]");
return;
}
let ip = commandArray[1];
for (let i = 0; i < s.serversOnNetwork.length; i++) {
if (getServerOnNetwork(s, i).ip == ip || getServerOnNetwork(s, i).hostname == ip) {
Terminal.connectToServer(ip);
return;
}
}
postError("Host not found");
break;
}
case "download": {
try {
if (commandArray.length !== 2) {
postError("Incorrect usage of download command. Usage: download [script/text file]");
return;
2018-03-12 20:39:04 +01:00
}
const fn = commandArray[1];
if (fn === "*" || fn === "*.script" || fn === "*.txt") {
// Download all scripts as a zip
var zip = new JSZip();
if (fn === "*" || fn === "*.script") {
for (var i = 0; i < s.scripts.length; ++i) {
var file = new Blob([s.scripts[i].code], {type:"text/plain"});
zip.file(s.scripts[i].filename + ".js", file);
}
}
if (fn === "*" || fn === "*.txt") {
for (var i = 0; i < s.textFiles.length; ++i) {
var file = new Blob([s.textFiles[i].text], {type:"text/plain"});
zip.file(s.textFiles[i].fn, file);
}
2018-03-12 20:39:04 +01:00
}
let zipFn;
switch (fn) {
case "*.script":
zipFn = "bitburnerScripts.zip"; break;
case "*.txt":
zipFn = "bitburnerTexts.zip"; break;
default:
zipFn = "bitburnerFiles.zip"; break;
}
2018-03-12 20:39:04 +01:00
zip.generateAsync({type:"blob"}).then(function(content) {
FileSaver.saveAs(content, zipFn);
});
return;
} else if (isScriptFilename(fn)) {
// Download a single script
const script = Terminal.getScript(fn);
if (script != null) {
return script.download();
2018-02-15 05:26:43 +01:00
}
} else if (fn.endsWith(".txt")) {
// Download a single text file
const txt = Terminal.getTextFile(fn);
if (txt != null) {
return txt.download();
}
} else {
postError(`Cannot download this filetype`);
return;
2018-02-15 05:26:43 +01:00
}
postError(`${fn} does not exist`);
} catch(e) {
Terminal.postThrownError(e);
}
break;
}
case "expr": {
if (commandArray.length <= 1) {
postError("Incorrect usage of expr command. Usage: expr [math expression]");
return;
}
let expr = commandArray.slice(1).join("");
// Sanitize the math expression
let sanitizedExpr = expr.replace(/s+/g, '').replace(/[^-()\d/*+.]/g, '');
let result;
try {
result = eval(sanitizedExpr);
} catch(e) {
postError(`Could not evaluate expression: ${sanitizedExpr}`);
return;
}
post(result);
break;
}
case "free":
Terminal.executeFreeCommand(commandArray);
break;
case "hack": {
if (commandArray.length !== 1) {
postError("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 (s.purchasedByPlayer) {
postError("Cannot hack your own machines! You are currently connected to your home PC or one of your purchased servers");
} else if (s.hasAdminRights == false ) {
postError("You do not have admin rights for this machine! Cannot hack");
} else if (s.requiredHackingSkill > Player.hacking_skill) {
postError("Your hacking skill is not high enough to attempt hacking this machine. Try analyzing the machine to determine the required hacking skill");
} else if (s instanceof HacknetServer) {
postError("Cannot hack this type of Server")
} else {
Terminal.startHack();
}
break;
}
case "help":
if (commandArray.length !== 1 && commandArray.length !== 2) {
postError("Incorrect usage of help command. Usage: help");
return;
}
if (commandArray.length === 1) {
2017-07-22 00:54:55 +02:00
post(TerminalHelpText);
} else {
var cmd = commandArray[1];
var txt = HelpTexts[cmd];
if (txt == null) {
postError("No help topics match '" + cmd + "'");
2017-07-22 00:54:55 +02:00
return;
}
post(txt);
}
break;
case "home":
if (commandArray.length !== 1) {
postError("Incorrect usage of home command. Usage: home");
return;
}
Player.getCurrentServer().isConnectedTo = false;
Player.currentServer = Player.getHomeComputer().ip;
Player.getCurrentServer().isConnectedTo = true;
post("Connected to home");
Terminal.currDir = "/";
2017-09-13 16:22:22 +02:00
Terminal.resetTerminalInput();
break;
case "hostname":
if (commandArray.length !== 1) {
postError("Incorrect usage of hostname command. Usage: hostname");
return;
}
post(Player.getCurrentServer().hostname);
break;
case "ifconfig":
if (commandArray.length !== 1) {
postError("Incorrect usage of ifconfig command. Usage: ifconfig");
return;
}
post(Player.getCurrentServer().ip);
break;
case "kill": {
Terminal.executeKillCommand(commandArray);
break;
}
case "killall": {
for (let i = s.runningScripts.length - 1; i >= 0; --i) {
killWorkerScript(s.runningScripts[i], s.ip, false);
2017-06-05 19:59:30 +02:00
}
WorkerScriptStartStopEventEmitter.emitEvent();
post("Killing all running scripts");
2017-06-05 19:59:30 +02:00
break;
}
case "ls": {
2017-05-06 08:24:01 +02:00
Terminal.executeListCommand(commandArray);
break;
}
case "lscpu": {
2017-10-10 06:56:48 +02:00
post(Player.getCurrentServer().cpuCores + " Core(s)");
break;
}
case "mem": {
Terminal.executeMemCommand(commandArray);
2017-05-15 04:46:52 +02:00
break;
}
case "mv": {
if (commandArray.length !== 3) {
postError(`Incorrect number of arguments. Usage: mv [src] [dest]`);
return;
}
try {
const source = commandArray[1];
const dest = commandArray[2];
if (!isScriptFilename(source) && !source.endsWith(".txt")) {
postError(`'mv' can only be used on scripts and text files (.txt)`);
return;
}
const srcFile = Terminal.getFile(source);
if (srcFile == null) {
postError(`Source file ${source} does not exist`);
return;
}
const sourcePath = Terminal.getFilepath(source);
const destPath = Terminal.getFilepath(dest);
const destFile = Terminal.getFile(dest);
// 'mv' command only works on scripts and txt files.
// Also, you can't convert between different file types
if (isScriptFilename(source)) {
if (!isScriptFilename(dest)) {
postError(`Source and destination files must have the same type`);
return;
}
// Command doesnt work if script is running
if (s.isRunning(sourcePath)) {
postError(`Cannot use 'mv' on a script that is running`);
return;
}
if (destFile != null) {
// Already exists, will be overwritten, so we'll delete it
const status = s.removeFile(destPath);
if (!status.res) {
postError(`Something went wrong...please contact game dev (probably a bug)`);
return;
} else {
post("Warning: The destination file was overwritten");
}
}
srcFile.filename = destPath;
} else if (source.endsWith(".txt")) {
if (!dest.endsWith(".txt")) {
postError(`Source and destination files must have the same type`);
return;
}
if (destFile != null) {
// Already exists, will be overwritten, so we'll delete it
const status = s.removeFile(destPath);
if (!status.res) {
postError(`Something went wrong...please contact game dev (probably a bug)`);
return;
} else {
post("Warning: The destination file was overwritten");
}
}
srcFile.fn = destPath;
}
} catch(e) {
Terminal.postThrownError(e);
}
break;
}
case "nano":
Terminal.executeNanoCommand(commandArray);
break;
case "ps":
if (commandArray.length !== 1) {
postError("Incorrect usage of ps command. Usage: ps");
return;
}
for (let i = 0; i < s.runningScripts.length; i++) {
let rsObj = s.runningScripts[i];
let res = `(PID - ${rsObj.pid}) ${rsObj.filename}`;
for (let j = 0; j < rsObj.args.length; ++j) {
res += (" " + rsObj.args[j].toString());
}
post(res);
}
break;
case "rm": {
if (commandArray.length !== 2) {
postError("Incorrect number of arguments. Usage: rm [program/script]");
return;
}
// Check programs
let delTarget, status;
try {
delTarget = Terminal.getFilepath(commandArray[1]);
status = s.removeFile(delTarget);
} catch(err) {
status = {
res: false,
msg: 'No such file exists',
};
}
if (!status.res) {
postError(status.msg);
}
break;
}
case "run":
// Run a program or a script
if (commandArray.length < 2) {
postError("Incorrect number of arguments. Usage: run [program/script] [-t] [num threads] [arg1] [arg2]...");
} else {
var executableName = commandArray[1];
// Secret Music player!
if (executableName === "musicplayer") {
post('<iframe src="https://open.spotify.com/embed/user/danielyxie/playlist/1ORnnL6YNvXOracUaUV2kh" width="300" height="380" frameborder="0" allowtransparency="true"></iframe>', false);
return;
}
// Check if its a script or just a program/executable
if (isScriptFilename(executableName)) {
Terminal.runScript(commandArray);
} else if (executableName.endsWith(".cct")) {
Terminal.runContract(executableName);
} else {
2019-02-20 09:42:27 +01:00
Terminal.runProgram(commandArray);
}
}
break;
case "scan":
Terminal.executeScanCommand(commandArray);
break;
case "scan-analyze":
if (commandArray.length === 1) {
Terminal.executeScanAnalyzeCommand(1);
} else {
// # of args must be 2 or 3
if (commandArray.length > 3) {
postError("Incorrect usage of scan-analyze command. usage: scan-analyze [depth]");
return;
2017-09-19 20:38:03 +02:00
}
let all = false;
if (commandArray.length === 3 && commandArray[2] === "-a") {
all = true;
2017-09-19 20:38:03 +02:00
}
let depth = parseInt(commandArray[1]);
if (isNaN(depth) || depth < 0) {
postError("Incorrect usage of scan-analyze command. depth argument must be positive numeric");
return;
}
2018-06-02 01:31:34 +02:00
if (depth > 3 && !Player.hasProgram(Programs.DeepscanV1.name) &&
!Player.hasProgram(Programs.DeepscanV2.name)) {
postError("You cannot scan-analyze with that high of a depth. Maximum depth is 3");
return;
2018-06-02 01:31:34 +02:00
} else if (depth > 5 && !Player.hasProgram(Programs.DeepscanV2.name)) {
postError("You cannot scan-analyze with that high of a depth. Maximum depth is 5");
return;
} else if (depth > 10) {
postError("You cannot scan-analyze with that high of a depth. Maximum depth is 10");
return;
}
2017-09-19 20:38:03 +02:00
Terminal.executeScanAnalyzeCommand(depth, all);
}
break;
/* eslint-disable no-case-declarations */
case "scp":
Terminal.executeScpCommand(commandArray);
2018-09-08 03:53:11 +02:00
break;
/* eslint-enable no-case-declarations */
2017-05-06 08:24:01 +02:00
case "sudov":
if (commandArray.length !== 1) {
postError("Incorrect number of arguments. Usage: sudov");
return;
2017-05-06 08:24:01 +02:00
}
if (s.hasAdminRights) {
2017-05-06 08:24:01 +02:00
post("You have ROOT access to this machine");
} else {
post("You do NOT have root access to this machine");
}
break;
case "tail": {
try {
if (commandArray.length < 2) {
postError("Incorrect number of arguments. Usage: tail [script] [arg1] [arg2]...");
2021-05-03 17:58:11 +02:00
} else if(typeof commandArray[1] === 'string') {
const scriptName = Terminal.getFilepath(commandArray[1]);
if (!isScriptFilename(scriptName)) {
postError("tail can only be called on .script, .ns, .js files, or by pid");
return;
}
2021-05-03 17:58:11 +02:00
// Get script arguments
const args = [];
for (let i = 2; i < commandArray.length; ++i) {
args.push(commandArray[i]);
}
2021-06-12 11:42:18 +02:00
// go over all the running scripts. If there's a perfect
// match, use it!
for (var i = 0; i < s.runningScripts.length; ++i) {
if (s.runningScripts[i].filename === scriptName &&
compareArrays(s.runningScripts[i].args, args)) {
logBoxCreate(s.runningScripts[i]);
return;
}
}
// Find all scripts that are potential candidates.
const candidates = [];
for (var i = 0; i < s.runningScripts.length; ++i) {
// only scripts that have more arguments (equal arguments is already caught)
if(s.runningScripts[i].args.length < args.length) continue;
// make a smaller copy of the args.
const args2 = s.runningScripts[i].args.slice(0, args.length);
if (s.runningScripts[i].filename === scriptName &&
compareArrays(args2, args)) {
candidates.push(s.runningScripts[i]);
}
}
// If there's only 1 possible choice, use that.
if(candidates.length === 1) {
logBoxCreate(candidates[0]);
2021-05-03 17:58:11 +02:00
return;
}
2021-06-12 11:42:18 +02:00
// otherwise lists all possible conflicting choices.
if(candidates.length > 1) {
postError("Found several potential candidates:");
for(const candidate of candidates)
postError(`${candidate.filename} ${candidate.args.join(' ')}`);
postError("Script arguments need to be specified.");
return;
}
// if there's no candidate then we just don't know.
postError("No such script exists.");
2021-05-03 17:58:11 +02:00
} else {
const runningScript = findRunningScriptByPid(commandArray[1], Player.getCurrentServer());
if (runningScript == null) {
postError("No such script exists");
return;
}
2021-05-03 17:58:11 +02:00
logBoxCreate(runningScript);
}
} catch(e) {
Terminal.postThrownError(e);
}
break;
}
case "theme": {
let args = commandArray.slice(1);
if (args.length !== 1 && args.length !== 3) {
postError("Incorrect number of arguments.");
postError("Usage: theme [default|muted|solarized] | #[background color hex] #[text color hex] #[highlight color hex]");
} else if(args.length === 1){
2017-06-07 03:23:51 +02:00
var themeName = args[0];
2018-02-15 05:26:43 +01:00
if (themeName == "default"){
2017-06-07 03:23:51 +02:00
document.body.style.setProperty('--my-highlight-color',"#ffffff");
document.body.style.setProperty('--my-font-color',"#66ff33");
document.body.style.setProperty('--my-background-color',"#000000");
document.body.style.setProperty('--my-prompt-color', "#f92672");
2018-02-15 05:26:43 +01:00
} else if (themeName == "muted"){
2017-06-07 03:23:51 +02:00
document.body.style.setProperty('--my-highlight-color',"#ffffff");
document.body.style.setProperty('--my-font-color',"#66ff33");
document.body.style.setProperty('--my-background-color',"#252527");
2018-02-15 05:26:43 +01:00
} else if (themeName == "solarized"){
2017-06-07 03:23:51 +02:00
document.body.style.setProperty('--my-highlight-color',"#6c71c4");
document.body.style.setProperty('--my-font-color',"#839496");
document.body.style.setProperty('--my-background-color',"#002b36");
2018-02-15 05:26:43 +01:00
} else {
return postError("Theme not found");
}
FconfSettings.THEME_HIGHLIGHT_COLOR = document.body.style.getPropertyValue("--my-highlight-color");
FconfSettings.THEME_FONT_COLOR = document.body.style.getPropertyValue("--my-font-color");
FconfSettings.THEME_BACKGROUND_COLOR = document.body.style.getPropertyValue("--my-background-color");
FconfSettings.THEME_PROMPT_COLOR = document.body.style.getPropertyValue("--my-prompt-color");
2018-02-15 05:26:43 +01:00
} else {
var inputBackgroundHex = args[0];
var inputTextHex = args[1];
var inputHighlightHex = args[2];
2018-02-15 05:26:43 +01:00
if (/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(inputBackgroundHex) &&
2017-06-07 03:23:51 +02:00
/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(inputTextHex) &&
/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(inputHighlightHex)){
document.body.style.setProperty('--my-highlight-color',inputHighlightHex);
document.body.style.setProperty('--my-font-color',inputTextHex);
document.body.style.setProperty('--my-background-color',inputBackgroundHex);
FconfSettings.THEME_HIGHLIGHT_COLOR = document.body.style.getPropertyValue("--my-highlight-color");
FconfSettings.THEME_FONT_COLOR = document.body.style.getPropertyValue("--my-font-color");
FconfSettings.THEME_BACKGROUND_COLOR = document.body.style.getPropertyValue("--my-background-color");
2018-02-15 05:26:43 +01:00
} else {
return postError("Invalid Hex Input for theme");
}
2017-06-07 03:23:51 +02:00
}
break;
}
case "top": {
if (commandArray.length !== 1) {
postError("Incorrect usage of top command. Usage: top");
return;
}
// Headers
const scriptWidth = 40;
const pidWidth = 10;
const threadsWidth = 16;
const scriptTxt = "Script";
const pidTxt = "PID";
const threadsTxt = "Threads";
const ramTxt = "RAM Usage";
const spacesAfterScriptTxt = " ".repeat(scriptWidth - scriptTxt.length);
const spacesAfterPidTxt = " ".repeat(pidWidth - pidTxt.length);
const spacesAfterThreadsTxt = " ".repeat(threadsWidth - threadsTxt.length);
const headers = `${scriptTxt}${spacesAfterScriptTxt}${pidTxt}${spacesAfterPidTxt}${threadsTxt}${spacesAfterThreadsTxt}${ramTxt}`;
post(headers);
let currRunningScripts = s.runningScripts;
// Iterate through scripts on current server
for (let i = 0; i < currRunningScripts.length; i++) {
let script = currRunningScripts[i];
// Calculate name padding
const numSpacesScript = Math.max(0, scriptWidth - script.filename.length);
const spacesScript = " ".repeat(numSpacesScript);
// Calculate PID padding
const numSpacesPid = Math.max(0, pidWidth - (script.pid + "").length);
const spacesPid = " ".repeat(numSpacesPid);
// Calculate thread padding
const numSpacesThread = Math.max(0, threadsWidth - (script.threads + "").length);
const spacesThread = " ".repeat(numSpacesThread);
// Calculate and transform RAM usage
const ramUsage = numeralWrapper.formatRAM(getRamUsageFromRunningScript(script) * script.threads);
const entry = [
script.filename,
spacesScript,
script.pid,
spacesPid,
script.threads,
spacesThread,
2021-04-30 05:52:56 +02:00
ramUsage,
].join("");
post(entry);
}
break;
}
case "unalias": {
if (commandArray.length !== 2) {
postError('Incorrect usage of unalias name. Usage: unalias [alias]');
return;
} else {
if (removeAlias(commandArray[1])) {
post(`Removed alias ${commandArray[1]}`);
} else {
postError(`No such alias exists: ${commandArray[1]}`);
}
}
break;
}
case "wget": {
if (commandArray.length !== 3) {
postError("Incorrect usage of wget command. Usage: wget [url] [target file]");
return;
}
let url = commandArray[1];
let target = Terminal.getFilepath(commandArray[2]);
2018-09-08 03:53:11 +02:00
if (!isScriptFilename(target) && !target.endsWith(".txt")) {
return post(`wget failed: Invalid target file. Target file must be script or text file`);
}
$.get(url, function(data) {
2018-09-08 03:53:11 +02:00
let res;
if (isScriptFilename(target)) {
res = s.writeToScriptFile(target, data);
2018-09-08 03:53:11 +02:00
} else {
res = s.writeToTextFile(target, data);
2018-09-08 03:53:11 +02:00
}
if (!res.success) {
return post("wget failed");
}
if (res.overwritten) {
return post(`wget successfully retrieved content and overwrote ${target}`);
}
return post(`wget successfully retrieved content to new file ${target}`);
}, 'text').fail(function(e) {
return postError("wget failed: " + JSON.stringify(e));
})
break;
}
default:
postError(`Command ${commandArray[0]} not found`);
}
},
connectToServer: function(ip) {
var serv = getServer(ip);
if (serv == null) {
post("Invalid server. Connection failed.");
return;
}
Player.getCurrentServer().isConnectedTo = false;
Player.currentServer = serv.ip;
Player.getCurrentServer().isConnectedTo = true;
post("Connected to " + serv.hostname);
Terminal.currDir = "/";
if (Player.getCurrentServer().hostname == "darkweb") {
checkIfConnectedToDarkweb(); // Posts a 'help' message if connecting to dark web
}
2017-09-13 16:22:22 +02:00
Terminal.resetTerminalInput();
},
executeFreeCommand: function(commandArray) {
if (commandArray.length !== 1) {
postError("Incorrect usage of free command. Usage: free");
return;
}
const ram = numeralWrapper.formatRAM(Player.getCurrentServer().maxRam);
const used = numeralWrapper.formatRAM(Player.getCurrentServer().ramUsed);
const avail = numeralWrapper.formatRAM(Player.getCurrentServer().maxRam - Player.getCurrentServer().ramUsed);
const maxLength = Math.max(ram.length, Math.max(used.length, avail.length));
const usedPercent = numeralWrapper.formatPercentage(Player.getCurrentServer().ramUsed/Player.getCurrentServer().maxRam);
post(`Total: ${" ".repeat(maxLength-ram.length)}${ram}`);
post(`Used: ${" ".repeat(maxLength-used.length)}${used} (${usedPercent})`);
post(`Available: ${" ".repeat(maxLength-avail.length)}${avail}`);
},
executeKillCommand: function(commandArray) {
try {
if (commandArray.length < 2) {
postError("Incorrect usage of kill command. Usage: kill [scriptname] [arg1] [arg2]...");
return;
}
// Kill by PID
if (typeof commandArray[1] === "number") {
const pid = commandArray[1];
const res = killWorkerScript(pid);
if (res) {
post(`Killing script with PID ${pid}`);
} else {
post(`Failed to kill script with PID ${pid}. No such script exists`);
}
return;
}
const s = Player.getCurrentServer();
const scriptName = Terminal.getFilepath(commandArray[1]);
const args = [];
for (let i = 2; i < commandArray.length; ++i) {
args.push(commandArray[i]);
}
const runningScript = s.getRunningScript(scriptName, args);
if (runningScript == null) {
postError("No such script is running. Nothing to kill");
return;
}
killWorkerScript(runningScript, s.ip);
post(`Killing ${scriptName}`);
} catch(e) {
Terminal.postThrownError(e);
}
},
2017-05-06 08:24:01 +02:00
executeListCommand: function(commandArray) {
const numArgs = commandArray.length;
function incorrectUsage() {
postError("Incorrect usage of ls command. Usage: ls [dir] [| grep pattern]");
}
if (numArgs <= 0 || numArgs > 5 || numArgs === 3) {
return incorrectUsage();
}
// Grep
let filter = null; // Grep
// Directory path
let prefix = Terminal.currDir;
if (!prefix.endsWith("/")) {
prefix += "/";
}
// If there are 4+ arguments, then the last 3 must be for grep
if (numArgs >= 4) {
if (commandArray[numArgs - 2] !== "grep" || commandArray[numArgs - 3] !== "|") {
return incorrectUsage();
}
filter = commandArray[numArgs - 1];
}
// If the second argument is not a pipe, then it must be for listing a directory
if (numArgs >= 2 && commandArray[1] !== "|") {
prefix = evaluateDirectoryPath(commandArray[1], Terminal.currDir);
if (prefix != null) {
if (!prefix.endsWith("/")) {
prefix += "/";
}
if (!isValidDirectoryPath(prefix)) {
return incorrectUsage();
}
}
2017-05-06 08:24:01 +02:00
}
// Root directory, which is the same as no 'prefix' at all
if (prefix === "/") {
prefix = null;
}
// Display all programs and scripts
2021-05-06 02:54:15 +02:00
const allPrograms = [];
const allScripts = [];
const allTextFiles = [];
const allContracts = [];
const allMessages = [];
const folders = [];
function handleFn(fn, dest) {
let parsedFn = fn;
2019-03-29 16:50:05 +01:00
if (prefix) {
if (!fn.startsWith(prefix)) {
return;
} else {
parsedFn = fn.slice(prefix.length, fn.length);
}
}
2019-03-29 16:50:05 +01:00
if (filter && !parsedFn.includes(filter)) {
return;
}
// If the fn includes a forward slash, it must be in a subdirectory.
// Therefore, we only list the "first" directory in its path
if (parsedFn.includes("/")) {
const firstParentDir = getFirstParentDirectory(parsedFn);
if (filter && !firstParentDir.includes(filter)) {
2019-03-29 16:50:05 +01:00
return;
}
if (!folders.includes(firstParentDir)) {
folders.push(firstParentDir);
}
return;
}
2019-03-29 16:50:05 +01:00
2021-05-06 02:54:15 +02:00
dest.push(parsedFn);
}
// Get all of the programs and scripts on the machine into one temporary array
2019-03-29 16:50:05 +01:00
const s = Player.getCurrentServer();
2021-05-06 02:54:15 +02:00
for (const program of s.programs) handleFn(program, allPrograms);
for (const script of s.scripts) handleFn(script.filename, allScripts);
for (const txt of s.textFiles) handleFn(txt.fn, allTextFiles);
for (const contract of s.contracts) handleFn(contract.fn, allContracts);
for (const msgOrLit of s.messages) (msgOrLit instanceof Message) ? handleFn(msgOrLit.filename, allMessages) : handleFn(msgOrLit, allMessages);
2019-03-29 16:50:05 +01:00
// Sort the files/folders alphabetically then print each
2021-05-06 02:54:15 +02:00
allPrograms.sort();
allScripts.sort();
allTextFiles.sort();
allContracts.sort();
allMessages.sort();
folders.sort();
2021-05-06 02:54:15 +02:00
function postSegments(segments, config) {
const maxLength = Math.max(...segments.map(s => s.length))+1;
const filesPerRow = Math.floor(80 / maxLength);
for(let i = 0; i < segments.length; i++) {
let row = '';
for(let col = 0; col < filesPerRow; col++) {
if(!(i < segments.length)) break;
row += segments[i];
row += " ".repeat((maxLength * (col+1)) - row.length);
i++
}
2021-05-09 04:38:48 +02:00
i--;
2021-05-06 02:54:15 +02:00
postContent(row, config);
}
2017-05-06 08:24:01 +02:00
}
2021-05-06 02:54:15 +02:00
const config = { color: "#0000FF" };
2021-05-18 03:58:11 +02:00
const groups = [
{segments: folders, config: config},
{segments: allMessages},
{segments: allTextFiles},
{segments: allPrograms},
{segments: allContracts},
{segments: allScripts},
].filter((g) => g.segments.length > 0)
for(let i = 0; i < groups.length; i++) {
if(i !== 0) postElement(<br />);
postSegments(groups[i].segments, groups[i].config);
}
},
executeMemCommand: function(commandArray) {
try {
if (commandArray.length !== 2 && commandArray.length !== 4) {
postError("Incorrect usage of mem command. usage: mem [scriptname] [-t] [number threads]");
return;
}
const scriptName = commandArray[1];
let numThreads = 1;
if (commandArray.length === 4 && commandArray[2] === "-t") {
numThreads = Math.round(parseInt(commandArray[3]));
if (isNaN(numThreads) || numThreads < 1) {
postError("Invalid number of threads specified. Number of threads must be greater than 1");
return;
}
}
const script = Terminal.getScript(scriptName);
if (script == null) {
postError("No such script exists!");
return;
}
const ramUsage = script.ramUsage * numThreads;
post(`This script requires ${numeralWrapper.formatRAM(ramUsage)} of RAM to run for ${numThreads} thread(s)`);
} catch(e) {
Terminal.postThrownError(e);
}
},
executeNanoCommand: function(commandArray) {
if (commandArray.length !== 2) {
postError("Incorrect usage of nano command. Usage: nano [scriptname]");
return;
}
try {
const filename = commandArray[1];
if (filename === ".fconf") {
let text = createFconf();
Engine.loadScriptEditorContent(filename, text);
return;
} else if (isScriptFilename(filename)) {
const filepath = Terminal.getFilepath(filename);
const script = Terminal.getScript(filename);
if (script == null) {
let code = ""
if(filename.endsWith(".ns") || filename.endsWith(".js")) {
code = `export async function main(ns) {
v0.51.6 (#905) * Make command `cd` without arguments an alias for `cd /` (#853) In most shells `cd` without arguments takes you to the home directory of the current user. I keep trying to do this due to muscle memory from working in terminals, so I figured I'd make it do something useful. There is no home directory in the game, but going to / is the closest thing we have, since that is the starting point for the user in the game. * Add new `backdoor` terminal command (#852) * Add the backdoor command to the terminal This command will perform a manual hack without rewarding money. It will be used for the story, mainly for faction hacking tests * Add tab completion for backdoor command * Add help text for backdoor command * Change condition syntax to be more consistent with others * Extract reused code block so it is always called after actions * Update documentation for new backdoor command Modified references to manual hack as it isn't for factions anymore * Remove extra parenthesis * Rename manuallyHacked to backdoorInstalled * Fix typo * Change faction test messages to use backdoor instad of hack * Rename more instances of manuallyHacked * fixed typo in helptext of darkweb buy (#858) * Fix typos and unify descriptions of augmentations (#859) Made an attempt to... - give all "+rep% company/faction" the same text - make all augmentations with a single effect use a single line to describe the effect - make all effects end with a period * Made Cashroot starter kit display its tooltip with the money formatted properly and in gold * fix typo in docs (#860) * Initial code for Casino Card Deck implementation * Casino Blackjack Implementation * Update some tools (eslint, typescript) * Blackjack code cleanup * Update README_contribution * Update ScriptHelpers.js (#861) expand error message * More augmentation typo fixes (#862) * Add Netscript function getCurrentScript (#856) Add netscript function that returns the current script. * Added milestones menu to guide new players. (#865) Milestone menu * fix typos in milestones (#866) Co-authored-by: sschmidTU <s.schmid@phonicscore.com> * Corrupt location title when backdoor is installed (#864) * Add corruptableText component * Corrupt location title if backdoor is installed * Formatting * Add helper to check value of backdoorInstalled Helper could be oneline but it would make it less readable * Fix some formatting * Add settings option to disable text effects * Import useState * getRunningScript (#867) * Replaced getCurrentScript with getRunningScript * Bunch of smaller fixes (#904) Fix #884 Fix #879 Fix #878 Fix #876 Fix #874 Fix #873 Fix #887 Fix #891 Fix #895 * rework the early servers to be more noob friendly (#903) * v0.51.6 Co-authored-by: Andreas Eriksson <2691182+AndreasTPC@users.noreply.github.com> Co-authored-by: Jack <jackdewinter1@gmail.com> Co-authored-by: Teun Pronk <5228255+Crownie88@users.noreply.github.com> Co-authored-by: Pimvgd <Pimvgd@gmail.com> Co-authored-by: Daniel Xie <daniel.xie@flockfreight.com> Co-authored-by: Simon <33069673+sschmidTU@users.noreply.github.com> Co-authored-by: sschmidTU <s.schmid@phonicscore.com>
2021-04-29 02:07:26 +02:00
}`;
}
Engine.loadScriptEditorContent(filepath, code);
} else {
Engine.loadScriptEditorContent(filepath, script.code);
}
} else if (filename.endsWith(".txt")) {
const filepath = Terminal.getFilepath(filename);
const txt = Terminal.getTextFile(filename);
if (txt == null) {
Engine.loadScriptEditorContent(filepath);
} else {
Engine.loadScriptEditorContent(filepath, txt.text);
}
} else {
postError("Invalid file. Only scripts (.script, .ns, .js), text files (.txt), or .fconf can be edited with nano"); return;
}
} catch(e) {
Terminal.postThrownError(e);
}
},
2017-05-06 08:24:01 +02:00
executeScanCommand: function(commandArray) {
if (commandArray.length !== 1) {
postError("Incorrect usage of netstat/scan command. Usage: netstat/scan");
return;
2017-05-06 08:24:01 +02:00
}
// Displays available network connections using TCP
const currServ = Player.getCurrentServer();
2021-05-18 05:59:45 +02:00
const servers = currServ.serversOnNetwork.map((_, i) => {
const server = getServerOnNetwork(currServ, i);
return {
hostname: server.hostname,
ip: server.ip,
hasRoot: server.hasAdminRights ? "Y" : "N",
2017-05-06 08:24:01 +02:00
}
2021-05-18 05:59:45 +02:00
});
servers.unshift({
hostname: "Hostname",
ip: "IP",
hasRoot: "Root Access",
})
const maxHostname = Math.max(...servers.map(s => s.hostname.length));
const maxIP = Math.max(...servers.map(s => s.ip.length));
for(const server of servers) {
let entry = server.hostname;
entry += " ".repeat(maxHostname-server.hostname.length+1);
entry += server.ip;
entry += " ".repeat(maxIP-server.ip.length+1);
entry += server.hasRoot;
2017-05-06 08:24:01 +02:00
post(entry);
}
},
2017-09-19 20:38:03 +02:00
executeScanAnalyzeCommand: function(depth=1, all=false) {
// TODO Using array as stack for now, can make more efficient
post("~~~~~~~~~~ Beginning scan-analyze ~~~~~~~~~~");
post(" ");
// Map of all servers to keep track of which have been visited
var visited = {};
for (const ip in AllServers) {
visited[ip] = 0;
}
2017-09-19 20:38:03 +02:00
const stack = [];
const depthQueue = [0];
const currServ = Player.getCurrentServer();
stack.push(currServ);
while(stack.length != 0) {
const s = stack.pop();
const d = depthQueue.pop();
const isHacknet = s instanceof HacknetServer;
2017-09-19 20:38:03 +02:00
if (!all && s.purchasedByPlayer && s.hostname != "home") {
continue; // Purchased server
2017-09-19 20:38:03 +02:00
} else if (visited[s.ip] || d > depth) {
continue; // Already visited or out-of-depth
} else if (!all && isHacknet) {
continue; // Hacknet Server
} else {
visited[s.ip] = 1;
}
for (var i = s.serversOnNetwork.length-1; i >= 0; --i) {
stack.push(getServerOnNetwork(s, i));
depthQueue.push(d+1);
}
if (d == 0) {continue;} // Don't print current server
var titleDashes = Array((d-1) * 4 + 1).join("-");
2018-06-02 01:31:34 +02:00
if (Player.hasProgram(Programs.AutoLink.name)) {
post("<strong>" + titleDashes + "> <a class='scan-analyze-link'>" + s.hostname + "</a></strong>", false);
} else {
post("<strong>" + titleDashes + ">" + s.hostname + "</strong>");
}
var dashes = titleDashes + "--";
var c = "NO";
if (s.hasAdminRights) {c = "YES";}
post(`${dashes}Root Access: ${c}${!isHacknet ? ", Required hacking skill: " + s.requiredHackingSkill : ""}`);
if (!isHacknet) { post(dashes + "Number of open ports required to NUKE: " + s.numOpenPortsRequired); }
post(dashes + "RAM: " + numeralWrapper.formatRAM(s.maxRam));
post(" ");
}
var links = document.getElementsByClassName("scan-analyze-link");
for (let i = 0; i < links.length; ++i) {
(function() {
var hostname = links[i].innerHTML.toString();
links[i].onclick = function() {
if (Terminal.analyzeFlag || Terminal.hackFlag || Terminal.backdoorFlag) {return;}
Terminal.connectToServer(hostname);
}
}());// Immediate invocation
}
},
executeScpCommand(commandArray) {
try {
if (commandArray.length !== 3) {
postError("Incorrect usage of scp command. Usage: scp [file] [destination hostname/ip]");
return;
}
const scriptname = Terminal.getFilepath(commandArray[1]);
if (!scriptname.endsWith(".lit") && !isScriptFilename(scriptname) && !scriptname.endsWith(".txt")) {
postError("scp only works for scripts, text files (.txt), and literature files (.lit)");
return;
}
const destServer = getServer(commandArray[2]);
if (destServer == null) {
postError(`Invalid destination. ${commandArray[2]} not found`);
return;
}
const currServ = Player.getCurrentServer();
// Scp for lit files
if (scriptname.endsWith(".lit")) {
var found = false;
for (var i = 0; i < currServ.messages.length; ++i) {
if (!(currServ.messages[i] instanceof Message) && currServ.messages[i] == scriptname) {
found = true;
break;
}
}
if (!found) { return postError("No such file exists!"); }
for (var i = 0; i < destServer.messages.length; ++i) {
if (destServer.messages[i] === scriptname) {
post(scriptname + " copied over to " + destServer.hostname);
return; // Already exists
}
}
destServer.messages.push(scriptname);
return post(scriptname + " copied over to " + destServer.hostname);
}
// Scp for txt files
if (scriptname.endsWith(".txt")) {
var found = false, txtFile;
for (var i = 0; i < currServ.textFiles.length; ++i) {
if (currServ.textFiles[i].fn === scriptname) {
found = true;
txtFile = currServ.textFiles[i];
break;
}
}
if (!found) { return postError("No such file exists!"); }
let tRes = destServer.writeToTextFile(txtFile.fn, txtFile.text);
if (!tRes.success) {
postError("scp failed");
return;
}
if (tRes.overwritten) {
post(`WARNING: ${scriptname} already exists on ${destServer.hostname} and will be overwriten`);
post(`${scriptname} overwritten on ${destServer.hostname}`);
return;
}
post(`${scriptname} copied over to ${destServer.hostname}`);
return;
}
// Get the current script
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) {
postError("scp() failed. No such script exists");
return;
}
let sRes = destServer.writeToScriptFile(scriptname, sourceScript.code);
if (!sRes.success) {
postError(`scp failed`);
return;
}
if (sRes.overwritten) {
post(`WARNING: ${scriptname} already exists on ${destServer.hostname} and will be overwritten`);
post(`${scriptname} overwritten on ${destServer.hostname}`);
return;
}
post(`${scriptname} copied over to ${destServer.hostname}`);
} catch(e) {
Terminal.postThrownError(e);
}
2017-05-06 08:24:01 +02:00
},
// First called when the "run [program]" command is called. Checks to see if you
// have the executable and, if you do, calls the executeProgram() function
runProgram: function(commandArray) {
2019-02-20 09:42:27 +01:00
if (commandArray.length < 2) { return; }
// Check if you have the program on your computer. If you do, execute it, otherwise
// display an error message
2019-02-20 09:42:27 +01:00
const programName = commandArray[1];
if (Player.hasProgram(programName)) {
Terminal.executeProgram(commandArray);
return;
}
post("ERROR: No such executable on home computer (Only programs that exist on your home computer can be run)");
},
// Contains the implementations of all possible programs
executeProgram: function(commandArray) {
2019-02-20 09:42:27 +01:00
if (commandArray.length < 2) { return; }
2017-04-19 23:40:26 +02:00
var s = Player.getCurrentServer();
2019-02-20 09:42:27 +01:00
const programName = commandArray[1];
const splitArgs = commandArray.slice(1);
2018-01-27 07:52:39 +01:00
// TODO: refactor this/these out of Terminal. This logic could reside closer to the Programs themselves.
/**
* @typedef {function (server=, args=)} ProgramHandler
* @param {Server} server The current server the program is being executed against
* @param {string[]} args The command line arguments passed in to the program
* @returns {void}
*/
/**
* @type {Object.<string, ProgramHandler}
*/
const programHandlers = {};
programHandlers[Programs.NukeProgram.name] = (server) => {
if (server.hasAdminRights) {
post("You already have root access to this computer. There is no reason to run NUKE.exe");
return;
}
if (server.openPortCount >= Player.getCurrentServer().numOpenPortsRequired) {
server.hasAdminRights = true;
post("NUKE successful! Gained root access to " + Player.getCurrentServer().hostname);
// TODO: Make this take time rather than be instant
return;
}
post("NUKE unsuccessful. Not enough ports have been opened");
};
programHandlers[Programs.BruteSSHProgram.name] = (server) => {
if (server.sshPortOpen) {
post("SSH Port (22) is already open!");
return;
}
server.sshPortOpen = true;
post("Opened SSH Port(22)!")
server.openPortCount++;
};
programHandlers[Programs.FTPCrackProgram.name] = (server) => {
if (server.ftpPortOpen) {
post("FTP Port (21) is already open!");
return;
}
server.ftpPortOpen = true;
post("Opened FTP Port (21)!");
server.openPortCount++;
};
programHandlers[Programs.RelaySMTPProgram.name] = (server) => {
if (server.smtpPortOpen) {
post("SMTP Port (25) is already open!");
return;
}
server.smtpPortOpen = true;
post("Opened SMTP Port (25)!");
server.openPortCount++;
};
programHandlers[Programs.HTTPWormProgram.name] = (server) => {
if (server.httpPortOpen) {
post("HTTP Port (80) is already open!");
return;
}
server.httpPortOpen = true;
post("Opened HTTP Port (80)!");
server.openPortCount++;
};
programHandlers[Programs.SQLInjectProgram.name] = (server) => {
if (server.sqlPortOpen) {
post("SQL Port (1433) is already open!");
return;
}
server.sqlPortOpen = true;
post("Opened SQL Port (1433)!");
server.openPortCount++;
};
programHandlers[Programs.ServerProfiler.name] = (server, args) => {
if (args.length !== 2) {
post("Must pass a server hostname or IP as an argument for ServerProfiler.exe");
return;
}
const targetServer = getServer(args[1]);
if (targetServer == null) {
post("Invalid server IP/hostname");
return;
}
if(targetServer instanceof HacknetServer) {
post(`${Programs.ServerProfiler.name} cannot be run on a Hacknet Server.`);
return
}
post(targetServer.hostname + ":");
post("Server base security level: " + targetServer.baseDifficulty);
post("Server current security level: " + targetServer.hackDifficulty);
post("Server growth rate: " + targetServer.serverGrowth);
post(`Netscript hack() execution time: ${convertTimeMsToTimeElapsedString(calculateHackingTime(targetServer, Player)*1000, true)}`);
post(`Netscript grow() execution time: ${convertTimeMsToTimeElapsedString(calculateGrowTime(targetServer, Player)*1000, true)}`);
post(`Netscript weaken() execution time: ${convertTimeMsToTimeElapsedString(calculateWeakenTime(targetServer, Player)*1000, true)}`);
};
programHandlers[Programs.AutoLink.name] = () => {
post("This executable cannot be run.");
post("AutoLink.exe lets you automatically connect to other servers when using 'scan-analyze'.");
post("When using scan-analyze, click on a server's hostname to connect to it.");
};
programHandlers[Programs.DeepscanV1.name] = () => {
post("This executable cannot be run.");
post("DeepscanV1.exe lets you run 'scan-analyze' with a depth up to 5.");
};
programHandlers[Programs.DeepscanV2.name] = () => {
post("This executable cannot be run.");
post("DeepscanV2.exe lets you run 'scan-analyze' with a depth up to 10.");
};
programHandlers[Programs.Flight.name] = () => {
const numAugReq = Math.round(BitNodeMultipliers.DaedalusAugsRequirement*30)
const fulfilled = Player.augmentations.length >= numAugReq &&
Player.money.gt(1e11) &&
Player.hacking_skill >= 2500;
if(!fulfilled) {
post(`Augmentations: ${Player.augmentations.length} / ${numAugReq}`);
2021-09-04 20:03:19 +02:00
postElement(<>Money: <Money money={Player.money.toNumber()} /> / <Money money={1e11} /></>);
post(`Hacking skill: ${Player.hacking_skill} / 2500`);
return;
}
post("We will contact you.");
post("-- Daedalus --");
};
programHandlers[Programs.BitFlume.name] = () => {
const yesBtn = yesNoBoxGetYesButton();
const noBtn = yesNoBoxGetNoButton();
yesBtn.innerHTML = "Travel to BitNode Nexus";
noBtn.innerHTML = "Cancel";
yesBtn.addEventListener("click", function() {
hackWorldDaemon(Player.bitNodeN, true);
return yesNoBoxClose();
});
noBtn.addEventListener("click", function() {
return yesNoBoxClose();
});
yesNoBoxCreate("WARNING: USING THIS PROGRAM WILL CAUSE YOU TO LOSE ALL OF YOUR PROGRESS ON THE CURRENT BITNODE.<br><br>" +
"Do you want to travel to the BitNode Nexus? This allows you to reset the current BitNode " +
"and select a new one.");
};
if (!programHandlers.hasOwnProperty(programName)){
post("Invalid executable. Cannot be run");
return;
}
programHandlers[programName](s, splitArgs);
},
/**
* Given a filename, returns that file's full path. This takes into account
* the Terminal's current directory.
*/
getFilepath : function(filename) {
const path = evaluateFilePath(filename, Terminal.currDir);
if (path == null) {
throw new Error(`Invalid file path specified: ${filename}`);
}
if (isInRootDirectory(path)) {
return removeLeadingSlash(path);
}
return path;
},
/**
* Given a filename, searches and returns that file. File-type agnostic
*/
getFile: function (filename) {
if (isScriptFilename(filename)) {
return Terminal.getScript(filename);
}
if (filename.endsWith(".lit")) {
return Terminal.getLitFile(filename);
}
if (filename.endsWith(".txt")) {
return Terminal.getTextFile(filename);
}
return null;
},
/**
* Processes a file path referring to a literature file, taking into account the terminal's
* current directory + server. Returns the lit file if it exists, and null otherwise
*/
getLitFile: function(filename) {
const s = Player.getCurrentServer();
const filepath = Terminal.getFilepath(filename);
for (const lit of s.messages) {
if (typeof lit === "string" && filepath === lit) {
return lit;
}
}
return null;
},
/**
* Processes a file path referring to a script, taking into account the terminal's
* current directory + server. Returns the script if it exists, and null otherwise.
*/
getScript: function(filename) {
const s = Player.getCurrentServer();
const filepath = Terminal.getFilepath(filename);
for (const script of s.scripts) {
if (filepath === script.filename) {
return script;
}
}
return null;
},
/**
* Processes a file path referring to a text file, taking into account the terminal's
* current directory + server. Returns the text file if it exists, and null otherwise.
*/
getTextFile: function(filename) {
const s = Player.getCurrentServer();
const filepath = Terminal.getFilepath(filename);
for (const txt of s.textFiles) {
if (filepath === txt.fn) {
return txt;
}
}
return null;
},
postThrownError: function(e) {
if (e instanceof Error) {
const errorLabel = "Error: ";
const errorString = e.toString();
if (errorString.startsWith(errorLabel)) {
postError(errorString.slice(errorLabel.length));
} else {
postError(errorString);
}
}
},
runScript: function(commandArray) {
if (commandArray.length < 2) {
dialogBoxCreate(`Bug encountered with Terminal.runScript(). Command array has a length of less than 2: ${commandArray}`);
return;
}
const server = Player.getCurrentServer();
const scriptName = Terminal.getFilepath(commandArray[1]);
2021-08-19 22:37:59 +02:00
const runArgs = {'--tail': Boolean, '-t': Number};
const flags = libarg(runArgs, {permissive: true, argv: commandArray.slice(2)});
const threadFlag = Math.round(parseFloat(flags['-t']));
const tailFlag = flags['--tail'] === true;
if(flags['-t'] !== undefined && (threadFlag < 0 || isNaN(threadFlag))) {
postError("Invalid number of threads specified. Number of threads must be greater than 0");
return;
}
2021-08-19 22:37:59 +02:00
const numThreads = !isNaN(threadFlag) && threadFlag > 0 ? threadFlag : 1;
const args = flags['_'];
// Check if this script is already running
if (findRunningScript(scriptName, args, server) != null) {
post("ERROR: This script is already running. Cannot run multiple instances");
return;
}
// Check if the script exists and if it does run it
2021-08-19 22:37:59 +02:00
for (let i = 0; i < server.scripts.length; i++) {
if (server.scripts[i].filename !== scriptName) {
continue
}
// Check for admin rights and that there is enough RAM availble to run
const script = server.scripts[i];
const ramUsage = script.ramUsage * numThreads;
const ramAvailable = server.maxRam - server.ramUsed;
2021-08-19 22:37:59 +02:00
if (!server.hasAdminRights) {
post("Need root access to run script");
return;
}
if (ramUsage > ramAvailable){
post("This machine does not have enough RAM to run this script with " +
numThreads + " threads. Script requires " + ramUsage + "GB of RAM");
return;
}
2021-08-19 22:37:59 +02:00
// Able to run script
const runningScript = new RunningScript(script, args);
runningScript.threads = numThreads;
const success = startWorkerScript(runningScript, server);
if (!success) {
postError(`Failed to start script`);
return
}
post(`Running script with ${numThreads} thread(s), pid ${runningScript.pid} and args: ${arrayToString(args)}.`);
if(tailFlag) {
logBoxCreate(runningScript)
}
return;
}
post("ERROR: No such script");
},
runContract: async function(contractName) {
// There's already an opened contract
if (Terminal.contractOpen) {
return post("ERROR: There's already a Coding Contract in Progress");
}
const serv = Player.getCurrentServer();
const contract = serv.getContract(contractName);
if (contract == null) {
return post("ERROR: No such contract");
}
2018-09-23 02:25:48 +02:00
Terminal.contractOpen = true;
const res = await contract.prompt();
switch (res) {
case CodingContractResult.Success:
var reward = Player.gainCodingContractReward(contract.reward, contract.getDifficulty());
post(`Contract SUCCESS - ${reward}`);
serv.removeContract(contract);
break;
case CodingContractResult.Failure:
++contract.tries;
if (contract.tries >= contract.getMaxNumTries()) {
2018-09-23 02:25:48 +02:00
post("Contract <p style='color:red;display:inline'>FAILED</p> - Contract is now self-destructing");
serv.removeContract(contract);
2018-09-23 02:25:48 +02:00
} else {
post(`Contract <p style='color:red;display:inline'>FAILED</p> - ${contract.getMaxNumTries() - contract.tries} tries remaining`);
}
break;
case CodingContractResult.Cancelled:
default:
post("Contract cancelled");
break;
}
Terminal.contractOpen = false;
},
};
v0.51.6 (#905) * Make command `cd` without arguments an alias for `cd /` (#853) In most shells `cd` without arguments takes you to the home directory of the current user. I keep trying to do this due to muscle memory from working in terminals, so I figured I'd make it do something useful. There is no home directory in the game, but going to / is the closest thing we have, since that is the starting point for the user in the game. * Add new `backdoor` terminal command (#852) * Add the backdoor command to the terminal This command will perform a manual hack without rewarding money. It will be used for the story, mainly for faction hacking tests * Add tab completion for backdoor command * Add help text for backdoor command * Change condition syntax to be more consistent with others * Extract reused code block so it is always called after actions * Update documentation for new backdoor command Modified references to manual hack as it isn't for factions anymore * Remove extra parenthesis * Rename manuallyHacked to backdoorInstalled * Fix typo * Change faction test messages to use backdoor instad of hack * Rename more instances of manuallyHacked * fixed typo in helptext of darkweb buy (#858) * Fix typos and unify descriptions of augmentations (#859) Made an attempt to... - give all "+rep% company/faction" the same text - make all augmentations with a single effect use a single line to describe the effect - make all effects end with a period * Made Cashroot starter kit display its tooltip with the money formatted properly and in gold * fix typo in docs (#860) * Initial code for Casino Card Deck implementation * Casino Blackjack Implementation * Update some tools (eslint, typescript) * Blackjack code cleanup * Update README_contribution * Update ScriptHelpers.js (#861) expand error message * More augmentation typo fixes (#862) * Add Netscript function getCurrentScript (#856) Add netscript function that returns the current script. * Added milestones menu to guide new players. (#865) Milestone menu * fix typos in milestones (#866) Co-authored-by: sschmidTU <s.schmid@phonicscore.com> * Corrupt location title when backdoor is installed (#864) * Add corruptableText component * Corrupt location title if backdoor is installed * Formatting * Add helper to check value of backdoorInstalled Helper could be oneline but it would make it less readable * Fix some formatting * Add settings option to disable text effects * Import useState * getRunningScript (#867) * Replaced getCurrentScript with getRunningScript * Bunch of smaller fixes (#904) Fix #884 Fix #879 Fix #878 Fix #876 Fix #874 Fix #873 Fix #887 Fix #891 Fix #895 * rework the early servers to be more noob friendly (#903) * v0.51.6 Co-authored-by: Andreas Eriksson <2691182+AndreasTPC@users.noreply.github.com> Co-authored-by: Jack <jackdewinter1@gmail.com> Co-authored-by: Teun Pronk <5228255+Crownie88@users.noreply.github.com> Co-authored-by: Pimvgd <Pimvgd@gmail.com> Co-authored-by: Daniel Xie <daniel.xie@flockfreight.com> Co-authored-by: Simon <33069673+sschmidTU@users.noreply.github.com> Co-authored-by: sschmidTU <s.schmid@phonicscore.com>
2021-04-29 02:07:26 +02:00
export {postNetburnerText, Terminal};