Compare commits

..

1 Commits

Author SHA1 Message Date
ff4cc47e60 Unknown 2023-01-29 07:50:58 -05:00
15 changed files with 885 additions and 936 deletions

View File

@ -1,30 +0,0 @@
---
name: "Bug report"
about: "Encountered an issue"
ref: "develop"
labels:
- Type/Bug
---
# Bug Report
<!-- Description of problem -->
I tried to ...
But instead ...
## Steps to Reproduce
<!-- How can developers replicate & test the problem? -->
1.
2.
3.
## Logs
<!-- Any logs that accompenied the error -->
```
```
## Screenshots
<!-- Screenshots (annoted if possible) of the problem -->

View File

@ -1,22 +0,0 @@
---
name: "Enhancement"
about: "Request a feature"
ref: "develop"
labels:
- Type/Enhancement
---
# Feature Request
<!-- Detailed description -->
...
## Requirements
<!-- Bullet list of requirments -->
1. ...
2. ...
## Notes
<!-- Any additional considerations, solutions or design choices -->
...

View File

@ -1,14 +0,0 @@
## Description
<!-- Adition information & context -->
...
## Issues
<!-- Issues this PR will address -->
- closes #___
- owner/repo#___
## Checklist
<!-- Compelte after creating PR -->
- [ ] Linked issues
- [ ] Reviewed changes
- [ ] Updated comments/documentation

View File

@ -1,7 +0,0 @@
Copyright (c) 2023 Zakary Timson
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

916
README.md
View File

@ -1,505 +1,411 @@
<!-- Header -->
<div id="top" align="center">
<br />
<!-- Logo -->
<img src="https://git.zakscode.com/repo-avatars/9b25b57330ba3a1d9da80dad4051be68373e52c4bfffc6f6ba9e89f7392f5f7d" alt="Logo" width="200" height="200">
<!-- Title -->
### Bitburner
<!-- Description -->
Collection of Bitburner scipts
<!-- Repo badges -->
[![Version](https://img.shields.io/badge/dynamic/json.svg?label=Version&style=for-the-badge&url=https://git.zakscode.com/api/v1/repos/ztimson/bitburner/tags&query=$[0].name)](https://git.zakscode.com/ztimson/bitburner/tags)
[![Pull Requests](https://img.shields.io/badge/dynamic/json.svg?label=Pull%20Requests&style=for-the-badge&url=https://git.zakscode.com/api/v1/repos/ztimson/bitburner&query=open_pr_counter)](https://git.zakscode.com/ztimson/bitburner/pulls)
[![Issues](https://img.shields.io/badge/dynamic/json.svg?label=Issues&style=for-the-badge&url=https://git.zakscode.com/api/v1/repos/ztimson/bitburner&query=open_issues_count)](https://git.zakscode.com/ztimson/bitburner/issues)
<!-- Links -->
---
<div>
<a href="https://git.zakscode.com/ztimson/bitburner/releases" target="_blank">Release Notes</a>
<a href="https://git.zakscode.com/ztimson/bitburner/issues/new?template=.github%2fissue_template%2fbug.md" target="_blank">Report a Bug</a>
<a href="https://git.zakscode.com/ztimson/bitburner/issues/new?template=.github%2fissue_template%2fenhancement.md" target="_blank">Request a Feature</a>
</div>
---
</div>
## Table of Contents
- [Bitburner](#top)
- [About](#about)
- [Built With](#built-with)
- [Quick Start](#qiuck-start)
- [Scripts](#scripts)
- [banner.js](#banner)
- [botnet-manager.js (WIP)](#botnet)
- [connect.js](#connect)
- [copy.js](#copy)
- [crawler.js](#crawler)
- [find-target.js](#find-target)
- [hacknet-manager.js](#hacknet)
- [miner.js](#miner)
- [network-graph.js](#network-graph)
- [rm.js](#rm)
- [rootkit.js](#rootkit)
- [server-manager.js](#server-manager)
- [update.js](#update)
- [License](#license)
## About
A collection of scripts & information pertaining to the [open source](https://github.com/danielyxie/bitburner) game [Bitburner](https://danielyxie.github.io/bitburner/)
### Built with
[![JavaScript](https://img.shields.io/badge/JavaScript-000000?style=for-the-badge&logo=javascript)](https://javascript.com/)
## Quick Start
```bash
# Download the update script in-game & run it
wget https://gitlab.zakscode.com/ztimson/Bitburner/-/raw/develop/scripts/update.js scripts/update.js
run scripts/update.js # Repeat to pull the latest
# View the network
run scripts/network-graph.js --verbose
run scripts/netowkr-graph.js -v --filter CSEC # Find path to a specific device
# Start the node manager in auto-mode
run scripts/node-manager.js -a
# Chain the crawler & rootkit to root all devices on the network
run scripts/crawler.js --not-rooted /scripts/rootkit.js {{TARGET}}
# Find the most profitable server & use the crawler to deploy miners on the network targeting it
run scripts/find-target.js # Output: n00dles
run scriipts/crawler.js --rooted --remote-exec /scripts/miner.js n00dles
# Install backdoor on CSEC
run scripts/rootkit.js CSEC
run scripts/connect.js CSEC
backdoor
```
## Scripts
<details>
<summary>
<h3 id="banner" style="display: inline">banner.js</h3>
</summary>
<br />
**RAM:** 1.60 GB | [Code](./src/banner.js)
Aesthetic & serves no real purpose. Prints a banner to the terminal & can repeat after game restarts.
```
[home ~/]> run scripts/banner.js --help
Running script with 1 thread(s), pid 1 and args: ["--help"].
/scripts/banner.js:
Display an ASCII banner.
Usage: run banner.js [OPTIONS]
run banner.js --help
Options:
-r, --reboot Automatically display after game reboots
-h, --help Display this help message
```
</details>
<details>
<summary>
<h3 id="botnet" style="display: inline">botnet-manager.js (WIP)</h3>
</summary>
<br />
**RAM:** 7.15 GB | [Code](./scripts/botnet-manager.js)
Late-game solution to hack servers. It orchestrates an unlimited number of servers to carry out distributed batched
attacks against targets. It includes a bunch of utilities to quickly dispatch single commands to all workers. Manger
can be tailed for live updates.
```
[home ~/]> run /scripts/botnet-manager.js --help
Running script with 1 thread(s), pid 1 and args: ["--help"].
/scripts/botnet-manager.js:
Connect & manage a network of devices to launch distributed attacks.
Usage: run botnet-manager.js [OPTIONS]
run botnet-manager.js [OPTIONS] COMMAND
run botnet-manager.js --help [COMMAND]
Options:
-s, --silent Suppress program output
-h, --help Display this help message
Commands:
copy Copy file & dependencies to swarm nodes
join Connect device as a worker node to the swarm
kill Kill any scripts running on worker nodes
leave Disconnect worker node from swarm
run Copy & run script on all worker nodes
start Start this device as the swarm manager
```
</details>
<details>
<summary>
<h3 id="connect" style="display: inline">connect.js</h3>
</summary>
<br />
**RAM:** 1.85 GB | [Code](./scripts/connect.js)
The built in `connect` command only allows you to connect to devices in the immediate vicinity or servers that have
backdoors installed requiring you to make several jumps. This script will automatically find a path & connect you saving
you some time.
```
[home ~/]> run /scripts/connect.js --help
Running script with 1 thread(s), pid 1 and args: ["--help"].
/scripts/connect.js:
Connect to a server anywhere in the network without a backdoor.
Usage: run connect.js [OPTIONS] SERVER
run connect.js --help
SERVER Server to connect to
Options:
-h, --help Display this help message
```
</details>
<details>
<summary>
<h3 id="copy" style="display: inline">copy.js</h3>
</summary>
<br />
**RAM:** 4.20 GB | [Code](./scripts/copy.js)
Scripts often import other scripts requiring multiple `scp` calls before it can be run on a remote machine. This script
will automatically scan the file being copied for imports & recursively scan & copy the dependencies. Plus it has a
fancy animated loading bar.
```
[home ~/]> run scripts/copy.js --help
Running script with 1 thread(s), pid 1 and args: ["--help"].
/scripts/copy.js:
Copy a file & it's dependencies to a server.
Usage: run copy.js [OPTIONS] FILE SERVER [ARGS]...
run copy.js --help
FILE File to copy
SERVER Server to copy file(s) to
ARGS Arguments to start file/script with
Options:
-c, --cpu Number of CPU threads to start script with, will use maximum if not specified
-e, --execute Start script after copying
-n, --no-deps Skip copying dependencies
-q, --quite Suppress program output
-h, --help Display this help message
```
</details>
<details>
<summary>
<h3 id="crawler" style="display: inline">crawler.js</h3>
</summary>
<br />
**RAM:** 5.80 GB | [Code](./scripts/crawler.js)
Mid-game solution to distribute & run scripts across the network.
```
[home ~/]> run scripts/crawler.js --help
Running script with 1 thread(s), pid 1 and args: ["--help"].
/scripts/crawler.js:
Search the network for servers to execute a script against.
Usage: run crawler.js [OPTIONS] SCRIPT [ARGS]...
run crawler.js --help
SCRIPT Script to copy & execute
ARGS Arguments for script. Forward the discovered server with: {{SERVER}}
Options:
-c, --cpu Number of CPU threads to start script with, will use maximum if not specified
-d, --depth Depth to scan to, defaults to 3
-k, --kill Kill all running scripts on the server
--level Skip servers with higher hack level, defaults to current hack level
-e, --remote-exec Execute script on remote server
-r, --rooted Only servers that have been rooted
-n, --not-rooted Only servers that have not been rooted
-p, --ports Skip servers with too many closed ports
-q, --quite Suppress program output
-v, --verbose Display the server names in the final report
-h, --help Display this help message
```
</details>
<details>
<summary>
<h3 id="find-target" style="display: inline">find-target.js</h3>
</summary>
<br />
**RAM:** 4.05 GB | [Code](./scripts/find-target.js)
A utility to help figure out which server is worth hacking the most. It does this by estimating the financial yield per
minute for each server & returns the servers in a sorted list.
```
[home ~/]> run scripts/find-target.js --help
Running script with 1 thread(s), pid 1 and args: ["--help"].
/scripts/find-target.js:
Scan the network for the best servers(s) to hack.
Usage: run find-target.js [OPTIONS]
run find-target.js --help
Options:
-c, --count Number of servers to return
-r, --rooted Only servers that have been rooted
-n, --not-rooted Only servers that have not been rooted
-v, --verbose Display the estimated income per minute per core
-h, --help Display this help message
```
</details>
<details>
<summary>
<h3 id="hacknet" style="display: inline">hacknet-manager.js</h3>
</summary>
<br />
**RAM:** 5.70 GB | [Code](./scripts/hacknet-manager.js)
An early game solution to automate the hacknet & get easy money.
```
[home ~/]> run scripts/hacknet-manager.js --help
Running script with 1 thread(s), pid 1 and args: ["--help"].
/scripts/hacknet-manager.js:
Buy, upgrade & manage Hacknet nodes automatically. Tail for live updates.
Usage: run hacknet-manager.js [OPTIONS] [LIMIT]
run hacknet-manager.js --help
LIMIT Limit the number of nodes the manager will buy, defaults to 8 or the current number of nodes
Options:
-a, --auto-limit Automatically increase the node limit when there is nothing to do
-b, --balance Prevent spending bellow point
-s, --sleep Amount of time to wait between purchases, defaults to 1 (second)
-h, --help Display this help message
```
</details>
<details>
<summary>
<h3 id="miner" style="display: inline">miner.js</h3>
</summary>
<br />
**RAM:** 2.45 GB | [Code](./scripts/miner.js)
An early-game HGW script to steal money from servers. You can deploy this on each server and have them hack themselves,
or they can all target the server with the most money which is more efficient (see [find-target.js](#find-target)).
```
[home ~/]> run scripts/miner.js --help
Running script with 1 thread(s), pid 1 and args: ["--help"].
/scripts/miner.js:
Buy, upgrade & manage Hacknet nodes automatically. Tail for live updates.
Usage: run hacknet-manager.js [OPTIONS] [LIMIT]
run hacknet-manager.js --help
LIMIT Limit the number of nodes the manager will buy, defaults to 8 or the current number of nodes
Options:
-a, --auto-limit Automatically increase the node limit when there is nothing to do
-b, --balance Prevent spending bellow point
-s, --sleep Amount of time to wait between purchases, defaults to 1 (second)
-h, --help Display this help message
```
</details>
<details>
<summary>
<h3 id="network-graph" style="display: inline">network-graph.js</h3>
</summary>
<br />
**RAM:** 3.85 GB | [Code](./scripts/network-graph.js)
A utility to scan the network & build a visual tree of all the devices. It comes with lots of flags to narrow down the
results. It's useful for figuring out where you are, manually finding targets & discovering the path to a server &
connecting to it.
```
[home ~/]> run /scripts/network-graph.js --help
Running script with 1 thread(s), pid 1 and args: ["--help"].
/scripts/network-graph.js:
Scan the network for servers and display as an ASCII tree. Servers with root access are highlighted & bold. Click to
automatically connect.
Usage: run network-graph.js [OPTIONS] [SERVER]
run network-graph.js --help
SERVER Point to start scan from, defaults to local server
Options:
-d, --depth Depth to scan to
-f, --filter Filter to servers matching name
-e, --regex Filter to servers matching pattern
-l, --level Display the required hack level & number of ports to root: [level|port]
-n, --not-rooted Filter to servers that have not been rooted
-r, --rooted Filter to servers that have been rooted
-s, --specs Display the server specifications: {CPU|RAM}
-u, --usage Display the server utilization: (USG%)
-v, --verbose Display level, specs & usage in that order: [HL|P] {CPU|RAM} (USG%)
-h, --help Display this help message
```
</details>
<details>
<summary>
<h3 id="rm" style="display: inline">rm.js</h3>
</summary>
<br />
**RAM:** 2.85 GB | [Code](./scripts/rm.js)
[bitburner-connector](https://plugins.jetbrains.com/plugin/18338-bitburner-connector) would occasionally push my IDE
files to the game, so I created this simple script to recursively search & delete files from a directory to save me
from having to delete files one-by-one.
```
[home ~/scripts]> run /scripts/rm.js --help
Running script with 1 thread(s), pid 1 and args: ["--help"].
/scripts/rm.js:
Recursively delete files inside a directory
Usage: run rm.js [OPTIONS] PATH [SERVER]
run rm.js --help
PATH Path to recursively search
SERVER Run on remote server
Options:
-f, --force Remove game files (.exe, .lit, .msg)
-r, --recursive Delete everything inside directory
-h, --help Display this help message
```
</details>
<details>
<summary>
<h3 id="rootkit" style="display: inline">rootkit.js</h3>
</summary>
<br />
**RAM:** 4.65 GB | [Code](./scripts/rootkit.js)
Automatically gains root on the local or remote server. A script can be passed as an additional argument; it will be
copied and automatically executed with the maximum number of threads after being rooted.
```
[home ~/]> run scripts/rootkit.js --help
Running script with 1 thread(s), pid 1 and args: ["--help"].
/scripts/rootkit.js:
Scan the network for servers and display as an ASCII tree. Servers with root access are highlighted & bold.
Usage: run network-graph.js [OPTIONS] [SERVER]
run network-graph.js --help
SERVER Point to start scan from, defaults to local server
Options:
-d, --depth Depth to scan to
-f, --filter Filter to servers matching name
-e, --regex Filter to servers matching pattern
-l, --level Display the required hack level & number of ports to root: [level|port]
-n, --not-rooted Filter to servers that have not been rooted
-r, --rooted Filter to servers that have been rooted
-s, --specs Display the server specifications: {CPU|RAM}
-u, --usage Display the server utilization: (USG%)
-v, --verbose Display level, specs & usage in that order: [HL|P] {CPU|RAM} (USG%)
-h, --help Display this help message
```
</details>
<details>
<summary>
<h3 id="server-miner" style="display: inline">server-miner.js</h3>
</summary>
<br />
**RAM:** 11.35 GB | [Code](./scripts/server-manager.js)
Mid-game script to handle purchasing and upgrading servers for more computer power. You can also set a script to run
automatically after purchase. Useful to chain with `miner.js` or `botnet.js`.
```
[home ~/]> run /scripts/server-manager.js --help
Running script with 1 thread(s), pid 1 and args: ["--help"].
/scripts/server-manager.js:
Automate the buying & upgrading of servers. Automatically starts script after purchase. Tail for live updates.
Usage: run server-manager.js [OPTIONS] [SCRIPT] [ARGS]...
run server-manager.js --help
SCRIPT Script to copy & execute
ARGS Arguments for script. Forward the discovered server with: {{SERVER}}
Options:
-b, --balance Prevent spending bellow point
-c, --cpu Number of CPU threads to start script with, will use maximum if not specified
-l, --limit Limit the number of servers that can be purchased, defaults to 25
-r, --ram Amount of RAM to purchase new servers with, defaults to 8 GB
-s, --sleep Amount of time to wait between purchases, defaults to 1 (second)
-h, --help Display this help message
```
</details>
<details>
<summary>
<h3 id="update" style="display: inline">update.js</h3>
</summary>
<br />
**RAM:** 2.65 GB | [Code](./scripts/update.js)
Uses the in-game `wget` to download all the scripts in this repository. Can target remote servers to quickly copy the
entire toolkit to the target.
```
[home ~/]> run scripts/update.js --help
Running script with 1 thread(s), pid 1 and args: ["--help"].
/scripts/update.js:
Download the latest script updates from the repository using wget.
Usage: run update.js [OPTIONS] [DEVICE]
run update.js --help
DEVICE Device to update, defaults to current machine
Options:
--skip-self Skip updating self (for debugging & used internally)
--no-banner Hide the banner (Used internally)
-h, --help Display this help message
```
</details>
## License
Copyright © 2023 Zakary Timson | Available under MIT Licensing
See the [license](./LICENSE) for more information.
# BitBurner - Scripts
A collection of scripts & information pertaining to the [open source](https://github.com/danielyxie/bitburner) game
[BitBurner](https://danielyxie.github.io/bitburner/).
## Table of Contents
- [BitBurner - Scripts](#bitburner-scripts)
- [Table of Contents](#table-of-contents)
- [Quick Start](#quick-start)
- [Guide](#guide)
- [BitNode 1](#bitnode-1)
- [Scripts](#scripts)
- [banner.js](#bannerjs)
- [botnet-manager.js (WIP)](#botnet-managerjs-wip)
- [connect.js](#connectjs)
- [copy.js](#copyjs)
- [crawler.js](#crawlerjs)
- [find-target.js](#find-targetjs)
- [hacknet-manager.js](#hacknet-managerjs)
- [miner.js](#minerjs)
- [network-graph.js](#network-graphjs)
- [rm.js](#rmjs)
- [rootkit.js](#rootkitjs)
- [server-manager.js](#server-managerjs)
- [update.js](#updatejs)
## Quick Start
```bash
# Download the update script in-game & run it
wget https://gitlab.zakscode.com/ztimson/BitBurner/-/raw/develop/scripts/update.js scripts/update.js
run scripts/update.js # Repeat to pull the latest
# View the network
run scripts/network-graph.js --verbose
run scripts/netowkr-graph.js -v --filter CSEC # Find path to a specific device
# Start the node manager in auto-mode
run scripts/node-manager.js -a
# Chain the crawler & rootkit to root all devices on the network
run scripts/crawler.js --not-rooted /scripts/rootkit.js {{TARGET}}
# Find the most profitable server & use the crawler to deploy miners on the network targeting it
run scripts/find-target.js # Output: n00dles
run scriipts/crawler.js --rooted --remote-exec /scripts/miner.js n00dles
# Install backdoor on CSEC
run scripts/rootkit.js CSEC
run scripts/connect.js CSEC
backdoor
```
Learn more about the [available scripts](#scripts) bellow or pass the `--help` flag to any of the included scripts in-game.
## Guide
This guide documents how you can use this repository to progress through the game. You should complete the tutorial
first if you haven't already.
### BitNode 1
1. First you need to download this repo into the game. Manually download `update.js` & run it:
`wget https://gitlab.zakscode.com/ztimson/BitBurner/-/raw/develop/scripts/update.js scripts/update.js; run scripts/update.js`
2. Scan the network to figure out your bearings, take note of discovered server's required hack level:
`run scripts/network-graph.js -vd 3`
3. Root the lowest level server (probably n00dles) & make it hack itself for money. You should repeat this step when
ever your hack level is high enough to hack another a new server. `run scripts/rootkit.js n00dles /scripts/miner.js`
4. Start `hacknet-manger.js`. You won't have enough *RAM* in the beginning to run the manager & hack servers. It's
recommended you `tail` the manager, so you can easily start/stop it as needed. `run script/hacknet-manager.js -a`
5. Once you have enough money ($??,???.??), upgrade your home severs *RAM*:
`City > alpha ent. > Upgrade 'home' RAM (8.00GB -> 16.00GB)`
6. At this point you have enough *RAM* to use `crawler.js` to automatically discover servers & hack them. Continue to
run this periodically as your hack level increases & you unlock more exploits:
`run scripts/crawler.js -n /scripts/rootkit.js {{TARGET}} /scripts/miner.js`
## Scripts
### [banner.js](./scripts/banner.js)
**RAM:** 1.60 GB
Aesthetic & serves no real purpose. Prints a banner to the terminal & can repeat after game restarts.
```
[home ~/]> run scripts/banner.js --help
Running script with 1 thread(s), pid 1 and args: ["--help"].
/scripts/banner.js:
Display an ASCII banner.
Usage: run banner.js [OPTIONS]
run banner.js --help
Options:
-r, --reboot Automatically display after game reboots
-h, --help Display this help message
```
### [botnet-manager.js (WIP)](./scripts/botnet-manager.js)
**RAM:** 7.15 GB
Late-game solution to hack servers. It orchestrates an unlimited number of servers to carry out distributed batched
attacks against targets. It includes a bunch of utilities to quickly dispatch single commands to all workers. Manger
can be tailed for live updates.
```
[home ~/]> run /scripts/botnet-manager.js --help
Running script with 1 thread(s), pid 1 and args: ["--help"].
/scripts/botnet-manager.js:
Connect & manage a network of devices to launch distributed attacks.
Usage: run botnet-manager.js [OPTIONS]
run botnet-manager.js [OPTIONS] COMMAND
run botnet-manager.js --help [COMMAND]
Options:
-s, --silent Suppress program output
-h, --help Display this help message
Commands:
copy Copy file & dependencies to swarm nodes
join Connect device as a worker node to the swarm
kill Kill any scripts running on worker nodes
leave Disconnect worker node from swarm
run Copy & run script on all worker nodes
start Start this device as the swarm manager
```
### [connect.js](./scripts/connect.js)
**RAM:** 1.85 GB
The built in `connect` command only allows you to connect to devices in the immediate vicinity or servers that have
backdoors installed requiring you to make several jumps. This script will automatically find a path & connect you saving
you some time.
```
[home ~/]> run /scripts/connect.js --help
Running script with 1 thread(s), pid 1 and args: ["--help"].
/scripts/connect.js:
Connect to a server anywhere in the network without a backdoor.
Usage: run connect.js [OPTIONS] SERVER
run connect.js --help
SERVER Server to connect to
Options:
-h, --help Display this help message
```
### [copy.js](./scripts/copy.js)
**RAM:** 4.20 GB
Scripts often import other scripts requiring multiple `scp` calls before it can be run on a remote machine. This script
will automatically scan the file being copied for imports & recursively scan & copy the dependencies. Plus it has a
fancy animated loading bar.
```
[home ~/]> run scripts/copy.js --help
Running script with 1 thread(s), pid 1 and args: ["--help"].
/scripts/copy.js:
Copy a file & it's dependencies to a server.
Usage: run copy.js [OPTIONS] FILE SERVER [ARGS]...
run copy.js --help
FILE File to copy
SERVER Server to copy file(s) to
ARGS Arguments to start file/script with
Options:
-c, --cpu Number of CPU threads to start script with, will use maximum if not specified
-e, --execute Start script after copying
-n, --no-deps Skip copying dependencies
-q, --quite Suppress program output
-h, --help Display this help message
```
### [crawler.js](./scripts/crawler.js)
**RAM:** 5.80 GB
Mid-game solution to distribute & run scripts across the network.
```
[home ~/]> run scripts/crawler.js --help
Running script with 1 thread(s), pid 1 and args: ["--help"].
/scripts/crawler.js:
Search the network for servers to execute a script against.
Usage: run crawler.js [OPTIONS] SCRIPT [ARGS]...
run crawler.js --help
SCRIPT Script to copy & execute
ARGS Arguments for script. Forward the discovered server with: {{SERVER}}
Options:
-c, --cpu Number of CPU threads to start script with, will use maximum if not specified
-d, --depth Depth to scan to, defaults to 3
-k, --kill Kill all running scripts on the server
--level Skip servers with higher hack level, defaults to current hack level
-e, --remote-exec Execute script on remote server
-r, --rooted Only servers that have been rooted
-n, --not-rooted Only servers that have not been rooted
-p, --ports Skip servers with too many closed ports
-q, --quite Suppress program output
-v, --verbose Display the server names in the final report
-h, --help Display this help message
```
### [find-target.js](./scripts/find-target.js)
**RAM:** 4.05 GB
A utility to help figure out which server is worth hacking the most. It does this by estimating the financial yield per
minute for each server & returns the servers in a sorted list.
```
[home ~/]> run scripts/find-target.js --help
Running script with 1 thread(s), pid 1 and args: ["--help"].
/scripts/find-target.js:
Scan the network for the best servers(s) to hack.
Usage: run find-target.js [OPTIONS]
run find-target.js --help
Options:
-c, --count Number of servers to return
-r, --rooted Only servers that have been rooted
-n, --not-rooted Only servers that have not been rooted
-v, --verbose Display the estimated income per minute per core
-h, --help Display this help message
```
### [hacknet-manager.js](./scripts/hacknet-manager.js)
**RAM:** 5.70 GB
An early game solution to automate the hacknet & get easy money.
```
[home ~/]> run scripts/hacknet-manager.js --help
Running script with 1 thread(s), pid 1 and args: ["--help"].
/scripts/hacknet-manager.js:
Buy, upgrade & manage Hacknet nodes automatically. Tail for live updates.
Usage: run hacknet-manager.js [OPTIONS] [LIMIT]
run hacknet-manager.js --help
LIMIT Limit the number of nodes the manager will buy, defaults to 8 or the current number of nodes
Options:
-a, --auto-limit Automatically increase the node limit when there is nothing to do
-b, --balance Prevent spending bellow point
-s, --sleep Amount of time to wait between purchases, defaults to 1 (second)
-h, --help Display this help message
```
### [miner.js](./scripts/miner.js)
**RAM:** 2.45 GB
An early-game HGW script to steal money from servers. You can deploy this on each server and have them hack themselves,
or they can all target the server with the most money which is more efficient (see [find-target.js](#find-targetjs)).
```
[home ~/]> run scripts/miner.js --help
Running script with 1 thread(s), pid 1 and args: ["--help"].
/scripts/miner.js:
Buy, upgrade & manage Hacknet nodes automatically. Tail for live updates.
Usage: run hacknet-manager.js [OPTIONS] [LIMIT]
run hacknet-manager.js --help
LIMIT Limit the number of nodes the manager will buy, defaults to 8 or the current number of nodes
Options:
-a, --auto-limit Automatically increase the node limit when there is nothing to do
-b, --balance Prevent spending bellow point
-s, --sleep Amount of time to wait between purchases, defaults to 1 (second)
-h, --help Display this help message
```
### [network-graph.js](./scripts/network-graph.js)
**RAM:** 3.85 GB
A utility to scan the network & build a visual tree of all the devices. It comes with lots of flags to narrow down the
results. It's useful for figuring out where you are, manually finding targets & discovering the path to a server &
connecting to it.
```
[home ~/]> run /scripts/network-graph.js --help
Running script with 1 thread(s), pid 1 and args: ["--help"].
/scripts/network-graph.js:
Scan the network for servers and display as an ASCII tree. Servers with root access are highlighted & bold. Click to
automatically connect.
Usage: run network-graph.js [OPTIONS] [SERVER]
run network-graph.js --help
SERVER Point to start scan from, defaults to local server
Options:
-d, --depth Depth to scan to
-f, --filter Filter to servers matching name
-e, --regex Filter to servers matching pattern
-l, --level Display the required hack level & number of ports to root: [level|port]
-n, --not-rooted Filter to servers that have not been rooted
-r, --rooted Filter to servers that have been rooted
-s, --specs Display the server specifications: {CPU|RAM}
-u, --usage Display the server utilization: (USG%)
-v, --verbose Display level, specs & usage in that order: [HL|P] {CPU|RAM} (USG%)
-h, --help Display this help message
```
### [rm.js](./scripts/rm.js)
**RAM:** 2.85 GB
[BitBurner-Connector](https://plugins.jetbrains.com/plugin/18338-bitburner-connector) would occasionally push my IDE
files to the game, so I created this simple script to recursively search & delete files from a directory to save me
from having to delete files one-by-one.
```
[home ~/scripts]> run /scripts/rm.js --help
Running script with 1 thread(s), pid 1 and args: ["--help"].
/scripts/rm.js:
Recursively delete files inside a directory
Usage: run rm.js [OPTIONS] PATH [SERVER]
run rm.js --help
PATH Path to recursively search
SERVER Run on remote server
Options:
-f, --force Remove game files (.exe, .lit, .msg)
-r, --recursive Delete everything inside directory
-h, --help Display this help message
```
### [rootkit.js](./scripts/rootkit.js)
**RAM:** 4.65 GB
Automatically gains root on the local or remote server. A script can be passed as an additional argument; it will be
copied and automatically executed with the maximum number of threads after being rooted.
```
[home ~/]> run scripts/rootkit.js --help
Running script with 1 thread(s), pid 1 and args: ["--help"].
/scripts/rootkit.js:
Scan the network for servers and display as an ASCII tree. Servers with root access are highlighted & bold.
Usage: run network-graph.js [OPTIONS] [SERVER]
run network-graph.js --help
SERVER Point to start scan from, defaults to local server
Options:
-d, --depth Depth to scan to
-f, --filter Filter to servers matching name
-e, --regex Filter to servers matching pattern
-l, --level Display the required hack level & number of ports to root: [level|port]
-n, --not-rooted Filter to servers that have not been rooted
-r, --rooted Filter to servers that have been rooted
-s, --specs Display the server specifications: {CPU|RAM}
-u, --usage Display the server utilization: (USG%)
-v, --verbose Display level, specs & usage in that order: [HL|P] {CPU|RAM} (USG%)
-h, --help Display this help message
```
### [server-manager.js](./scripts/server-manager.js)
**RAM:** 11.35 GB
Mid-game script to handle purchasing and upgrading servers for more computer power. You can also set a script to run
automatically after purchase. Useful to chain with `miner.js` or `botnet.js`.
```
[home ~/]> run /scripts/server-manager.js --help
Running script with 1 thread(s), pid 1 and args: ["--help"].
/scripts/server-manager.js:
Automate the buying & upgrading of servers. Automatically starts script after purchase. Tail for live updates.
Usage: run server-manager.js [OPTIONS] [SCRIPT] [ARGS]...
run server-manager.js --help
SCRIPT Script to copy & execute
ARGS Arguments for script. Forward the discovered server with: {{SERVER}}
Options:
-b, --balance Prevent spending bellow point
-c, --cpu Number of CPU threads to start script with, will use maximum if not specified
-l, --limit Limit the number of servers that can be purchased, defaults to 25
-r, --ram Amount of RAM to purchase new servers with, defaults to 8 GB
-s, --sleep Amount of time to wait between purchases, defaults to 1 (second)
-h, --help Display this help message
```
### [update.js](./scripts/update.js)
**RAM:** 2.65 GB
Uses the in-game `wget` to download all the scripts in this repository. Can target remote servers to quickly copy the
entire toolkit to the target.
```
[home ~/]> run scripts/update.js --help
Running script with 1 thread(s), pid 1 and args: ["--help"].
/scripts/update.js:
Download the latest script updates from the repository using wget.
Usage: run update.js [OPTIONS] [DEVICE]
run update.js --help
DEVICE Device to update, defaults to current machine
Options:
--skip-self Skip updating self (for debugging & used internally)
--no-banner Hide the banner (Used internally)
-h, --help Display this help message
```

View File

@ -1,49 +1,49 @@
import {ArgParser} from "/scripts/lib/arg-parser";
/**
* Display an ASCII banner, optionally automatically after reboots.
*
* @param {NS} ns - BitBurner API
*/
export async function main(ns) {
// Setup
ns.disableLog('ALL');
const argParser = new ArgParser('banner.js', 'Display an ASCII banner.', [
{name: 'reboot', desc: 'Automatically display after game reboots', flags: ['-r', '--reboot'], default: false}
]);
const args = argParser.parse(ns.args);
// Help
if(args['help'] || args['_error'].length)
return ns.tprint(argParser.help(args['help'] ? null : args['_error'][0], args['_command']));
ns.tprint(`
&&&&&&&& O &&&&&&&&
&&& & && CDDDD &&&&&&&&&&
&&&& &&& && &&& &&&&&&&&&&&&&
&&&&& && && & .&&&. &&&&&&&&&&&&&&
&&&&&&&&&& && && &&&&& &&&&&&&&&&&&&&&
&&&&&&&& && & &&&&& &&&&&&&&&&&&&&&&
&&&&&&&&&& &&& &&&&& &&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&& *&&&* *&&&&&&&&&&&&&&&
&&&&&&&&&&&&& &&&&&&&&& *&&&&&&* .&&
&&&&&&&&&&& &&& & & &&& &&* .&&&
&&&&&&&&&& & & ,,,,,* .&&&&
&&&&& & & &&&&&&&&&&&&&&&&
&& &&&& & & & &&&&&&&&&&&&&&
&& &&&&&&& & & & &&&&&* &&&&&
&& &&&&&&&& & & &&&&&&&* &&&*
&& &&&&&&&&&&& & & &&&& &*
&& &&&&&&&&& & & && &&
&&& &&&&&& & & && &&
&&& &&&& & & && &&
&&&& &&& & & && &&
&&&&&&& \\&/ && &&
&&&&&& V &* &*
`);
// Prevent from exiting so the banner will automatically display on startup.
if(args['reboot']) while(true) { await ns.sleep(1000 * 60); }
}
import {ArgParser} from "/scripts/lib/arg-parser";
/**
* Display an ASCII banner, optionally automatically after reboots.
*
* @param {NS} ns - BitBurner API
*/
export async function main(ns) {
// Setup
ns.disableLog('ALL');
const argParser = new ArgParser('banner.js', 'Display an ASCII banner.', [
{name: 'reboot', desc: 'Automatically display after game reboots', flags: ['-r', '--reboot'], default: false}
]);
const args = argParser.parse(ns.args);
// Help
if(args['help'] || args['_error'].length)
return ns.tprint(argParser.help(args['help'] ? null : args['_error'][0], args['_command']));
ns.tprint(`
&&&&&&&& O &&&&&&&&
&&& & && CDDDD &&&&&&&&&&
&&&& &&& && &&& &&&&&&&&&&&&&
&&&&& && && & .&&&. &&&&&&&&&&&&&&
&&&&&&&&&& && && &&&&& &&&&&&&&&&&&&&&
&&&&&&&& && & &&&&& &&&&&&&&&&&&&&&&
&&&&&&&&&& &&& &&&&& &&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&& *&&&* *&&&&&&&&&&&&&&&
&&&&&&&&&&&&& &&&&&&&&& *&&&&&&* .&&
&&&&&&&&&&& &&& & & &&& &&* .&&&
&&&&&&&&&& & & ,,,,,* .&&&&
&&&&& & & &&&&&&&&&&&&&&&&
&& &&&& & & & &&&&&&&&&&&&&&
&& &&&&&&& & & & &&&&&* &&&&&
&& &&&&&&&& & & &&&&&&&* &&&*
&& &&&&&&&&&&& & & &&&& &*
&& &&&&&&&&& & & && &&
&&& &&&&&& & & && &&
&&& &&&& & & && &&
&&&& &&& & & && &&
&&&&&&& \\&/ && &&
&&&&&& V &* &*
`);
// Prevent from exiting so the banner will automatically display on startup.
if(args['reboot']) while(true) { await ns.sleep(1000 * 60); }
}

34
scripts/bitburner.js Normal file
View File

@ -0,0 +1,34 @@
/**
* Automatically complete the current BitNode.
*
* @param {NS} ns - BitBurner API
*/
export function main(ns) {
let modules = [
'auto-root',
'auto-hack',
'botnet-manager',
'hacknet-manager',
'server-manager'
];
// Banner
ns.run('/scripts/banner.js', 1, '-r');
ns.tprint(`Starting BitBurner with ${modules.length} enabled: `);
ns.tprint(modules.join(', '));
// botnet-manager
// hacknet-manager
ns.run('/scripts/hacknet-manager', 1, '-a');
// server-manager
ns.run('/scripts/server-manager', 1, '');
while(true) {
// auto-hack
ns.sleep(1000);
}
}

View File

@ -1,16 +1,20 @@
import {ArgParser} from '/scripts/lib/arg-parser';
import {Config} from '/scripts/lib/data-file';
import {Logger} from '/scripts/lib/logger';
import {copyWithDependencies} from '/scripts/copy';
const configPath = '/etc/botnet.txt';
const port = 1;
class Manager {
running;
workers = [];
constructor(ns, device, port, config = '/conf/botnet.txt') {
async constructor(ns, hostname) {
ns.disableLog('ALL');
this.ns = ns;
this.config = config;
this.device = device;
this.config = new Config(configPath);
this.hostname = hostname;
this.logger = new Logger(this.ns, [
() => `Botnet: ${device}`,
() => `Workers: ${this.workers.length}\tCores: ${this.workers.reduce((acc, w) => acc + w.cpuCores, 0)}\tRAM: ${this.workers.reduce((acc, w) => acc + w.maxRam, 0)} GB`
@ -124,7 +128,8 @@ class Manager {
export async function main(ns) {
// Setup
ns.disableLog('ALL');
const hostname = ns.getHostname(), portNum = 1;
const config = await new Config(ns, configPath).load();
const hostname = ns.getHostname();
const argParser = new ArgParser('botnet-manager.js', 'Connect & manage a network of servers to launch distributed attacks.', [
new ArgParser('copy', 'Copy file & dependencies to botnet', [
{name: 'file', desc: 'File to copy', default: false},
@ -139,6 +144,7 @@ export async function main(ns) {
new ArgParser('leave', 'Disconnect worker node from swarm', [
{name: 'device', desc: 'Device to disconnect, defaults to the current machine', optional: true, default: hostname}
]),
new ArgParser('list', 'List connected worker nodes'),
new ArgParser('run', 'Copy & run script on the botnet', [
{name: 'script', desc: 'Script to copy & execute', type: 'string'},
{name: 'args', desc: 'Arguments for script. Forward the current target with: {{TARGET}}', optional: true, extras: true},
@ -154,9 +160,9 @@ export async function main(ns) {
// Run command
if(args['_command'] == 'start') { // Start botnet manager
ns.tprint(`Starting ${hostname} as botnet manager`);
ns.tprint(`Connect more nodes with: run botnet-manager.js join [SERVER]`);
await new Manager(ns, hostname, portNum).start();
ns.tprint(`Starting botnet controller on: ${hostname}`);
ns.tprint(`Connect workers to botnet with: run botnet-manager.js join [SERVER]`);
await new Manager(ns, hostname).start();
} else if(args['_command'] == 'copy') { // Issue copy command
await ns.writePort(portNum, JSON.stringify({
command: 'copy',
@ -176,6 +182,9 @@ export async function main(ns) {
command: 'leave',
value: args['device']
}));
} else if(args['_command'] == 'list') {
ns.tprint('Botnet workers:');
ns.tprint(config['workers'].map(worker => worker.hostname).join(', '));
} else if(args['_command'] == 'run') { // Issue run command
await ns.writePort(portNum, JSON.stringify({
command: 'run',

View File

@ -1,107 +1,107 @@
import {ArgParser} from '/scripts/lib/arg-parser';
import {maxThreads, progressBar} from '/scripts/lib/utils';
/**
* Copy a file & it's dependencies to a server.
*
* @param {NS} ns - BitBurner API
* @param {string} src - File to scan & copy
* @param {string} server - Device to copy files to
* @returns {Promise<string[]>} - Array of copied files
*/
export async function copyWithDependencies(ns, src, server) {
const queue = [src], found = [src];
while(queue.length) {
const file = queue.splice(0, 1)[0];
const imports = new RegExp(/from ["']\.?(\/.+)["']/g);
const script = await ns.read(file);
let match;
while((match = imports.exec(script)) != null) {
const path = `${match[1]}.js`;
if(!found.includes(path)) found.push(path);
queue.push(path);
}
}
await ns.scp(found, server);
return found.reverse();
}
/**
* Copy a file & it's dependencies to a server.
*
* @param {NS} ns - BitBurner API
*/
export async function main(ns) {
// Setup
ns.disableLog('ALL');
const argParser = new ArgParser('copy.js', 'Copy a file & it\'s dependencies to a server.', [
{name: 'file', desc: 'File to copy'},
{name: 'server', desc: 'Server to copy file(s) to'},
{name: 'args', desc: 'Arguments to start file/script with', optional: true, extras: true},
{name: 'cpu', desc: 'Number of CPU threads to start script with, will use maximum if not specified', flags: ['-c', '--cpu']},
{name: 'execute', desc: 'Start script after copying', flags: ['-e', '--execute'], default: false},
{name: 'noDeps', desc: 'Skip copying dependencies', flags: ['-n', '--no-deps'], default: false},
{name: 'quite', desc: 'Suppress program output', flags: ['-q', '--quite'], default: false},
]);
const args = argParser.parse(ns.args);
// Help
if(args['help'] || args['_error'].length)
return ns.tprint(argParser.help(args['help'] ? null : args['_error'][0], args['_command']));
// Banner
if(!args['quite']) {
ns.tprint('===================================================');
ns.tprint(`Copying: ${args['server']}`);
ns.tprint('===================================================');
ns.tprint('');
ns.tprint('Copying Files:');
await ns.sleep(500);
}
// Copy files & create download bar
if(args['noDeps']) {
await ns.scp(args['file'], args['server']);
if(!args['quite']) await progressBar(ns, args['file']);
} else {
const files = await copyWithDependencies(ns, args['file'], args['server']);
if(!args['quite']) {
for(let file of files) {
await progressBar(ns, file);
}
}
}
// Run the script if requested
if(args['execute']) {
const threads = args['cpu'] || maxThreads(ns, args['file'], args['server']) || 1;
if(!args['quite']) {
ns.tprint('');
ns.tprint(`Executing with ${threads} thread${threads > 1 ? 's' : ''}...`);
await ns.sleep(500);
}
ns.killall(args['server']);
const pid = ns.exec(args['file'], args['server'], threads, ...args['args']);
if(!args['quite']) {
ns.tprint(!!pid ? 'Done!' : 'Failed to start');
ns.tprint('');
}
}
// Done message
if(!args['quite']) {
ns.tprint('');
ns.tprint('Done!');
ns.tprint('');
}
}
/**
* BitBurner autocomplete.
*
* @param {{servers: string[], txts: string[], scripts: string[], flags: string[]}} data - Contextual information
* @returns {string[]} - Pool of autocomplete options
*/
export function autocomplete(data) {
return [...data.servers, ...data.scripts];
}
import {ArgParser} from '/scripts/lib/arg-parser';
import {maxThreads, progressBar} from '/scripts/lib/utils';
/**
* Copy a file & it's dependencies to a server.
*
* @param {NS} ns - BitBurner API
* @param {string} src - File to scan & copy
* @param {string} server - Device to copy files to
* @returns {Promise<string[]>} - Array of copied files
*/
export async function copyWithDependencies(ns, src, server) {
const queue = [src], found = [src];
while(queue.length) {
const file = queue.splice(0, 1)[0];
const imports = new RegExp(/from ["']\.?(\/.+)["']/g);
const script = await ns.read(file);
let match;
while((match = imports.exec(script)) != null) {
const path = `${match[1]}.js`;
if(!found.includes(path)) found.push(path);
queue.push(path);
}
}
await ns.scp(found, server);
return found.reverse();
}
/**
* Copy a file & it's dependencies to a server.
*
* @param {NS} ns - BitBurner API
*/
export async function main(ns) {
// Setup
ns.disableLog('ALL');
const argParser = new ArgParser('copy.js', 'Copy a file & it\'s dependencies to a server.', [
{name: 'file', desc: 'File to copy'},
{name: 'server', desc: 'Server to copy file(s) to'},
{name: 'args', desc: 'Arguments to start file/script with', optional: true, extras: true},
{name: 'cpu', desc: 'Number of CPU threads to start script with, will use maximum if not specified', flags: ['-c', '--cpu']},
{name: 'execute', desc: 'Start script after copying', flags: ['-e', '--execute'], default: false},
{name: 'noDeps', desc: 'Skip copying dependencies', flags: ['-n', '--no-deps'], default: false},
{name: 'quite', desc: 'Suppress program output', flags: ['-q', '--quite'], default: false},
]);
const args = argParser.parse(ns.args);
// Help
if(args['help'] || args['_error'].length)
return ns.tprint(argParser.help(args['help'] ? null : args['_error'][0], args['_command']));
// Banner
if(!args['quite']) {
ns.tprint('===================================================');
ns.tprint(`Copying: ${args['server']}`);
ns.tprint('===================================================');
ns.tprint('');
ns.tprint('Copying Files:');
await ns.sleep(500);
}
// Copy files & create download bar
if(args['noDeps']) {
await ns.scp(args['file'], args['server']);
if(!args['quite']) await progressBar(ns, args['file']);
} else {
const files = await copyWithDependencies(ns, args['file'], args['server']);
if(!args['quite']) {
for(let file of files) {
await progressBar(ns, file);
}
}
}
// Run the script if requested
if(args['execute']) {
const threads = args['cpu'] || maxThreads(ns, args['file'], args['server']) || 1;
if(!args['quite']) {
ns.tprint('');
ns.tprint(`Executing with ${threads} thread${threads > 1 ? 's' : ''}...`);
await ns.sleep(500);
}
ns.killall(args['server']);
const pid = ns.exec(args['file'], args['server'], threads, ...args['args']);
if(!args['quite']) {
ns.tprint(!!pid ? 'Done!' : 'Failed to start');
ns.tprint('');
}
}
// Done message
if(!args['quite']) {
ns.tprint('');
ns.tprint('Done!');
ns.tprint('');
}
}
/**
* BitBurner autocomplete.
*
* @param {{servers: string[], txts: string[], scripts: string[], flags: string[]}} data - Contextual information
* @returns {string[]} - Pool of autocomplete options
*/
export function autocomplete(data) {
return [...data.servers, ...data.scripts];
}

View File

@ -1,68 +1,68 @@
import {ArgParser} from '/scripts/lib/arg-parser';
import {toCurrency} from '/scripts/lib/utils';
import {scanNetwork} from '/scripts/crawler';
/**
* Sort array of servers based on the potential return/yield.
*
* @param {NS} ns - BitBurner API
* @param {string[]} servers - List of servers to sort based on yield
* @returns {[string, number][]} - Sorted list of servers & their potential yield per minute
*/
export function bestTarget(ns, servers) {
return servers.map(s => [s, serverYield(ns, s)]).sort((a, b) => {
if(a[1] < b[1]) return 1;
if(a[1] > b[1]) return -1;
return 0;
});
}
/**
* Calculate the average return per minute when hacking a server.
*
* **Disclaimer:** Does not take into account security or weaken time.
*
* @param {NS} ns - BitBurner API
* @param {string} server - Server to calculate yield for
* @returns {number} - $/minute
*/
export function serverYield(ns, server) {
return (ns.hackAnalyze(server) * ns.getServerMaxMoney(server))
* ((60 / (ns.getHackTime(server) / 1000)) * ns.hackAnalyzeChance(server));
}
/**
* Scan the network for the best server(s) to hack.
*
* @param ns {NS} - BitBurner API
* @returns {*}
*/
export function main(ns) {
// Setup
ns.disableLog('ALL');
const argParser = new ArgParser('find-target.js', 'Scan the network for the best servers(s) to hack.',[
{name: 'count', desc: 'Number of servers to return', flags: ['-c', '--count'], default: Infinity},
{name: 'rooted', desc: 'Only servers that have been rooted', flags: ['-r', '--rooted'], default: false},
{name: 'notRooted', desc: 'Only servers that have not been rooted', flags: ['-n', '--not-rooted'], default: false},
{name: 'verbose', desc: 'Display the estimated income per minute per core', flags: ['-v', '--verbose'], default: false},
]);
const args = argParser.parse(ns.args);
// Help
if(args['help'] || args['_error'].length)
return ns.tprint(argParser.help(args['help'] ? null : args['_error'][0], args['_command']));
// Banner
ns.tprint('===================================================');
ns.tprint(`Finding Targets:`);
ns.tprint('===================================================');
// Search & display results
const [servers, ignore] = scanNetwork(ns);
bestTarget(ns, servers).map(s => [...s, ns.hasRootAccess(s[0])])
.filter(s => (!args['rooted'] || s[2]) || (!args['notRooted'] || !s[2]))
.filter((s, i) => i < args['count'])
.map(s => `${s[0]}${args['verbose'] ? ` (~${toCurrency(s[1])}/min)` : ''}`)
.forEach((s, i) => ns.tprint(`${i + 1}) ${s}`));
ns.tprint('');
}
import {ArgParser} from '/scripts/lib/arg-parser';
import {toCurrency} from '/scripts/lib/utils';
import {scanNetwork} from '/scripts/crawler';
/**
* Sort array of servers based on the potential return/yield.
*
* @param {NS} ns - BitBurner API
* @param {string[]} servers - List of servers to sort based on yield
* @returns {[string, number][]} - Sorted list of servers & their potential yield per minute
*/
export function bestTarget(ns, servers) {
return servers.map(s => [s, serverYield(ns, s)]).sort((a, b) => {
if(a[1] < b[1]) return 1;
if(a[1] > b[1]) return -1;
return 0;
});
}
/**
* Calculate the average return per minute when hacking a server.
*
* **Disclaimer:** Does not take into account security or weaken time.
*
* @param {NS} ns - BitBurner API
* @param {string} server - Server to calculate yield for
* @returns {number} - $/minute
*/
export function serverYield(ns, server) {
return (ns.hackAnalyze(server) * ns.getServerMaxMoney(server))
* ((60 / (ns.getHackTime(server) / 1000)) * ns.hackAnalyzeChance(server));
}
/**
* Scan the network for the best server(s) to hack.
*
* @param ns {NS} - BitBurner API
* @returns {*}
*/
export function main(ns) {
// Setup
ns.disableLog('ALL');
const argParser = new ArgParser('find-target.js', 'Scan the network for the best servers(s) to hack.',[
{name: 'count', desc: 'Number of servers to return', flags: ['-c', '--count'], default: Infinity},
{name: 'rooted', desc: 'Only servers that have been rooted', flags: ['-r', '--rooted'], default: false},
{name: 'notRooted', desc: 'Only servers that have not been rooted', flags: ['-n', '--not-rooted'], default: false},
{name: 'verbose', desc: 'Display the estimated income per minute per core', flags: ['-v', '--verbose'], default: false},
]);
const args = argParser.parse(ns.args);
// Help
if(args['help'] || args['_error'].length)
return ns.tprint(argParser.help(args['help'] ? null : args['_error'][0], args['_command']));
// Banner
ns.tprint('===================================================');
ns.tprint(`Finding Targets:`);
ns.tprint('===================================================');
// Search & display results
const [servers, ignore] = scanNetwork(ns);
bestTarget(ns, servers).map(s => [...s, ns.hasRootAccess(s[0])])
.filter(s => (!args['rooted'] || s[2]) || (!args['notRooted'] || !s[2]))
.filter((s, i) => i < args['count'])
.map(s => `${s[0]}${args['verbose'] ? ` (~${toCurrency(s[1])}/min)` : ''}`)
.forEach((s, i) => ns.tprint(`${i + 1}) ${s}`));
ns.tprint('');
}

31
scripts/lib/data-file.js Normal file
View File

@ -0,0 +1,31 @@
export class DataFile {
/**
* Read & write data to a JSON file.
*
* @param {NS} ns - Bitburner API
* @param path - Path to config file
*/
constructor(ns, path) {
this.ns = ns;
this.path = path;
}
/**
* Load data file
*
* @returns {Promise<any>} - Saved data
*/
async load() {
return JSON.parse(await this.ns.read(this.path) || 'null');
}
/**
* Save data to file
*
* @param values - Data to save
* @returns {Promise<void>} - Save complete
*/
async save(values) {
await this.ns.write(this.path, JSON.stringify(values), 'w');
}
}

View File

@ -0,0 +1,42 @@
export class PortHelper {
/**
*
* @param ns
* @param port
* @param host
*/
constructor(ns, port, host) {
this.ns = ns;
this.host = host;
this.portNum = port;
this.port = ns.getPortHandle(port);
this.callbacks = {};
}
check() {
const pending = [];
while(!this.port.empty()) pending.push(this.port.read());
pending.filter(p => {
try {
const payload = JSON.parse(p);
if(this.callbacks[payload.subject]) return !this.callbacks[payload.subject](payload.value);
if(this.callbacks['*']) return !this.callbacks['*'](payload.value);
return true;
} catch {
return true;
}
}).forEach(p => this.port.write(p));
}
subscribe(subject, callback) { if(typeof callback == 'function') this.callbacks[subject] = callback; }
send(subject, value) {
this.ns.writePort(this.portNum, JSON.stringify({
from: this.host,
subject,
value
}));
}
unsubscribe(subject) { delete this.callbacks[subject]; }
}

View File

@ -1,39 +1,39 @@
import {ArgParser} from '/scripts/lib/arg-parser';
/**
* Recursively delete files inside a path. Equivalent to the Unix "rm -r".
* @param {NS} ns - BitBurner API
*/
export function main(ns) {
// Setup
ns.disableLog('ALL');
const argParser = new ArgParser('rm.js', 'Recursively delete files inside a directory', [
{name: 'path', desc: 'Path to recursively search'},
{name: 'server', desc: 'Run on remote server', optional: true, default: ns.getHostname()},
{name: 'force', desc: 'Remove game files (.exe, .lit, .msg)', flags: ['-f', '--force'], default: false},
{name: 'recursive', desc: 'Delete everything inside directory', flags: ['-r', '--recursive'], default: true}
]);
const args = argParser.parse(ns.args);
// Help
if(args['help'] || args['_error'].length)
return ns.tprint(argParser.help(args['help'] ? null : args['_error'][0], args['_command']));
// Run
ns.ls(args['server'], args['path'])
.filter(f => new RegExp(/\.(exe|lit|msg)$/g).test(f) ? args['force'] : true)
.forEach(f => ns.rm(f, args['server']));
}
/**
* BitBurner autocomplete.
*
* @param {{servers: string[], txts: string[], scripts: string[], flags: string[]}} data - Contextual information
* @returns {string[]} - Pool of autocomplete options
*/
export function autocomplete(data) {
return [...data.txts, ...data.scripts]
.map(file => file.split('/').slice(0, -1).join('/'))
.filter((path, i, arr) => arr.indexOf(path) == i)
.concat(data.txts, data.scripts);
}
import {ArgParser} from '/scripts/lib/arg-parser';
/**
* Recursively delete files inside a path. Equivalent to the Unix "rm -r".
* @param {NS} ns - BitBurner API
*/
export function main(ns) {
// Setup
ns.disableLog('ALL');
const argParser = new ArgParser('rm.js', 'Recursively delete files inside a directory', [
{name: 'path', desc: 'Path to recursively search'},
{name: 'server', desc: 'Run on remote server', optional: true, default: ns.getHostname()},
{name: 'force', desc: 'Remove game files (.exe, .lit, .msg)', flags: ['-f', '--force'], default: false},
{name: 'recursive', desc: 'Delete everything inside directory', flags: ['-r', '--recursive'], default: true}
]);
const args = argParser.parse(ns.args);
// Help
if(args['help'] || args['_error'].length)
return ns.tprint(argParser.help(args['help'] ? null : args['_error'][0], args['_command']));
// Run
ns.ls(args['server'], args['path'])
.filter(f => new RegExp(/\.(exe|lit|msg)$/g).test(f) ? args['force'] : true)
.forEach(f => ns.rm(f, args['server']));
}
/**
* BitBurner autocomplete.
*
* @param {{servers: string[], txts: string[], scripts: string[], flags: string[]}} data - Contextual information
* @returns {string[]} - Pool of autocomplete options
*/
export function autocomplete(data) {
return [...data.txts, ...data.scripts]
.map(file => file.split('/').slice(0, -1).join('/'))
.filter((path, i, arr) => arr.indexOf(path) == i)
.concat(data.txts, data.scripts);
}

View File

@ -1,87 +1,87 @@
import {ArgParser} from '/scripts/lib/arg-parser';
import {Logger} from '/scripts/lib/logger';
import {maxThreads, toCurrency} from '/scripts/lib/utils';
import {copyWithDependencies} from "/scripts/copy";
/**
* Automate the buying & upgrading of servers.
*
* @param {NS} ns - BitBurner API
*/
export async function main(ns) {
// Setup
ns.disableLog('ALL');
let servers = ns.getPurchasedServers();
const logger = new Logger(ns, [
() => `Server Manager: ${servers.length}`
]);
const argParser = new ArgParser('server-manager.js', 'Automate the buying & upgrading of servers. Automatically starts script after purchase. Tail for live updates.', [
{name: 'script', desc: 'Script to copy & execute', optional: true},
{name: 'args', desc: 'Arguments for script. Forward the discovered server with: {{SERVER}}', optional: true, extras: true},
{name: 'balance', desc: 'Prevent spending bellow point', flags: ['-b', '--balance'], default: 0},
{name: 'cpu', desc: 'Number of CPU threads to start script with, will use maximum if not specified', flags: ['-c', '--cpu'], default: false},
{name: 'limit', desc: 'Limit the number of servers that can be purchased, defaults to 25', flags: ['-l', '--limit'], default: 25},
{name: 'ram', desc: 'Amount of RAM to purchase new servers with, defaults to 8 GB', flags: ['-r', '--ram'], default: 8},
{name: 'sleep', desc: 'Amount of time to wait between purchases, defaults to 1 (second)', flags: ['-s', '--sleep'], default: 1}
]);
const args = argParser.parse(ns.args);
const serverPrefix = 'botnet_'
const maxRam = ns.getPurchasedServerMaxRam();
const minRamCost = ns.getPurchasedServerCost(args['ram']);
async function startScript(server) {
await copyWithDependencies(ns, args['script'], server);
const threads = args['cpu'] || maxThreads(ns, args['script'], server) || 1;
const pid = ns.exec(args['script'], server, threads, ...args['args']);
logger.log(`Starting "${args['script']}" with ${threads} thread${threads > 1 ? 's' : ''}`);
logger[pid == -1 ? 'warn' : 'log'](pid == -1 ? 'Done!' : 'Failed to start');
}
// Help
if(args['help'] || args['_error'].length)
return ns.tprint(argParser.help(args['help'] ? null : args['_error'][0], args['_command']));
// Main loop
// noinspection InfiniteLoopJS
while(true) {
servers = ns.getPurchasedServers();
const balance = ns.getServerMoneyAvailable('home');
// Purchase new server if we can afford it
if(servers.length < args['limit'] && balance - minRamCost > args['balance']) {
logger.log(`Buying server (${args['ram']} GB): ${toCurrency(minRamCost)}`);
ns.purchaseServer(`${serverPrefix}${servers.length}`, args['ram']);
// Run the script if requested
if(args['script']) await startScript(`${serverPrefix}${servers.length}`);
} else { // Check for upgrades
let upgrades = servers.map(server => {
// Calculate next RAM upgrades (must be a power of two: 2, 4, 8, 16, 32...)
let ram = Math.pow(2, Math.log2(ns.getServerMaxRam(server)) + 1);
if(ram > maxRam) ram = null;
return {
server,
ram,
cost: ram ? ns.getPurchasedServerCost(ram) : null
}
});
upgrades = upgrades.sort((a, b) => { // Sort by price
if(a.cost < b.cost) return 1;
if(a.cost < b.cost) return -1;
return 0;
});
// Do the cheapest upgrade if we can afford it
const upgrade = upgrades[0];
if(upgrade && !!upgrade.ram && balance - upgrade.cost > args['balance']) {
logger.log(`Upgrading ${upgrade.server}: ${upgrade.ram} GB / ${toCurrency(upgrade.cost)}`);
ns.killall(upgrade.server);
ns.deleteServer(upgrade.server);
ns.purchaseServer(upgrade.server, upgrade.ram);
// Run the script if requested
if(args['script']) await startScript(upgrade.server);
}
}
await ns.sleep(args['sleep'] * 1000);
}
}
import {ArgParser} from '/scripts/lib/arg-parser';
import {Logger} from '/scripts/lib/logger';
import {maxThreads, toCurrency} from '/scripts/lib/utils';
import {copyWithDependencies} from "/scripts/copy";
/**
* Automate the buying & upgrading of servers.
*
* @param {NS} ns - BitBurner API
*/
export async function main(ns) {
// Setup
ns.disableLog('ALL');
let servers = ns.getPurchasedServers();
const logger = new Logger(ns, [
() => `Server Manager: ${servers.length}`
]);
const argParser = new ArgParser('server-manager.js', 'Automate the buying & upgrading of servers. Automatically starts script after purchase. Tail for live updates.', [
{name: 'script', desc: 'Script to copy & execute', optional: true},
{name: 'args', desc: 'Arguments for script. Forward the discovered server with: {{SERVER}}', optional: true, extras: true},
{name: 'balance', desc: 'Prevent spending bellow point', flags: ['-b', '--balance'], default: 0},
{name: 'cpu', desc: 'Number of CPU threads to start script with, will use maximum if not specified', flags: ['-c', '--cpu'], default: false},
{name: 'limit', desc: 'Limit the number of servers that can be purchased, defaults to 25', flags: ['-l', '--limit'], default: 25},
{name: 'ram', desc: 'Amount of RAM to purchase new servers with, defaults to 8 GB', flags: ['-r', '--ram'], default: 8},
{name: 'sleep', desc: 'Amount of time to wait between purchases, defaults to 1 (second)', flags: ['-s', '--sleep'], default: 1}
]);
const args = argParser.parse(ns.args);
const serverPrefix = 'botnet_'
const maxRam = ns.getPurchasedServerMaxRam();
const minRamCost = ns.getPurchasedServerCost(args['ram']);
async function startScript(server) {
await copyWithDependencies(ns, args['script'], server);
const threads = args['cpu'] || maxThreads(ns, args['script'], server) || 1;
const pid = ns.exec(args['script'], server, threads, ...args['args']);
logger.log(`Starting "${args['script']}" with ${threads} thread${threads > 1 ? 's' : ''}`);
logger[pid == -1 ? 'warn' : 'log'](pid == -1 ? 'Done!' : 'Failed to start');
}
// Help
if(args['help'] || args['_error'].length)
return ns.tprint(argParser.help(args['help'] ? null : args['_error'][0], args['_command']));
// Main loop
// noinspection InfiniteLoopJS
while(true) {
servers = ns.getPurchasedServers();
const balance = ns.getServerMoneyAvailable('home');
// Purchase new server if we can afford it
if(servers.length < args['limit'] && balance - minRamCost > args['balance']) {
logger.log(`Buying server (${args['ram']} GB): ${toCurrency(minRamCost)}`);
ns.purchaseServer(`${serverPrefix}${servers.length}`, args['ram']);
// Run the script if requested
if(args['script']) await startScript(`${serverPrefix}${servers.length}`);
} else { // Check for upgrades
let upgrades = servers.map(server => {
// Calculate next RAM upgrades (must be a power of two: 2, 4, 8, 16, 32...)
let ram = Math.pow(2, Math.log2(ns.getServerMaxRam(server)) + 1);
if(ram > maxRam) ram = null;
return {
server,
ram,
cost: ram ? ns.getPurchasedServerCost(ram) : null
}
});
upgrades = upgrades.sort((a, b) => { // Sort by price
if(a.cost < b.cost) return 1;
if(a.cost < b.cost) return -1;
return 0;
});
// Do the cheapest upgrade if we can afford it
const upgrade = upgrades[0];
if(upgrade && !!upgrade.ram && balance - upgrade.cost > args['balance']) {
logger.log(`Upgrading ${upgrade.server}: ${upgrade.ram} GB / ${toCurrency(upgrade.cost)}`);
ns.killall(upgrade.server);
ns.deleteServer(upgrade.server);
ns.purchaseServer(upgrade.server, upgrade.ram);
// Run the script if requested
if(args['script']) await startScript(upgrade.server);
}
}
await ns.sleep(args['sleep'] * 1000);
}
}

View File

@ -183,7 +183,7 @@ export async function main(ns) {
{name: 'no-banner', desc: 'Hide the banner (Used internally)', flags: ['--no-banner'], default: false}
]);
const args = argParser.parse(ns.args || []);
const src = 'https://raw.githubusercontent.com/PointyTrident/Bitburner/develop/scripts/';
const src = 'https://gitlab.zakscode.com/ztimson/BitBurner/-/raw/develop/scripts/';
const dest = '/scripts/';
const fileList = [
'lib/arg-parser.js',