diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cf8cf27fb..a6cfd9dbd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,7 +6,7 @@ The game is made better because the community as a whole speaks up about ways to improve the game. Here's some of the ways you can make your voice heard: -- [Discord](https://discordapp.com) +- [Discord](https://discord.gg/XKEGvHqVr3) There is a dedicated Discord instance set up for more free-form chats between all members of the community. Regular players, heavy scripters, Bitburner contributors, and everyone in between can be found on the diff --git a/dist/bitburner.d.ts b/dist/bitburner.d.ts index dcda6d7b1..b5ef5e228 100644 --- a/dist/bitburner.d.ts +++ b/dist/bitburner.d.ts @@ -3538,13 +3538,13 @@ export declare interface NS extends Singularity { * @remarks * RAM cost: 0.05 GB * - * Returns the amount of time in milliseconds it takes to execute the weaken() Netscript function on the target server. + * Returns the amount of time in milliseconds it takes to execute the weaken Netscript function on the target server. * The function takes in an optional hackLvl parameter that can be specified to see what the weaken time would be at different hacking levels. * * @param host - Host of target server. * @param hackLvl - Optional hacking level for the calculation. Defaults to player’s current hacking level. * @param intLvl - Optional intelligence level for the calculation. Defaults to player’s current intelligence level. (Intelligence is unlocked after obtaining Source-File 5). - * @returns Returns the amount of time in milliseconds it takes to execute the grow Netscript function. Returns Infinity if called on a Hacknet Server. + * @returns Returns the amount of time in milliseconds it takes to execute the weaken Netscript function. Returns Infinity if called on a Hacknet Server. */ getWeakenTime(host: string): number; diff --git a/doc/source/advancedgameplay/hackingalgorithms.rst b/doc/source/advancedgameplay/hackingalgorithms.rst index 6018973db..7f5edd47e 100644 --- a/doc/source/advancedgameplay/hackingalgorithms.rst +++ b/doc/source/advancedgameplay/hackingalgorithms.rst @@ -1,36 +1,32 @@ - - Hacking algorithms ================== -There are 3 main family of hacking algorithms. This guide will go over each of them and give advice on how to -implement them. +There are three primary families of hacking algorithms. This guide will go over each of them and advise on how they can be implemented. Self-contained algorithms ------------------------- +**Difficulty**: Easy -Implementation difficulty: Easy - -pros: +Pros: * Easy to implement * Does not require other scripts to work * Works at any stage of the game -cons: +Cons: * Limits income generation -* Very inefficient with ram -* Makes poor use of your script online time. +* Extremely RAM inefficient +* Utilizes script online time poorly +* Risk of over hacking -This family of algorithms are the simplest to implement they are called self-contained because a single script -contains everything needed to maintain a constant flow of money. +Self-contained algorithms are the simplest family of hacking algorithms to implement. Each script is tasked with choosing which function to execute based on the status of the target server. Because of this, they guarantee a consistent, but relatively small, flow of money. The general logic goes like this: .. code-block:: javascript - for ever { + loop forever { if security is not minimum { weaken(target) } else if money is not maximum { @@ -40,104 +36,91 @@ The general logic goes like this: } } -This is a perfectly fine algorithm to start with and can get you through most of the game. But it does have -some very serious issues. +This algorithm is perfectly capable of paving the way through the majority of the game, but it has a few significant issues. -- It tends to make all your scripts on every server do the same thing. - This means if you are 0.01 security above minimum most scripts will be doing a weaken when only a - handful of thread should be. -- At higher thread count it can drain a server of all it's money in 1 hack(). Recovering from $0 is - possible but extremely slow. -- It makes very poor use of the servers RAM. To implement this you will need to call functions like - getServerSecurityLevel and that functions ram cost will be multiplied by the number of thread. +- It tends to make all your scripts on every server do the same thing. (e.g. If the target is 0.01 security above the minimum, all scripts will decide to weaken, when only a handful of threads should be devoted to the task) +- At higher thread counts, these scripts have the potential to hack the server to $0, or maximum security, requiring a long setup time while the scripts return the server to the best stats. +- Requires function calls such as `getServerSecurityLevel()` and `getServerMoneyAvailable()`, as well as calling all three hacking functions, increasing RAM cost which is multiplied by the number of allocated threads -loop algorithms +Loop algorithms --------------- +**Difficulty**: Easy to Medium -Implementation difficulty: Easy to Medium. - -pros: +Pros: * Simple to understand * Works at any stage of the game -* Maximize RAM usage. +* Maximize RAM usage -cons: +Cons: -* Support scripts are required to make things easy. +* Requires a script that handles deployment -We can kill 2 birds with 1 stone from the previous algorithm by splitting our 3 main functions into 3 files +By splitting our hack, weaken, and grow functions into three separate scripts, we can both remove our reliance on functions such as `getServerSecurityLevel()` as well as removing functions that cannot work concurrently, reducing RAM requirements, and thus increasing our thread limits. Loop scripts are formatted like this: .. code-block:: javascript - for ever { + loop forever { hack(target) // or grow, or weaken } -Now we take the total amount of thread available and split it. We allocate: -- 1 part to the hack script. -- 10 part to the grow script. -- 2 part to the weaken script. +Now we can take the total amount of threads available and split it and allocate, for example: -Meaning if we have room for 100 thread across all network 7 thread will go to hack, 76 thread to grow and 15 to weaken. -These ratios are arbitrary and can be improved but this is generally a good idea. +- 1 part to the hack scripts +- 10 parts to the grow scripts +- 2 parts to the weaken scripts -Carefull when applying this algorithm that you monitor the amount of money in the server, it should hover around maximum. -For that reason it may be wise to start the hack script later than the grow / weaken. If you find that the ratio is not -right feel free to modify it. +Meaning if we have space for 100 threads across the entire network 7 threads will go to the hack scripts, 76 threads will go to the grow scripts and 15 threads will go to the weaken scripts. The ratios described here are arbitrary and can be greatly improved through the use of the analyze functions, and later, through the use of Formulas.exe. -To some extent it's better to split the grow processes into smaller parts. -4 process with 20 thread each is better than 1 process with 80 threads. +When utilizing this strategy, monitor the amount of money and security on the target server, if the money is not hovering around maximum and the security around the minimum, the ratios should be tweaked until that is the case. -It can be useful to add a delay to your scripts in order to prevent them from all starting at the same time. -The sleep function has no RAM cost. +Growth can be made more efficient by dividing it into many processes, instead of one script with a high thread count. Four grow scripts with 20 threads will outperform one grow script with 80 threads. -batch algorithms (aka hwgw or cycles) +Utilizing `sleep()` or `asleep()` to ensure that your scripts do not all start at the same time can decrease the chance of issues associated with overhacking occurring. Both functions have a ram cost of zero. + +Batch algorithms (HGW, HWGW, or Cycles) ------------------------------------- +**Difficulty**: Hard -Implementation difficulty: Hard +Pros: -pros: +* Maximum potential income -* Maximize money +Cons: -cons: +* Very difficult to implement without prior programming knowledge +* Very difficult to make work on servers with less than 1TB of RAM -* Very hard to implement -* Does not work well without a large player bought server. +Batch algorithms utilize a master script that uses `exec()` many scripts which utilize a relevant hacking function in batches. -Batch algorithms are so called because you have a master script that `exec` a lot of other scripts in batches. - -The basic building blocks are even simpler than the previous algorithm but a controller is required and is much -more complex. +The scripts used to execute the hacking functions are even simpler than the previous algorithms but a complex controller is required to calculate the effect, time taken, and the necessary delay. .. code-block:: javascript sleep(a bit) hack(target) // or grow, or weaken -We need to know a couple of things before we can implement this algorithm. +A few things need to be known before this algorithm can be implemented: -- The effect of hack / grow depends on the server security. -- The time it takes for hack/grow/weaken takes to complete is determined when the - function is called but the effect is calculated at the end. +- The effects of hack and grow depend on the server security level, a higher security level results in a reduced effect. You only want these effects to occur when the security level is minimized. +- The time taken to execute hack, grow, or weaken is determined when the function is called and is based on the security level of the target server and your hacking level. You only want these effects to start when the security level is minimized. +- The effects of hack, grow, and weaken, are determined when the time is completed, rather than at the beginning. Hack should finish when security is minimum and money is maximum. Grow should finish when security is minimum, shortly after a hack occurred. Weaken should occur when security is not at a minimum due to a hack or grow increasing it. -A batch consist of a set of 4 special process +A single batch consists of four actions: -1. A hack script that will remove a predefined, precalculated amount of money from the server. -2. A weaken script that counters the security increase of the hack process. -3. A grow script that counters the money decrease of the hack process. -4. A weaken script that counters the security increase of the grow process. +1. A hack script removes a predefined, precalculated amount of money from the target server. +2. A weaken script counters the security increase of the hack script. +3. A grow script counters the money decrease caused by the hack script. +4. A weaken script counters the security increase caused by the grow script. -It is also important that these 4 scripts finish in the order specified. Hence why you need a delay in your script. -It's possible to make a batch with 3 scripts (hgw) but that it less efficient as the effectiveness of `grow` is based off server security. +It is also important that these 4 scripts finish in the order specified above, and all of their effects be precalculated to optimize the ratios between them. This is the reason for the delay in the scripts. -Here's a picture demonstrating batch in action. +It is possible to create batches with 3 scripts (HGW) but the efficiency of grow will be harmed by the security increase caused by the hack scripts. + +The following is an image demonstrating batches in action: .. image:: batch.png -For batches to work the server needs to be at max money and min security. It is possible to use batches -to reach max money and min sec, just don't use any hack in your cycles. - -The time set between each script ending cannot be tighter than 20ms as this is the best the javascript engine can do. +Batches only function predictably when the target server is at minimum security and maximum money, so your script must also handle preparing a server for your batches. You can utilize batches to prepare a server by using no hack threads during preparation. +Depending on your computer's performance as well as a few other factors, the necessary delay between script execution times may range between 20ms and 200ms, you want to fine-tune this value to be as low as possible while also avoiding your scripts finishing out of order. Anything lower than 20ms will not work due to javascript limitations. diff --git a/electron/utils.js b/electron/utils.js index 03175b57b..17385b20e 100644 --- a/electron/utils.js +++ b/electron/utils.js @@ -48,11 +48,12 @@ function promptForReload(window) { } function attachUnresponsiveAppHandler(window) { - window.on('unresponsive', () => promptForReload(window)); + window.unresponsiveHandler = () => promptForReload(window); + window.on('unresponsive', window.unresponsiveHandler); } function detachUnresponsiveAppHandler(window) { - window.off('unresponsive', () => promptForReload(window)); + window.off('unresponsive', window.unresponsiveHandler); } function showErrorBox(title, error) { diff --git a/src/NetscriptFunctions.ts b/src/NetscriptFunctions.ts index 892b3f54b..1f87c4781 100644 --- a/src/NetscriptFunctions.ts +++ b/src/NetscriptFunctions.ts @@ -833,18 +833,18 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS { workerScript.log("nuke", () => "Cannot be executed on this server."); return false; } + if (server.hasAdminRights) { + workerScript.log("nuke", () => `Already have root access to '${server.hostname}'.`); + return true; + } if (!Player.hasProgram(Programs.NukeProgram.name)) { throw makeRuntimeErrorMsg("nuke", "You do not have the NUKE.exe virus!"); } if (server.openPortCount < server.numOpenPortsRequired) { throw makeRuntimeErrorMsg("nuke", "Not enough ports opened to use NUKE.exe virus."); } - if (server.hasAdminRights) { - workerScript.log("nuke", () => `Already have root access to '${server.hostname}'.`); - } else { - server.hasAdminRights = true; - workerScript.log("nuke", () => `Executed NUKE.exe virus on '${server.hostname}' to gain root access.`); - } + server.hasAdminRights = true; + workerScript.log("nuke", () => `Executed NUKE.exe virus on '${server.hostname}' to gain root access.`); return true; }, brutessh: function (hostname: any): boolean { diff --git a/src/ScriptEditor/NetscriptDefinitions.d.ts b/src/ScriptEditor/NetscriptDefinitions.d.ts index f4fcfda68..706861804 100644 --- a/src/ScriptEditor/NetscriptDefinitions.d.ts +++ b/src/ScriptEditor/NetscriptDefinitions.d.ts @@ -5508,12 +5508,12 @@ export interface NS extends Singularity { * @remarks * RAM cost: 0.05 GB * - * Returns the amount of time in milliseconds it takes to execute the weaken() Netscript function on the target server. + * Returns the amount of time in milliseconds it takes to execute the weaken Netscript function on the target server. * The function takes in an optional hackLvl parameter that can be specified to see what the weaken time would be at different hacking levels. * The required time is increased by the security level of the target server and decreased by the player's hacking level. * * @param host - Host of target server. - * @returns Returns the amount of time in milliseconds it takes to execute the grow Netscript function. Returns Infinity if called on a Hacknet Server. + * @returns Returns the amount of time in milliseconds it takes to execute the weaken Netscript function. Returns Infinity if called on a Hacknet Server. */ getWeakenTime(host: string): number; diff --git a/src/ui/React/Snackbar.tsx b/src/ui/React/Snackbar.tsx index 30f59b2bd..a566767d8 100644 --- a/src/ui/React/Snackbar.tsx +++ b/src/ui/React/Snackbar.tsx @@ -19,16 +19,17 @@ export function SnackbarProvider(props: IProps): React.ReactElement { export const SnackbarEvents = new EventEmitter<[string, "success" | "warning" | "error" | "info", number]>(); export function Snackbar(): React.ReactElement { - const { enqueueSnackbar } = useSnackbar(); + const { enqueueSnackbar, closeSnackbar } = useSnackbar(); useEffect(() => - SnackbarEvents.subscribe((s, variant, duration) => - enqueueSnackbar({s}, { + SnackbarEvents.subscribe((s, variant, duration) => { + const id = enqueueSnackbar({s}, { content: (k, m) => {m}, variant: variant, autoHideDuration: duration, - }), - ), + onClick: () => closeSnackbar(id), + }) + }), ); return <>; }