mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2026-04-16 14:28:36 +02:00
Compare commits
412 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
faf8389bef | ||
|
|
50919a88cd | ||
|
|
4860d6dc83 | ||
|
|
c59a267437 | ||
|
|
f9fd7a48f8 | ||
|
|
07b12ca6fb | ||
|
|
707a68dae9 | ||
|
|
1f46d69430 | ||
|
|
f2fa7a3c2d | ||
|
|
100ac2db95 | ||
|
|
338953fa1a | ||
|
|
de8e5ef441 | ||
|
|
c06087c634 | ||
|
|
8587625bd6 | ||
|
|
c5fb744a39 | ||
|
|
d7cd5b0d96 | ||
|
|
c445df4168 | ||
|
|
f8cba0ddc8 | ||
|
|
e3a181faf2 | ||
|
|
f65e546c32 | ||
|
|
772317a4f1 | ||
|
|
225de0faf6 | ||
|
|
0dbb067eae | ||
|
|
0d02ce6308 | ||
|
|
042189b187 | ||
|
|
52ca4c177a | ||
|
|
b38e411cd0 | ||
|
|
c9d40ccf95 | ||
|
|
438ae51fcd | ||
|
|
2747bf4439 | ||
|
|
dd720897e8 | ||
|
|
449df63dd8 | ||
|
|
f0161367af | ||
|
|
ac0bcbca8e | ||
|
|
914b06ec88 | ||
|
|
d5561abd46 | ||
|
|
53e3547d87 | ||
|
|
501cabfdc5 | ||
|
|
fff1de63d3 | ||
|
|
23b21e63a0 | ||
|
|
88db255f29 | ||
|
|
dfae337d26 | ||
|
|
7655b91e2a | ||
|
|
0368456d1e | ||
|
|
8191716562 | ||
|
|
3ceed8cf24 | ||
|
|
69ed320b93 | ||
|
|
8e0b5e3ecd | ||
|
|
ea3a1e5a2a | ||
|
|
1372c28a1b | ||
|
|
b123d191c0 | ||
|
|
82c963c04e | ||
|
|
df37f884ed | ||
|
|
dfabc0ac11 | ||
|
|
6c3618cb65 | ||
|
|
6d8df6744e | ||
|
|
bdef14b029 | ||
|
|
38923af436 | ||
|
|
057a229759 | ||
|
|
5c57bd43f6 | ||
|
|
8c851b577a | ||
|
|
3ac26594db | ||
|
|
409fa29b65 | ||
|
|
74ee7f371d | ||
|
|
62c19c9078 | ||
|
|
f1592a77fb | ||
|
|
f8607ce73e | ||
|
|
d0214c1fed | ||
|
|
4fb1dbf2e3 | ||
|
|
1e0e9f7bd7 | ||
|
|
1819e5a98a | ||
|
|
a2d75ae10c | ||
|
|
cd9fad06d0 | ||
|
|
d4eab92ed0 | ||
|
|
93c833a211 | ||
|
|
29aca108fb | ||
|
|
01cb0cca81 | ||
|
|
a1ec54ff90 | ||
|
|
52c82f026c | ||
|
|
b80cc31cb0 | ||
|
|
a6be7ecc3e | ||
|
|
1a07399312 | ||
|
|
8cfb355ca2 | ||
|
|
c5248fabb3 | ||
|
|
d53b87b8ce | ||
|
|
ca51e2144f | ||
|
|
c8667b5194 | ||
|
|
4486d7d454 | ||
|
|
7f812f56d9 | ||
|
|
4810a9004d | ||
|
|
b9b4ee23fe | ||
|
|
dd4b548917 | ||
|
|
5aa08f4123 | ||
|
|
8428264f05 | ||
|
|
4096ce4a9d | ||
|
|
1dcde649be | ||
|
|
2e0242ccbf | ||
|
|
59d8e1f979 | ||
|
|
8707dc7079 | ||
|
|
e3e1770439 | ||
|
|
c6ec27781b | ||
|
|
50f41e79e6 | ||
|
|
2637653d29 | ||
|
|
2b7464ebb7 | ||
|
|
b402cc7f6e | ||
|
|
2189c5b663 | ||
|
|
f3aed87fa4 | ||
|
|
31ed5d8f64 | ||
|
|
38366e45db | ||
|
|
351d4151bb | ||
|
|
bc0791840f | ||
|
|
bf1a2b56ba | ||
|
|
8f3da16ecf | ||
|
|
b578e09986 | ||
|
|
d823b5f28f | ||
|
|
7a0fdb9ce9 | ||
|
|
1b41e3326e | ||
|
|
72d9770a8e | ||
|
|
5c5cc9708d | ||
|
|
636fc7cda0 | ||
|
|
a098289856 | ||
|
|
383e56e9c8 | ||
|
|
91243f4742 | ||
|
|
04f2cfe522 | ||
|
|
0fc95e6215 | ||
|
|
9673b6f31d | ||
|
|
3c3f482e7b | ||
|
|
5d7d72a3e2 | ||
|
|
cc4f07d037 | ||
|
|
6eb8b2adf9 | ||
|
|
aaf1ad4ae5 | ||
|
|
ab5a2a8297 | ||
|
|
f98968f8b2 | ||
|
|
1b7a0224c5 | ||
|
|
26ab62eea6 | ||
|
|
9f9ce40ef0 | ||
|
|
39e6c5ca35 | ||
|
|
39c7a7781a | ||
|
|
f674d2d253 | ||
|
|
b27bb36a95 | ||
|
|
329221a974 | ||
|
|
952ea89777 | ||
|
|
5aff5fc944 | ||
|
|
d181ac4104 | ||
|
|
e583b46b16 | ||
|
|
8b42703f95 | ||
|
|
91d9549999 | ||
|
|
a29ffead78 | ||
|
|
dd3ab9ca48 | ||
|
|
c7657e5ec8 | ||
|
|
0842aba6cf | ||
|
|
8b33f72703 | ||
|
|
e9fd5f46eb | ||
|
|
8aae2c9b7f | ||
|
|
33e4e31099 | ||
|
|
b13f146bc3 | ||
|
|
90ca9407d5 | ||
|
|
7c846abb65 | ||
|
|
58dd450aca | ||
|
|
e3a9f9edab | ||
|
|
5607561c50 | ||
|
|
169d3e6c77 | ||
|
|
1087db9f33 | ||
|
|
6a9f6c05ec | ||
|
|
a4eddb4691 | ||
|
|
73adc71965 | ||
|
|
eb137455f5 | ||
|
|
a16cb745c5 | ||
|
|
3dd818cb7b | ||
|
|
23683d3482 | ||
|
|
3b8bdb7449 | ||
|
|
072653674e | ||
|
|
07b00bc377 | ||
|
|
f28ddd3b3f | ||
|
|
fd93c6d338 | ||
|
|
8f77f720e6 | ||
|
|
d99b03d12e | ||
|
|
2d949c076b | ||
|
|
13e68ba48e | ||
|
|
deb6d6cc0a | ||
|
|
3eedd9df88 | ||
|
|
ed86577d6c | ||
|
|
16c51e8e8e | ||
|
|
87d6c18254 | ||
|
|
12ba68a375 | ||
|
|
4861ac4153 | ||
|
|
b33af9df20 | ||
|
|
fcb876695d | ||
|
|
0bddb7d349 | ||
|
|
6458440193 | ||
|
|
ea03889082 | ||
|
|
693c6480a0 | ||
|
|
c056ef2854 | ||
|
|
eee72aa8d2 | ||
|
|
e0aaa383a4 | ||
|
|
7805b72457 | ||
|
|
88151efa61 | ||
|
|
795f8b4d2b | ||
|
|
bfdfee2a68 | ||
|
|
d2d6c33fc8 | ||
|
|
dce7217fc5 | ||
|
|
6363c704db | ||
|
|
9ea66e8743 | ||
|
|
7c599f2005 | ||
|
|
fba2265cce | ||
|
|
9ce8bdd29b | ||
|
|
35cfa9492e | ||
|
|
ed4d4d091c | ||
|
|
a97d2a93cb | ||
|
|
dbf8c788e0 | ||
|
|
76d67fdba5 | ||
|
|
f2141dd83d | ||
|
|
21ac94dbb3 | ||
|
|
06ec11a107 | ||
|
|
c2e5c9f371 | ||
|
|
7260d5fe35 | ||
|
|
366bffad85 | ||
|
|
1c7b0ab9a3 | ||
|
|
ce0fb7a383 | ||
|
|
91ac40efd0 | ||
|
|
e83c38b5fb | ||
|
|
50a85b61e2 | ||
|
|
64dea97e3c | ||
|
|
d6c1f3bfca | ||
|
|
6b59a58ea3 | ||
|
|
17b11f107f | ||
|
|
7baacf4e1b | ||
|
|
7f3f5c7648 | ||
|
|
f2bdf00aba | ||
|
|
e7e1e82394 | ||
|
|
ea0be338e1 | ||
|
|
b2b682fa04 | ||
|
|
41593e0dce | ||
|
|
79eb2f7e0b | ||
|
|
5021013cb7 | ||
|
|
c1c7131545 | ||
|
|
81e3f2afd1 | ||
|
|
f01b12a56a | ||
|
|
26106fa71d | ||
|
|
4be5e45740 | ||
|
|
94d695bb12 | ||
|
|
1830287a6e | ||
|
|
7a9e8936ee | ||
|
|
4183ed6f2b | ||
|
|
ede6be3d0d | ||
|
|
2d269c7a4e | ||
|
|
d873f7279b | ||
|
|
dbe36fd6b7 | ||
|
|
f2ccc63b2d | ||
|
|
1427993a25 | ||
|
|
0b71a83cfe | ||
|
|
bd375851a4 | ||
|
|
8ccb128e6f | ||
|
|
a6aebd4a29 | ||
|
|
56e540802b | ||
|
|
99f1e67224 | ||
|
|
bb2f8e883c | ||
|
|
9a1437559a | ||
|
|
d30edc7f59 | ||
|
|
009bae5870 | ||
|
|
b57ac45698 | ||
|
|
41a7109baa | ||
|
|
65d0877edc | ||
|
|
ddd0eaaf5c | ||
|
|
63891351be | ||
|
|
60749eefa7 | ||
|
|
ee177393fa | ||
|
|
4ec021c8f0 | ||
|
|
e9886cc6bc | ||
|
|
5dc9ac040a | ||
|
|
25f78f2b30 | ||
|
|
df265df9ce | ||
|
|
388a3f56c3 | ||
|
|
3fd904ff87 | ||
|
|
6641ca9c73 | ||
|
|
517066a710 | ||
|
|
d372166c8b | ||
|
|
00b3cb61f4 | ||
|
|
8be201cd93 | ||
|
|
ab0ed5d6a4 | ||
|
|
87bf23b6f4 | ||
|
|
afdac4e9cc | ||
|
|
e60996b86c | ||
|
|
08a4a1649f | ||
|
|
3df0fd3945 | ||
|
|
14532cd0a8 | ||
|
|
f72d4b89d4 | ||
|
|
53ce11c33a | ||
|
|
302af48be4 | ||
|
|
6d90025370 | ||
|
|
e5c4c8f64b | ||
|
|
9c19ddf6a7 | ||
|
|
cbfdfa5753 | ||
|
|
3120d97cfa | ||
|
|
6dc7dc42c5 | ||
|
|
3255768259 | ||
|
|
7215e73f41 | ||
|
|
e4345ebf68 | ||
|
|
2267845e2d | ||
|
|
b95261d905 | ||
|
|
6ec7fcb9fa | ||
|
|
82f6bbee13 | ||
|
|
565e7677f8 | ||
|
|
d1abe27484 | ||
|
|
7710ae5564 | ||
|
|
e521415273 | ||
|
|
61dde4cfac | ||
|
|
fcbf8a3824 | ||
|
|
f678574a6c | ||
|
|
8b355c365e | ||
|
|
2bbb767575 | ||
|
|
06acccdfe1 | ||
|
|
3b99da8474 | ||
|
|
92e8b42d18 | ||
|
|
d1696148c4 | ||
|
|
890b1df593 | ||
|
|
3ed5aa8045 | ||
|
|
2f9eb324b4 | ||
|
|
8c2b969026 | ||
|
|
29f1bed823 | ||
|
|
05ed3f5461 | ||
|
|
69fda94808 | ||
|
|
a9cf635a84 | ||
|
|
efc3992c78 | ||
|
|
76890ad1b9 | ||
|
|
3a21beb708 | ||
|
|
a76f67ade5 | ||
|
|
24f0c9e65d | ||
|
|
e6b84a73b2 | ||
|
|
b6df183953 | ||
|
|
f5f206561c | ||
|
|
1ea8c62d4f | ||
|
|
bc7f94ddda | ||
|
|
1dcc17c4fb | ||
|
|
6d79561859 | ||
|
|
b8b3897e64 | ||
|
|
b2add6c26b | ||
|
|
24c7fb2b92 | ||
|
|
1f6954b393 | ||
|
|
790ffeb8a1 | ||
|
|
555216a39b | ||
|
|
aad4024e0f | ||
|
|
db64d9869c | ||
|
|
eec9fbf997 | ||
|
|
8ba5199e54 | ||
|
|
160682f25a | ||
|
|
ecc650576e | ||
|
|
b3f9380ebd | ||
|
|
6fb5565b08 | ||
|
|
cdd85c09e1 | ||
|
|
fb5d374279 | ||
|
|
c4bd6d8e11 | ||
|
|
88666ec3fa | ||
|
|
c080f367b8 | ||
|
|
c38992be8d | ||
|
|
9346979e2b | ||
|
|
9e9a1ca882 | ||
|
|
a8f764bb8c | ||
|
|
dfdb940aa6 | ||
|
|
154f467935 | ||
|
|
7e474da3fe | ||
|
|
12114f0146 | ||
|
|
246e088365 | ||
|
|
638e0e8a13 | ||
|
|
d86986555c | ||
|
|
1d046d7d87 | ||
|
|
b326bd26bc | ||
|
|
3cdb73be6c | ||
|
|
4c88ab7794 | ||
|
|
30af70c4ab | ||
|
|
63c5387cfe | ||
|
|
6b0c4471a6 | ||
|
|
beaa60c967 | ||
|
|
aa7cf7469e | ||
|
|
fa1dd4d0cf | ||
|
|
181b7f39e5 | ||
|
|
a48cd2f1b4 | ||
|
|
403ab167b5 | ||
|
|
043aaeab8a | ||
|
|
cf11def6b9 | ||
|
|
ff4bcb26f4 | ||
|
|
1e9cf015e9 | ||
|
|
326cd5afa0 | ||
|
|
ff8cd8b3e2 | ||
|
|
01a6dd7aab | ||
|
|
c2b58ffcce | ||
|
|
f42bc288a6 | ||
|
|
d6cbca94bd | ||
|
|
d169d2af4c | ||
|
|
ac74d6a46b | ||
|
|
41592a199a | ||
|
|
7764afaf31 | ||
|
|
73bbf4d454 | ||
|
|
ced4ac2502 | ||
|
|
6e7ca6a9b5 | ||
|
|
3b13db1e33 | ||
|
|
cd8da81c97 | ||
|
|
b222b1ecbf | ||
|
|
b990e0e71c | ||
|
|
154936c1c5 | ||
|
|
5ef51d521b | ||
|
|
db6452ee3c | ||
|
|
89dffa6dfc | ||
|
|
ffb390fe7d | ||
|
|
83eb4afdf0 | ||
|
|
bc0ab1077c | ||
|
|
018dc7c579 | ||
|
|
ef5fbb7e49 | ||
|
|
ca50123d1a | ||
|
|
6b7a468688 | ||
|
|
9f14c38396 | ||
|
|
724914b85c |
@@ -1,7 +1,27 @@
|
||||
node_modules/
|
||||
doc/build/
|
||||
dist/
|
||||
tests/*.bundle.*
|
||||
input/
|
||||
|
||||
.dist
|
||||
.tmp
|
||||
.package
|
||||
|
||||
assets/
|
||||
css/
|
||||
.cypress/
|
||||
cypress/
|
||||
doc/
|
||||
markdown/
|
||||
netscript_tests/
|
||||
scripts/
|
||||
|
||||
electron/lib
|
||||
electron/greenworks.js
|
||||
src/ThirdParty/*
|
||||
src/JSInterpreter.js
|
||||
main.bundle.js
|
||||
|
||||
test/*.bundle.*
|
||||
editor.main.js
|
||||
main.bundle.js
|
||||
webpack.config.js
|
||||
webpack.config-test.js
|
||||
|
||||
55
.github/workflows/ci.yml
vendored
Normal file
55
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
# Triggers the workflow on push or pull request events but only for the dev branch
|
||||
push:
|
||||
branches: [ dev ]
|
||||
pull_request:
|
||||
branches: [ dev ]
|
||||
|
||||
# Allows you to run this workflow manually from the Actions tab
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js 16.13.1
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 16.13.1
|
||||
cache: 'npm'
|
||||
- name: Install npm dependencies
|
||||
run: npm ci
|
||||
- name: Build the production app
|
||||
run: npm run build
|
||||
lint:
|
||||
name: Lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js 16.13.1
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 16.13.1
|
||||
cache: 'npm'
|
||||
- name: Install npm dependencies
|
||||
run: npm ci
|
||||
- name: Run linter
|
||||
run: npm run lint:report
|
||||
test:
|
||||
name: Test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js 16.13.1
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 16.13.1
|
||||
cache: 'npm'
|
||||
- name: Install npm dependencies
|
||||
run: npm ci
|
||||
- name: Run linter
|
||||
run: npm run test
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,6 +4,7 @@ Changelog.txt
|
||||
Netburner.txt
|
||||
/doc/build
|
||||
/node_modules
|
||||
/electron/node_modules
|
||||
/dist/*.map
|
||||
/test/*.map
|
||||
/test/*.bundle.*
|
||||
|
||||
@@ -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
|
||||
@@ -84,7 +84,9 @@ changes are okay to contribute:
|
||||
- Changes that directly affect the game's balance
|
||||
- New gameplay mechanics
|
||||
|
||||
### How to setup fork properly
|
||||
---
|
||||
|
||||
## How to setup fork properly
|
||||
|
||||
Fork and clone the repo
|
||||
|
||||
@@ -106,7 +108,15 @@ Fork and clone the repo
|
||||
# Makes sure you always start from `danielyxie/dev` to avoid merge conflicts.
|
||||
```
|
||||
|
||||
### Running locally.
|
||||
## Development Workflow Best Practices
|
||||
|
||||
- Work in a new branch forked from the `dev` branch to isolate your new code
|
||||
- Keep code-changes on a branch as small as possible. This makes it easier for code review. Each branch should be its own independent feature.
|
||||
- Regularly rebase your branch against `dev` to make sure you have the latest updates pulled.
|
||||
- When merging, always merge your branch into `dev`. When releasing a new update, then merge `dev` into `master`
|
||||
|
||||
|
||||
## Running locally.
|
||||
|
||||
Install
|
||||
|
||||
@@ -118,10 +128,32 @@ Inside the root of the repo run
|
||||
`npm install` to install all the dependencies
|
||||
`npm run start:dev` to launch the game in dev mode.
|
||||
|
||||
After that you can open any browser and naviguate to `localhost:8000` and play the game.
|
||||
After that you can open any browser and navigate to `localhost:8000` and play the game.
|
||||
Saving a file will reload the game automatically.
|
||||
|
||||
#### Submitting a Pull Request
|
||||
|
||||
### How to build the electron app
|
||||
|
||||
Tested on Node v16.13.1 (LTS) on Windows
|
||||
These steps only work in a bash-like environment, like MinGW for Windows.
|
||||
|
||||
```sh
|
||||
# Install the main game dependencies & build the app in debug mode
|
||||
npm install
|
||||
npm run build:dev
|
||||
|
||||
# Use electron-packager to build the app to the .build/ folder
|
||||
npm run electron
|
||||
|
||||
# When launching the .exe directly, you'll need the steam_appid.txt file in the root
|
||||
# If not using windows, change this line accordingly
|
||||
cp .build/bitburner-win32-x64/resources/app/steam_appid.txt .build/bitburner-win32-x64/steam_appid.txt
|
||||
|
||||
# And run the game...
|
||||
.build/bitburner-win32-x64/bitburner.exe
|
||||
```
|
||||
|
||||
### Submitting a Pull Request
|
||||
|
||||
When submitting a pull request with your code contributions, please abide by
|
||||
the following rules:
|
||||
@@ -146,9 +178,14 @@ the following rules:
|
||||
|
||||
## As a Documentor
|
||||
|
||||
To contribute to and view your changes to the BitBurner documentation, you will
|
||||
To contribute to and view your changes to the BitBurner documentation on [Read The
|
||||
Docs](http://bitburner.readthedocs.io/), you will
|
||||
need to have Python installed, along with [Sphinx](http://www.sphinx-doc.org).
|
||||
|
||||
To make change to the [in-game documentation](./markdown/bitburner.md), you will need to modify the [TypeScript definitions](./src/ScriptEditor/NetscriptDefinitions.d.ts), not the markdown files.
|
||||
|
||||
We are using [API Extractor](https://api-extractor.com/pages/tsdoc/doc_comment_syntax/) (tsdoc hints) to generate the markdown doc. Make your changes to the TypeScript definitions and then run `npm run doc`.
|
||||
|
||||
Before submitting your code for a pull request, please try to follow these
|
||||
rules:
|
||||
|
||||
@@ -160,3 +197,14 @@ rules:
|
||||
_danielyxie/bitburner_ and the base is _dev_.
|
||||
- Do not check in any generated files under `doc\`. The documentation is built
|
||||
automatically by ReadTheDocs.
|
||||
|
||||
## Deploying a new version
|
||||
|
||||
Update the following
|
||||
|
||||
- `src/Constants.ts` `Version` and `LatestUpdate`
|
||||
- `package.json` `version`
|
||||
- `doc/source/conf.py` `version` and `release`
|
||||
- `doc/source/changelog.rst`
|
||||
- post to discord
|
||||
- post to reddit.com/r/Bitburner
|
||||
|
||||
87
FAQ.md
Normal file
87
FAQ.md
Normal file
@@ -0,0 +1,87 @@
|
||||
# Frequently Asked Questions
|
||||
|
||||
## Can I donate to the project?
|
||||
|
||||
No, the project does not take donation.
|
||||
|
||||
If you still want to donate, go donate blood to your local blood bank or donate to the [Electronic Frontier Foundation](https://www.eff.org/) or [Médecins Sans Frontières](https://www.msf.org/)
|
||||
|
||||
---
|
||||
|
||||
## I need help / Where can I learn?
|
||||
|
||||
The best way to get help is to join the [official discord server](https://discord.gg/TFc3hKD). People of all skill levels will be able to give you hints and tips.
|
||||
|
||||
---
|
||||
|
||||
## Can I play the same save on browser & steam?
|
||||
|
||||
Yes, just export the save file from the options menu & import it in the other platform.
|
||||
|
||||
---
|
||||
|
||||
## Game is stuck after running scripts!
|
||||
|
||||
You may have created an infinite loop with no sleep. You'll have to restart the game by killing all scripts.
|
||||
* On Browser: Stick `?noScript` at the end of the URL
|
||||
* On Steam:
|
||||
* In the menu, "Reloads" -> "Reload & Kill All Scripts".
|
||||
* If this does not work, when launching the game, use the kill all script options.
|
||||
|
||||
---
|
||||
|
||||
## Steam: Where is the save game located?
|
||||
|
||||
To maintain compatibility with the web browser version, the save game is not stored as a file on your filesystem. It lives inside the localStorage of the WebKit instance. You may export the save (and should backup it!) in the option menu.
|
||||
|
||||
---
|
||||
|
||||
## Steam: Game won't stop / Game is shown as "Running"
|
||||
|
||||
Due to a limitation with the way Steam tracks the game, if you launch an external link (such as documentation), Steam may keep tracking the game as "Running" even after it is closed. You should simply have to close your web browser to fix this.
|
||||
|
||||
---
|
||||
|
||||
## Steam: How do I get to the game files? <a name="game-files"></a>
|
||||
|
||||
You can navigate to the game files by right-clicking the game in your library and then go into "Manage" -> "Browse Local Files". The game can be launched directly from that location, if you're having issues with Steam.
|
||||
|
||||
---
|
||||
|
||||
## Steam: Game won't launch
|
||||
|
||||
### **On Windows**
|
||||
If the game is installed on a network drive, it will fail to start due to a [limitation in Chromium](https://github.com/electron/electron/issues/27356).
|
||||
|
||||
If you cannot move the game to another drive, you'll have to add the `--no-sandbox` launch option. In your Steam Library, Right click the game and hit "Properties". You'll see the launch option section in the "General" window.
|
||||
|
||||
### **On Linux**
|
||||
The game is built natively, do not use Proton unless native does not work.
|
||||
|
||||
When launching the game, you will be prompted with three options. If the standard launch does not work, you may attempt the `--disable-seccomp-filter-sandbox` or `--no-sandbox` launch option. If this still does not work, the game should be able to start by launching it directly or through the terminal. See [How do I get to the game files?](#game-files).
|
||||
|
||||
---
|
||||
|
||||
## Steam: File locations
|
||||
|
||||
### Logs (using [electron-log](https://github.com/megahertz/electron-log#readme))
|
||||
|
||||
You may want access the logs to get information about crashes or such.
|
||||
|
||||
* on Linux: `~/.config/bitburner/logs/main.log`
|
||||
* on macOS: `~/Library/Logs/bitburner/main.log`
|
||||
* on Windows: `%USERPROFILE%\AppData\Roaming\bitburner\logs\main.log`
|
||||
|
||||
### Config (using [electron-store](https://github.com/sindresorhus/electron-store#readme))
|
||||
|
||||
Configuration file will be written to disk in the application data directory.
|
||||
|
||||
* on Linux: `~/.config/bitburner/config.json`
|
||||
* on macOS: `~/Library/Application\ Support/bitburner/config.json`
|
||||
* on Windows: `%USERPROFILE%\AppData\Roaming\bitburner\config.json`
|
||||
|
||||
---
|
||||
|
||||
## Steam: What is the API Server?
|
||||
|
||||
The API Server allows the official [Visual Studio Code Extension](https://github.com/bitburner-official/bitburner-vscode) to push script file from VSCode to your in-game home.
|
||||
11
README.md
11
README.md
@@ -1,16 +1,19 @@
|
||||
# Bitburner
|
||||
|
||||
[](https://github.com/danielyxie/bitburner/actions/workflows/ci.yml)
|
||||
|
||||
Bitburner is a programming-based [incremental game](https://en.wikipedia.org/wiki/Incremental_game)
|
||||
that revolves around hacking and cyberpunk themes.
|
||||
The game can be played at https://danielyxie.github.io/bitburner.
|
||||
The game can be played at https://danielyxie.github.io/bitburner or installed through [Steam](https://store.steampowered.com/app/1812820/Bitburner/).
|
||||
|
||||
See the [frequently asked questions](./FAQ.md) for more information . To discuss the game or get help, join the [official discord server](https://discord.gg/TFc3hKD)
|
||||
|
||||
# Documentation
|
||||
|
||||
The game's official documentation can be found on [Read The
|
||||
Docs](http://bitburner.readthedocs.io/). Please note that this is still a
|
||||
work-in-progress.
|
||||
Docs](http://bitburner.readthedocs.io/). Please note that this is still a work-in-progress.
|
||||
|
||||
The documentation is created using [Sphinx](http://www.sphinx-doc.org).
|
||||
The [in-game documentation](./markdown/bitburner.md) is generated from the [TypeScript definitions](./src/ScriptEditor/NetscriptDefinitions.d.ts).
|
||||
|
||||
Anyone is welcome to contribute to the documentation by editing the [source
|
||||
files](/doc/source) and then making a pull request with your contributions.
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
## Deploying a new version
|
||||
|
||||
Update the following
|
||||
|
||||
- `src/Constants.ts` `Version` and `LatestUpdate`
|
||||
- `package.json` `version`
|
||||
- `doc/source/conf.py` `version` and `release`
|
||||
- `doc/source/changelog.rst`
|
||||
- post to discord
|
||||
- post to reddit.com/r/Bitburner
|
||||
|
||||
## Deploying `dev` to the Beta Branch
|
||||
|
||||
TODO
|
||||
|
||||
## Development Workflow Best Practices
|
||||
|
||||
- Work in a new branch forked from the `dev` branch to isolate your new code
|
||||
- Keep code-changes on a branch as small as possible. This makes it easier for code review. Each branch should be its own independent feature.
|
||||
- Regularly rebase your branch against `dev` to make sure you have the latest updates pulled.
|
||||
- When merging, always merge your branch into `dev`. When releasing a new update, then merge `dev` into `master`
|
||||
13
dist/bitburner.d.ts
vendored
13
dist/bitburner.d.ts
vendored
@@ -2720,7 +2720,7 @@ export declare interface NS extends Singularity {
|
||||
* @param args - Additional arguments to pass into the new script that is being run. Note that if any arguments are being passed into the new script, then the second argument numThreads must be filled in with a value.
|
||||
* @returns Returns the PID of a successfully started script, and 0 otherwise.
|
||||
*/
|
||||
run(script: string, numThreads?: number, ...args: string[]): number;
|
||||
run(script: string, numThreads?: number, ...args: Array<string | number | boolean>): number;
|
||||
|
||||
/**
|
||||
* Start another script on any server.
|
||||
@@ -2760,7 +2760,7 @@ export declare interface NS extends Singularity {
|
||||
* @param args - Additional arguments to pass into the new script that is being run. Note that if any arguments are being passed into the new script, then the third argument numThreads must be filled in with a value.
|
||||
* @returns Returns the PID of a successfully started script, and 0 otherwise.
|
||||
*/
|
||||
exec(script: string, host: string, numThreads?: number, ...args: string[]): number;
|
||||
exec(script: string, host: string, numThreads?: number, ...args: Array<string | number | boolean>): number;
|
||||
|
||||
/**
|
||||
* Terminate current script and start another in 10s.
|
||||
@@ -3498,7 +3498,7 @@ export declare interface NS extends Singularity {
|
||||
* Returns 0 if the script does not exist.
|
||||
*
|
||||
* @param script - Filename of script. This is case-sensitive.
|
||||
* @param host - Host of target server the script is located on. This is optional, If it is not specified then the function will se the current server as the target server.
|
||||
* @param host - Host of target server the script is located on. This is optional, If it is not specified then the function will use the current server as the target server.
|
||||
* @returns Amount of RAM required to run the specified script on the target server, and 0 if the script does not exist.
|
||||
*/
|
||||
getScriptRam(script: string, host?: string): number;
|
||||
@@ -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;
|
||||
|
||||
@@ -3678,8 +3678,9 @@ export declare interface NS extends Singularity {
|
||||
* Queue a toast (bottom-right notification).
|
||||
* @param msg - Message in the toast.
|
||||
* @param variant - Type of toast, must be one of success, info, warning, error. Defaults to success.
|
||||
* @param duration - Duration of toast in ms, defaults to 2000
|
||||
*/
|
||||
toast(msg: any, variant?: string): void;
|
||||
toast(msg: any, variant?: string, duration?: number): void;
|
||||
|
||||
/**
|
||||
* Download a file from the internet.
|
||||
|
||||
7
dist/ext/monaco-vim.js
vendored
Normal file
7
dist/ext/monaco-vim.js
vendored
Normal file
File diff suppressed because one or more lines are too long
74
dist/vendor.bundle.js
vendored
74
dist/vendor.bundle.js
vendored
File diff suppressed because one or more lines are too long
@@ -12,3 +12,4 @@ must be unlocked.
|
||||
Source-Files <advancedgameplay/sourcefiles>
|
||||
Intelligence <advancedgameplay/intelligence>
|
||||
Sleeves <advancedgameplay/sleeves>
|
||||
Hacking algorithms <advancedgameplay/hackingalgorithms>
|
||||
|
||||
BIN
doc/source/advancedgameplay/batch.png
Normal file
BIN
doc/source/advancedgameplay/batch.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 50 KiB |
126
doc/source/advancedgameplay/hackingalgorithms.rst
Normal file
126
doc/source/advancedgameplay/hackingalgorithms.rst
Normal file
@@ -0,0 +1,126 @@
|
||||
Hacking algorithms
|
||||
==================
|
||||
|
||||
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
|
||||
|
||||
Pros:
|
||||
|
||||
* Easy to implement
|
||||
* Does not require other scripts to work
|
||||
* Works at any stage of the game
|
||||
|
||||
Cons:
|
||||
|
||||
* Limits income generation
|
||||
* Extremely RAM inefficient
|
||||
* Utilizes script online time poorly
|
||||
* Risk of over hacking
|
||||
|
||||
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
|
||||
|
||||
loop forever {
|
||||
if security is not minimum {
|
||||
weaken(target)
|
||||
} else if money is not maximum {
|
||||
grow(target)
|
||||
} else {
|
||||
hack(target)
|
||||
}
|
||||
}
|
||||
|
||||
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. (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
|
||||
---------------
|
||||
**Difficulty**: Easy to Medium
|
||||
|
||||
Pros:
|
||||
|
||||
* Simple to understand
|
||||
* Works at any stage of the game
|
||||
* Maximize RAM usage
|
||||
|
||||
Cons:
|
||||
|
||||
* Requires a script that handles deployment
|
||||
|
||||
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
|
||||
|
||||
loop forever {
|
||||
hack(target) // or grow, or weaken
|
||||
}
|
||||
|
||||
Now we can take the total amount of threads available and split it and allocate, for example:
|
||||
|
||||
- 1 part to the hack scripts
|
||||
- 10 parts to the grow scripts
|
||||
- 2 parts to the weaken scripts
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
|
||||
Pros:
|
||||
|
||||
* Maximum potential income
|
||||
|
||||
Cons:
|
||||
|
||||
* Very difficult to implement without prior programming knowledge
|
||||
* Very difficult to make work on servers with less than 1TB of RAM
|
||||
|
||||
Batch algorithms utilize a master script that uses `exec()` many scripts which utilize a relevant hacking function in batches.
|
||||
|
||||
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
|
||||
|
||||
A few things need to be known before this algorithm can be implemented:
|
||||
|
||||
- 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 single batch consists of four actions:
|
||||
|
||||
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 above, and all of their effects be precalculated to optimize the ratios between them. This is the reason for the delay in the scripts.
|
||||
|
||||
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
|
||||
|
||||
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.
|
||||
@@ -18,7 +18,7 @@ Sleeve technology is unlocked in :ref:`BitNode-10 <gameplay_bitnodes>`.
|
||||
|
||||
Duplicate Sleeves
|
||||
^^^^^^^^^^^^^^^^^
|
||||
Duplicate Sleeves are MK-V Synthoids (synthetic androids) into which your consciuosness
|
||||
Duplicate Sleeves are MK-V Synthoids (synthetic androids) into which your consciousness
|
||||
has been copied. In other words, these Synthoids contain a perfect duplicate of your mind.
|
||||
|
||||
Duplicate Sleeves are essentially clones which you can use to perform work-type actions,
|
||||
|
||||
@@ -28,7 +28,7 @@ List of all Source-Files
|
||||
|| || * Increases the player's charisma and company salary multipliers by 8%/12%/14%. |
|
||||
+-------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
|| BitNode-4: The Singularity || * Let the player access and use Netscript Singularity Functions in other BitNodes. |
|
||||
|| || * Each level of this Source-File opens up more of the Singularity Functions to use. |
|
||||
|| || * Each level of this Source-File reduces the RAM cost of singularity functions. |
|
||||
+-------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
|| BitNode-5: Artificial Intelligence || * Unlocks :ref:`gameplay_intelligence`. |
|
||||
|| || * Unlocks :js:func:`getBitNodeMultipliers` and start with Formulas.exe. |
|
||||
|
||||
@@ -13,7 +13,8 @@ Server RAM
|
||||
Perhaps the most important property of a server to make note of is its RAM,
|
||||
which refers to how much memory is available on that machine. RAM is
|
||||
important because it is required to run Scripts. More RAM allows
|
||||
the user to run more powerful and complicated scripts.
|
||||
the user to run more powerful and complicated scripts as well as executing
|
||||
a script with :ref:`more threads <gameplay_scripts_multithreadingscripts>`.
|
||||
|
||||
The `free`, `scan-analyze`, and `analyze` Terminal commands
|
||||
can be used to check how much RAM a server has.
|
||||
|
||||
@@ -432,7 +432,10 @@ empty file will be created.
|
||||
ps
|
||||
^^
|
||||
|
||||
$ ps [-g, --grep pattern]
|
||||
|
||||
Prints all scripts that are currently running on the current server.
|
||||
The :code:`-g, --grep pattern` option will only output running scripts where the name matches the provided pattern.
|
||||
|
||||
rm
|
||||
^^
|
||||
|
||||
@@ -3,6 +3,93 @@
|
||||
Changelog
|
||||
=========
|
||||
|
||||
v1.3.0 - 2022-01-04 Cleaning up
|
||||
-------------------------------
|
||||
|
||||
** External IDE integration **
|
||||
|
||||
* The Steam version has a webserver that allows integration with external IDEs.
|
||||
A VSCode extension is available on the market place. (The documentation for the ext. isn't
|
||||
written yet)
|
||||
|
||||
** Source-Files **
|
||||
|
||||
* SF4 has been reworked.
|
||||
* New SF -1.
|
||||
|
||||
** UI **
|
||||
|
||||
* Fix some edge case with skill bat tooltips (@MartinFournier)
|
||||
* Made some background match theme color (@Kejikus)
|
||||
* Fix problem with script editor height not adjusting correctly (@billyvg)
|
||||
* Fix some formatting issues with Bladeburner (@MartinFournier, @nickofolas)
|
||||
* Fix some functions like 'alert' format messages better (@MageKing17)
|
||||
* Many community themes added.
|
||||
* New script editor theme (@Hedrauta, @Dexalt142)
|
||||
* Improvements to tail windows (@theit8514)
|
||||
* Training is more consise (@mikomyazaki)
|
||||
* Fix Investopedia not displaying properly (@JotaroS)
|
||||
* Remove alpha from theme editor (@MartinFournier)
|
||||
* Fix corporation tooltip not displaying properly (@MartinFournier)
|
||||
* Add tooltip on backdoored location names (@MartinFournier)
|
||||
* Allow toasts to be dismissed by clicking them (@nickofolas)
|
||||
* Darkweb item listing now shows what you own. (@hexnaught)
|
||||
|
||||
** Bug fix **
|
||||
|
||||
* Fix unit tests (@MartinFournier)
|
||||
* Fixed issue with 'cat' and 'read' not finding foldered files (@Nick-Colclasure)
|
||||
* Buying on the dark web will remove incomplete exe (@hexnaught)
|
||||
* Fix bug that would cause the game to crash trying to go to a job without a job (@hexnaught)
|
||||
* purchaseServer validation (@nickofolas)
|
||||
* Script Editor focuses code when changing tab (@MartinFournier)
|
||||
* Fix script editor for .txt files (@65-7a)
|
||||
* Fix 'buy' command not displaying correctly. (@hexnaught)
|
||||
* Fix hackAnalyzeThread returning NaN (@mikomyazaki)
|
||||
* Electron handles exceptions better (@MageKing17)
|
||||
* Electron will handle 'unresponsive' event and present the opportunity to reload the game with no scripts (@MartinFournier)
|
||||
* Fix 'cp' between folders (@theit8514)
|
||||
* Fix throwing null/undefined errors (@nickofolas)
|
||||
* Allow shortcuts to work when unfocused (@MageKing17)
|
||||
* Fix some dependency issue (@locriacyber)
|
||||
* Fix corporation state returning an object instead of a string (@antonvmironov)
|
||||
* Fix 'mv' overwriting files (@theit8514)
|
||||
* Fix joesguns not being influenced by hack/grow (@dou867, @MartinFournier)
|
||||
* Added warning when opening external links. (@MartinFournier)
|
||||
* Prevent applying for positions that aren't offered (@TheMas3212)
|
||||
* Import has validation (@MartinFournier)
|
||||
|
||||
** Misc. **
|
||||
|
||||
* Added vim mode to script editor (@billyvg)
|
||||
* Clean up script editor code (@Rez855)
|
||||
* 'cat' works on scripts (@65-7a)
|
||||
* Add wordWrap for Monaco (@MartinFournier)
|
||||
* Include map bundles in electron for easier debugging (@MartinFournier)
|
||||
* Fix importing very large files (@MartinFournier)
|
||||
* Cache program blob, reducing ram usage of the game (@theit8514)
|
||||
* Dev menu can set server to $0 (@mikomyazaki)
|
||||
* 'backdoor' allows direct connect (@mikomyazaki)
|
||||
* Github workflow work (@MartinFournier)
|
||||
* workForFaction / workForCompany have a new parameter (@theit8514)
|
||||
* Alias accept single quotes (@sporkwitch, @FaintSpeaker)
|
||||
* Add grep options to 'ps' (@maxtimum)
|
||||
* Added buy all option to 'buy' (@anthonydroberts)
|
||||
* Added more shortcuts to terminal input (@Frank-py)
|
||||
* Refactor some port code (@ErzengelLichtes)
|
||||
* Settings to control GiB vs GB (@ErzengelLichtes)
|
||||
* Add electron option to export save game (@MartinFournier)
|
||||
* Electron improvements (@MartinFournier)
|
||||
* Expose some notifications functions to electron (@MartinFournier)
|
||||
* Documentation (@MartinFournier, @cyn, @millennIumAMbiguity, @2PacIsAlive,
|
||||
@TheCoderJT, @hexnaught, @sschmidTU, @FOLLGAD, @Hedrauta, @Xynrati,
|
||||
@mikomyazaki, @Icehawk78, @aaronransley, @TheMas3212, @Hedrauta, @alkemann,
|
||||
@ReeseJones, @amclark42, @thadguidry, @jasonhaxstuff, @pan-kuleczka, @jhollowe,
|
||||
@ApatheticsAnonymous, @erplsf, @daanflore, @nickofolas, @Kebap, @smolgumball,
|
||||
@woody-lam-cwl)
|
||||
|
||||
|
||||
|
||||
v1.1.0 - 2021-12-18 You guys are awesome (community because they're god damn awesome)
|
||||
-------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ master_doc = 'index'
|
||||
# General information about the project.
|
||||
project = 'Bitburner'
|
||||
author = 'Bitburner'
|
||||
copyright = '2018, {0}'.format(author)
|
||||
copyright = '2016, {0}'.format(author)
|
||||
documentation_title = '{0} Documentation'.format(project)
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
@@ -64,9 +64,9 @@ documentation_title = '{0} Documentation'.format(project)
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '1.2'
|
||||
version = '1.3'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '1.2.0'
|
||||
release = '1.3.0'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
||||
@@ -520,10 +520,12 @@ will appear that simply says :code:`Work`. Click this to start working.
|
||||
Working at :code:`Joe's Guns` earns $110 per second and also grants some experience
|
||||
for every stat except hacking.
|
||||
|
||||
Working for a company is completely passive. However, you will not be able to do anything
|
||||
else in the game while you work. You can cancel working at any time. You'll notice that
|
||||
cancelling your work early causes you to lose out on some reputation gains, but
|
||||
you shouldn't worry about this. Company reputation isn't important right now.
|
||||
Working for a company is completely passive. You can choose to focus on your work, do
|
||||
something else simultaneously, or switch between those two. While you focus on work,
|
||||
you will not be able to do anything else in the game. If you do something else meanwhile,
|
||||
you will not gain reputation at the same speed. You can cancel working at any time.
|
||||
You'll notice that cancelling your work early causes you to lose out on some reputation
|
||||
gains, but you shouldn't worry about this. Company reputation isn't important right now.
|
||||
|
||||
Once your hacking hits level 75, you can visit :code:`Carmichael Security` in the city
|
||||
and get a software job there. This job offers higher pay and also earns you
|
||||
@@ -720,9 +722,10 @@ navigation menu, and from there select |CyberSec|. In the middle of
|
||||
the page there should be a button for :code:`Hacking Contracts`.
|
||||
Click it to start earning reputation for the |CyberSec| faction (as well
|
||||
as some hacking experience). The higher your hacking level, the more reputation you
|
||||
will gain. Note that while you are working for a faction, you cannot interact with
|
||||
the rest of the game in any way. You can cancel your faction work at any time
|
||||
with no penalty.
|
||||
will gain. Note that while you are working for a faction, you can choose to not interact
|
||||
with the rest of the game in any way to gain reputation at full speed. You can also select to
|
||||
do something else simultaneously, gaining reputation a bit more slowly, until you focus again.
|
||||
You can cancel your faction work at any time with no penalty to your reputation gained so far.
|
||||
|
||||
Purchasing Upgrades and Augmentations
|
||||
-------------------------------------
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
Netscript Basic Functions
|
||||
=========================
|
||||
|
||||
This page contains the complete documentation for all functions that are available in Netscript.
|
||||
This page contains a subset of functions that are available in Bitburner.
|
||||
For the complete list see https://github.com/danielyxie/bitburner/tree/dev/markdown
|
||||
This includes information such as function signatures, what they do, and their return values.
|
||||
|
||||
.. toctree::
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
canPlace() Netscript Function
|
||||
=======================================
|
||||
|
||||
.. js:function:: canPlace(worldX, worldY, rotation, fragmentId)
|
||||
|
||||
:RAM cost: 0.5 GB
|
||||
:param int worldX: World X against which to align the top left of the fragment.
|
||||
:param int worldY: World Y against which to align the top left of the fragment.
|
||||
:param int rotation: A number from 0 to 3, the mount of 90 degree turn to take.
|
||||
:param int fragmentId: ID of the fragment to place.
|
||||
:returns: `true` if the fragment can be placed at that position. `false` otherwise.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: javascript
|
||||
canPlace(0, 4, 17); // returns true
|
||||
@@ -1,21 +0,0 @@
|
||||
charge() Netscript Function
|
||||
=======================================
|
||||
|
||||
.. js:function:: charge(worldX, worldY)
|
||||
|
||||
:RAM cost: 0.4 GB
|
||||
:param int worldX: World X of the fragment to charge.
|
||||
:param int worldY: World Y of the fragment to charge.
|
||||
|
||||
Charge a fragment, increasing it's power but also it's heat. The
|
||||
effectiveness of the charge depends on the amount of ram the running script
|
||||
consumes as well as the fragments current heat. This operation takes time to
|
||||
complete.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: javascript
|
||||
charge(0, 4); // Finishes 5 seconds later.
|
||||
.. warning::
|
||||
|
||||
Netscript JS users: This function is `async`
|
||||
@@ -1,13 +0,0 @@
|
||||
clear() Netscript Function
|
||||
=======================================
|
||||
|
||||
.. js:function:: clear()
|
||||
|
||||
:RAM cost: 0 GB
|
||||
|
||||
Completely clear Stanek's Gift.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: javascript
|
||||
clear(); // No more fragments.
|
||||
@@ -1,16 +0,0 @@
|
||||
deleteAt() Netscript Function
|
||||
=======================================
|
||||
|
||||
.. js:function:: deleteAt(worldX, worldY)
|
||||
|
||||
:RAM cost: 0.15 GB
|
||||
:param int worldX: World X coordinate of the fragment to delete.
|
||||
:param int worldY: World Y coordinate of the fragment to delete.
|
||||
:returns: `true` if the fragment was deleted. `false` otherwise.
|
||||
|
||||
Delete the fragment located at `[worldX, worldY]`.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: javascript
|
||||
deleteAt(0, 4); // returns true
|
||||
@@ -1,28 +0,0 @@
|
||||
fragmentAt() Netscript Function
|
||||
=======================================
|
||||
|
||||
.. js:function:: fragmentAt(worldX, worldY)
|
||||
|
||||
:RAM cost: 2 GB
|
||||
:param int worldX: World X coordinate of the fragment.
|
||||
:param int worldY: World Y coordinate of the fragment.
|
||||
:returns: The fragment located at `[worldX, worldY]` in Stanek's Gift, or null.
|
||||
|
||||
.. code-block:: typescript
|
||||
{
|
||||
// In world coordinates
|
||||
x: number;
|
||||
y: number;
|
||||
heat: number;
|
||||
charge: number;
|
||||
id: number;
|
||||
shape: boolean[][];
|
||||
type: string;
|
||||
magnitude: number;
|
||||
limit: number;
|
||||
}
|
||||
Example:
|
||||
|
||||
.. code-block:: javascript
|
||||
var fragment = fragmentAt(0, 4);
|
||||
print(fragment); // {'heat': 50, 'charge': 98}
|
||||
@@ -1,23 +0,0 @@
|
||||
fragmentDefinitions() Netscript Function
|
||||
=======================================
|
||||
|
||||
.. js:function:: fragmentDefinitions()
|
||||
|
||||
:RAM cost: 0 GB
|
||||
:returns: The list of all fragment that can be embedded in Stanek's Gift.
|
||||
|
||||
.. code-block:: typescript
|
||||
[
|
||||
{
|
||||
id: number;
|
||||
shape: boolean[][];
|
||||
type: string;
|
||||
magnitude: number;
|
||||
limit: number;
|
||||
}
|
||||
]
|
||||
Example:
|
||||
|
||||
.. code-block:: javascript
|
||||
var fragments = fragmentDefinitions();
|
||||
print(fragment); // prints all possible fragments
|
||||
@@ -1,16 +0,0 @@
|
||||
place() Netscript Function
|
||||
=======================================
|
||||
|
||||
.. js:function:: place(worldX, worldY, fragmentId)
|
||||
|
||||
:RAM cost: 5 GB
|
||||
:param int worldX: World X against which to align the top left of the fragment.
|
||||
:param int worldY: World Y against which to align the top left of the fragment.
|
||||
:param int rotation: A number from 0 to 3, the mount of 90 degree turn to take.
|
||||
:param int fragmentId: ID of the fragment to place.
|
||||
:returns: `true` if the fragment has been placed at that position. `false` otherwise.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: javascript
|
||||
place(0, 4, 17); // returns true
|
||||
@@ -1,26 +0,0 @@
|
||||
placedFragments() Netscript Function
|
||||
=======================================
|
||||
|
||||
.. js:function:: placedFragments()
|
||||
|
||||
:RAM cost: 5 GB
|
||||
:returns: The list of all fragment that are embedded in Stanek's Gift.
|
||||
|
||||
.. code-block:: typescript
|
||||
[
|
||||
{
|
||||
// In world coordinates
|
||||
x: number;
|
||||
y: number;
|
||||
charge: number;
|
||||
id: number;
|
||||
shape: boolean[][];
|
||||
type: string;
|
||||
power: number;
|
||||
limit: number;
|
||||
}
|
||||
]
|
||||
Example:
|
||||
|
||||
.. code-block:: javascript
|
||||
var myFragments = placedFragments();
|
||||
35
electron/achievements.js
Normal file
35
electron/achievements.js
Normal file
@@ -0,0 +1,35 @@
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const greenworks = require("./greenworks");
|
||||
|
||||
function enableAchievementsInterval(window) {
|
||||
// This is backward but the game fills in an array called `document.achievements` and we retrieve it from
|
||||
// here. Hey if it works it works.
|
||||
const steamAchievements = greenworks.getAchievementNames();
|
||||
const intervalID = setInterval(async () => {
|
||||
try {
|
||||
const playerAchievements = await window.webContents.executeJavaScript("document.achievements");
|
||||
for (const ach of playerAchievements) {
|
||||
if (!steamAchievements.includes(ach)) continue;
|
||||
greenworks.activateAchievement(ach, () => undefined);
|
||||
}
|
||||
} catch (error) {
|
||||
log.error(error);
|
||||
|
||||
// The interval probably did not get cleared after a window kill
|
||||
log.warn('Clearing achievements timer');
|
||||
clearInterval(intervalID);
|
||||
return;
|
||||
}
|
||||
}, 1000);
|
||||
window.achievementsIntervalID = intervalID;
|
||||
}
|
||||
|
||||
function disableAchievementsInterval(window) {
|
||||
if (window.achievementsIntervalID) {
|
||||
clearInterval(window.achievementsIntervalID);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
enableAchievementsInterval, disableAchievementsInterval
|
||||
}
|
||||
147
electron/api-server.js
Normal file
147
electron/api-server.js
Normal file
@@ -0,0 +1,147 @@
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const http = require("http");
|
||||
const crypto = require("crypto");
|
||||
const log = require("electron-log");
|
||||
const Config = require("electron-config");
|
||||
const config = new Config();
|
||||
|
||||
let server;
|
||||
let window;
|
||||
|
||||
async function initialize(win) {
|
||||
window = win;
|
||||
server = http.createServer(async function (req, res) {
|
||||
let body = "";
|
||||
|
||||
req.on("data", (chunk) => {
|
||||
body += chunk.toString(); // convert Buffer to string
|
||||
});
|
||||
req.on("end", () => {
|
||||
const providedToken = req.headers?.authorization?.replace('Bearer ', '') ?? '';
|
||||
const isValid = providedToken === getAuthenticationToken();
|
||||
if (isValid) {
|
||||
log.debug('Valid authentication token');
|
||||
} else {
|
||||
log.log('Invalid authentication token');
|
||||
res.writeHead(401);
|
||||
res.write('Invalid authentication token');
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
let data;
|
||||
try {
|
||||
data = JSON.parse(body);
|
||||
} catch (error) {
|
||||
log.warn(`Invalid body data`);
|
||||
res.writeHead(400);
|
||||
res.write('Invalid body data');
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
if (data) {
|
||||
window.webContents.executeJavaScript(`document.saveFile("${data.filename}", "${data.code}")`).then((result) => {
|
||||
res.write(result);
|
||||
res.end();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const autostart = config.get('autostart', false);
|
||||
if (autostart) {
|
||||
try {
|
||||
await enable()
|
||||
} catch (error) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
|
||||
function enable() {
|
||||
if (isListening()) {
|
||||
log.warn('API server already listening');
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
const port = config.get('port', 9990);
|
||||
log.log(`Starting http server on port ${port}`);
|
||||
|
||||
// https://stackoverflow.com/a/62289870
|
||||
let startFinished = false;
|
||||
return new Promise((resolve, reject) => {
|
||||
server.listen(port, "127.0.0.1", () => {
|
||||
if (!startFinished) {
|
||||
startFinished = true;
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
server.once('error', (err) => {
|
||||
if (!startFinished) {
|
||||
startFinished = true;
|
||||
console.log(
|
||||
'There was an error starting the server in the error listener:',
|
||||
err
|
||||
);
|
||||
reject(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function disable() {
|
||||
if (!isListening()) {
|
||||
log.warn('API server not listening');
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
log.log('Stopping http server');
|
||||
return server.close();
|
||||
}
|
||||
|
||||
function toggleServer() {
|
||||
if (isListening()) {
|
||||
return disable();
|
||||
} else {
|
||||
return enable();
|
||||
}
|
||||
}
|
||||
|
||||
function isListening() {
|
||||
return server?.listening ?? false;
|
||||
}
|
||||
|
||||
function toggleAutostart() {
|
||||
const newValue = !isAutostart();
|
||||
config.set('autostart', newValue);
|
||||
log.log(`New autostart value is '${newValue}'`);
|
||||
}
|
||||
|
||||
function isAutostart() {
|
||||
return config.get('autostart');
|
||||
}
|
||||
|
||||
function getAuthenticationToken() {
|
||||
const token = config.get('token');
|
||||
if (token) return token;
|
||||
|
||||
const newToken = generateToken();
|
||||
config.set('token', newToken);
|
||||
return newToken;
|
||||
}
|
||||
|
||||
function generateToken() {
|
||||
const buffer = crypto.randomBytes(48);
|
||||
return buffer.toString('base64')
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
initialize,
|
||||
enable, disable, toggleServer,
|
||||
toggleAutostart, isAutostart,
|
||||
getAuthenticationToken, isListening,
|
||||
}
|
||||
30
electron/exit.html
Normal file
30
electron/exit.html
Normal file
@@ -0,0 +1,30 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Bitburner</title>
|
||||
<link rel="stylesheet" href="main.css" />
|
||||
<style>
|
||||
body {
|
||||
background-color: black;
|
||||
color: #0c0;
|
||||
}
|
||||
|
||||
div {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<h1>Exiting ...</h1>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
30
electron/export.html
Normal file
30
electron/export.html
Normal file
@@ -0,0 +1,30 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Bitburner</title>
|
||||
<link rel="stylesheet" href="main.css" />
|
||||
<style>
|
||||
body {
|
||||
background-color: black;
|
||||
color: #0c0;
|
||||
}
|
||||
|
||||
div {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<h1>Close me when operation is completed.</h1>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
56
electron/gameWindow.js
Normal file
56
electron/gameWindow.js
Normal file
@@ -0,0 +1,56 @@
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const { app, BrowserWindow } = require("electron");
|
||||
const log = require("electron-log");
|
||||
const utils = require("./utils");
|
||||
const achievements = require("./achievements");
|
||||
const menu = require("./menu");
|
||||
const api = require("./api-server");
|
||||
|
||||
const debug = process.argv.includes("--debug");
|
||||
|
||||
async function createWindow(killall) {
|
||||
const setStopProcessHandler = global.app_handlers.stopProcess
|
||||
const window = new BrowserWindow({
|
||||
show: false,
|
||||
backgroundThrottling: false,
|
||||
backgroundColor: "#000000",
|
||||
});
|
||||
|
||||
window.removeMenu();
|
||||
window.maximize();
|
||||
noScripts = killall ? { query: { noScripts: killall } } : {};
|
||||
window.loadFile("index.html", noScripts);
|
||||
window.show();
|
||||
if (debug) window.webContents.openDevTools();
|
||||
|
||||
window.webContents.on("new-window", function (e, url) {
|
||||
// make sure local urls stay in electron perimeter
|
||||
if (url.substr(0, "file://".length) === "file://") {
|
||||
return;
|
||||
}
|
||||
|
||||
// and open every other protocols on the browser
|
||||
e.preventDefault();
|
||||
utils.openExternal(url);
|
||||
});
|
||||
window.webContents.backgroundThrottling = false;
|
||||
|
||||
achievements.enableAchievementsInterval(window);
|
||||
utils.attachUnresponsiveAppHandler(window);
|
||||
|
||||
try {
|
||||
await api.initialize(window);
|
||||
} catch (error) {
|
||||
log.error(error);
|
||||
utils.showErrorBox('Error starting http server', error);
|
||||
}
|
||||
|
||||
menu.refreshMenu(window);
|
||||
setStopProcessHandler(app, window, true);
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
createWindow,
|
||||
}
|
||||
214
electron/main.js
214
electron/main.js
@@ -1,146 +1,116 @@
|
||||
const { app, BrowserWindow, Menu, shell } = require("electron");
|
||||
/* eslint-disable no-process-exit */
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const { app, dialog, BrowserWindow } = require("electron");
|
||||
const log = require("electron-log");
|
||||
const greenworks = require("./greenworks");
|
||||
const api = require("./api-server");
|
||||
const gameWindow = require("./gameWindow");
|
||||
const achievements = require("./achievements");
|
||||
const utils = require("./utils");
|
||||
|
||||
log.catchErrors();
|
||||
log.info(`Started app: ${JSON.stringify(process.argv)}`);
|
||||
|
||||
process.on('uncaughtException', function () {
|
||||
// The exception will already have been logged by electron-log
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
if (greenworks.init()) {
|
||||
console.log("Steam API has been initialized.");
|
||||
log.info("Steam API has been initialized.");
|
||||
} else {
|
||||
console.log("Steam API has failed to initialize.");
|
||||
}
|
||||
|
||||
const debug = false;
|
||||
|
||||
function createWindow(killall) {
|
||||
const win = new BrowserWindow({
|
||||
show: false,
|
||||
backgroundThrottling: false,
|
||||
backgroundColor: "#000000",
|
||||
});
|
||||
|
||||
win.removeMenu();
|
||||
win.maximize();
|
||||
noScripts = killall ? { query: { noScripts: killall } } : {};
|
||||
win.loadFile("index.html", noScripts);
|
||||
win.show();
|
||||
if (debug) win.webContents.openDevTools();
|
||||
|
||||
win.webContents.on("new-window", function (e, url) {
|
||||
// make sure local urls stay in electron perimeter
|
||||
if (url.substr(0, "file://".length) === "file://") {
|
||||
return;
|
||||
}
|
||||
|
||||
// and open every other protocols on the browser
|
||||
e.preventDefault();
|
||||
shell.openExternal(url);
|
||||
});
|
||||
win.webContents.backgroundThrottling = false;
|
||||
|
||||
// This is backward but the game fills in an array called `document.achievements` and we retrieve it from
|
||||
// here. Hey if it works it works.
|
||||
const achievements = greenworks.getAchievementNames();
|
||||
const intervalID = setInterval(async () => {
|
||||
const achs = await win.webContents.executeJavaScript("document.achievements");
|
||||
console.log(achs);
|
||||
for (const ach of achs) {
|
||||
if (!achievements.includes(ach)) continue;
|
||||
greenworks.activateAchievement(ach, () => undefined);
|
||||
}
|
||||
}, 1000);
|
||||
win.achievementsIntervalID = intervalID;
|
||||
|
||||
// Create the Application's main menu
|
||||
Menu.setApplicationMenu(
|
||||
Menu.buildFromTemplate([
|
||||
{
|
||||
label: "Edit",
|
||||
submenu: [
|
||||
{ label: "Undo", accelerator: "CmdOrCtrl+Z", selector: "undo:" },
|
||||
{ label: "Redo", accelerator: "Shift+CmdOrCtrl+Z", selector: "redo:" },
|
||||
{ type: "separator" },
|
||||
{ label: "Cut", accelerator: "CmdOrCtrl+X", selector: "cut:" },
|
||||
{ label: "Copy", accelerator: "CmdOrCtrl+C", selector: "copy:" },
|
||||
{ label: "Paste", accelerator: "CmdOrCtrl+V", selector: "paste:" },
|
||||
{ label: "Select All", accelerator: "CmdOrCtrl+A", selector: "selectAll:" },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "reloads",
|
||||
submenu: [
|
||||
{
|
||||
label: "reload",
|
||||
accelerator: "f5",
|
||||
click: () => {
|
||||
win.loadFile("index.html");
|
||||
},
|
||||
},
|
||||
{
|
||||
label: "reload & kill all scripts",
|
||||
click: () => {
|
||||
setStopProcessHandler(app, win, false);
|
||||
if (intervalID) clearInterval(intervalID);
|
||||
win.webContents.forcefullyCrashRenderer();
|
||||
win.close();
|
||||
createWindow(true);
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "fullscreen",
|
||||
submenu: [
|
||||
{
|
||||
label: "toggle",
|
||||
accelerator: "f9",
|
||||
click: (() => {
|
||||
let full = false;
|
||||
return () => {
|
||||
full = !full;
|
||||
win.setFullScreen(full);
|
||||
};
|
||||
})(),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "debug",
|
||||
submenu: [
|
||||
{
|
||||
label: "activate",
|
||||
click: () => win.webContents.openDevTools(),
|
||||
},
|
||||
],
|
||||
},
|
||||
]),
|
||||
);
|
||||
|
||||
return win;
|
||||
log.warn("Steam API has failed to initialize.");
|
||||
}
|
||||
|
||||
function setStopProcessHandler(app, window, enabled) {
|
||||
const clearWindowHandler = () => {
|
||||
if (window.achievementsIntervalID) {
|
||||
clearInterval(window.achievementsIntervalID);
|
||||
const closingWindowHandler = async (e) => {
|
||||
// We need to prevent the default closing event to add custom logic
|
||||
e.preventDefault();
|
||||
|
||||
// First we clear the achievement timer
|
||||
achievements.disableAchievementsInterval(window);
|
||||
|
||||
// Shutdown the http server
|
||||
api.disable();
|
||||
|
||||
// Because of a steam limitation, if the player has launched an external browser,
|
||||
// steam will keep displaying the game as "Running" in their UI as long as the browser is up.
|
||||
// So we'll alert the player to close their browser.
|
||||
if (global.app_playerOpenedExternalLink) {
|
||||
await dialog.showMessageBox({
|
||||
title: 'Bitburner',
|
||||
message: 'You may have to close your browser to properly exit the game.',
|
||||
detail: 'Steam will keep tracking Bitburner as "Running" if any process started within the game is still running.' +
|
||||
' This includes launching an external link, which opens up your browser.',
|
||||
type: 'warning', buttons: ['OK']
|
||||
});
|
||||
}
|
||||
// We'll try to execute javascript on the page to see if we're stuck
|
||||
let canRunJS = false;
|
||||
window.webContents.executeJavaScript('window.stop(); document.close()', true)
|
||||
.then(() => canRunJS = true);
|
||||
setTimeout(() => {
|
||||
// Wait a few milliseconds to prevent a race condition before loading the exit screen
|
||||
window.webContents.stop();
|
||||
window.loadFile("exit.html")
|
||||
}, 20);
|
||||
|
||||
// Wait 200ms, if the promise has not yet resolved, let's crash the process since we're possibly in a stuck scenario
|
||||
setTimeout(() => {
|
||||
if (!canRunJS) {
|
||||
// We're stuck, let's crash the process
|
||||
log.warn('Forcefully crashing the renderer process');
|
||||
window.webContents.forcefullyCrashRenderer();
|
||||
}
|
||||
|
||||
log.debug('Destroying the window');
|
||||
window.destroy();
|
||||
}, 200);
|
||||
}
|
||||
|
||||
const clearWindowHandler = () => {
|
||||
window = null;
|
||||
};
|
||||
|
||||
const stopProcessHandler = () => {
|
||||
if (process.platform !== "darwin") {
|
||||
app.quit();
|
||||
process.exit(0);
|
||||
}
|
||||
log.info('Quitting the app...');
|
||||
app.isQuiting = true;
|
||||
app.quit();
|
||||
process.exit(0);
|
||||
};
|
||||
|
||||
if (enabled) {
|
||||
log.debug('Adding closing handlers');
|
||||
window.on("closed", clearWindowHandler);
|
||||
window.on("close", closingWindowHandler)
|
||||
app.on("window-all-closed", stopProcessHandler);
|
||||
} else {
|
||||
log.debug('Removing closing handlers');
|
||||
window.removeListener("closed", clearWindowHandler);
|
||||
window.removeListener("close", closingWindowHandler);
|
||||
app.removeListener("window-all-closed", stopProcessHandler);
|
||||
}
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const win = createWindow(process.argv.includes("--no-scripts"));
|
||||
setStopProcessHandler(app, win, true);
|
||||
function startWindow(noScript) {
|
||||
gameWindow.createWindow(noScript);
|
||||
}
|
||||
|
||||
global.app_handlers = {
|
||||
stopProcess: setStopProcessHandler,
|
||||
createWindow: startWindow,
|
||||
}
|
||||
|
||||
app.whenReady().then(async () => {
|
||||
log.info('Application is ready!');
|
||||
|
||||
if (process.argv.includes("--export-save")) {
|
||||
const window = new BrowserWindow({ show: false });
|
||||
await window.loadFile("export.html", false);
|
||||
window.show();
|
||||
setStopProcessHandler(app, window, true);
|
||||
await utils.exportSave(window);
|
||||
} else {
|
||||
startWindow(process.argv.includes("--no-scripts"));
|
||||
}
|
||||
});
|
||||
|
||||
140
electron/menu.js
Normal file
140
electron/menu.js
Normal file
@@ -0,0 +1,140 @@
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const { Menu, clipboard, dialog } = require("electron");
|
||||
const log = require("electron-log");
|
||||
const api = require("./api-server");
|
||||
const utils = require("./utils");
|
||||
|
||||
function getMenu(window) {
|
||||
return Menu.buildFromTemplate([
|
||||
{
|
||||
label: "Edit",
|
||||
submenu: [
|
||||
{ label: "Undo", accelerator: "CmdOrCtrl+Z", selector: "undo:" },
|
||||
{ label: "Redo", accelerator: "Shift+CmdOrCtrl+Z", selector: "redo:" },
|
||||
{ type: "separator" },
|
||||
{ label: "Cut", accelerator: "CmdOrCtrl+X", selector: "cut:" },
|
||||
{ label: "Copy", accelerator: "CmdOrCtrl+C", selector: "copy:" },
|
||||
{ label: "Paste", accelerator: "CmdOrCtrl+V", selector: "paste:" },
|
||||
{ label: "Select All", accelerator: "CmdOrCtrl+A", selector: "selectAll:" },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Reloads",
|
||||
submenu: [
|
||||
{
|
||||
label: "Reload",
|
||||
accelerator: "f5",
|
||||
click: () => window.loadFile("index.html"),
|
||||
},
|
||||
{
|
||||
label: "Reload & Kill All Scripts",
|
||||
click: () => utils.reloadAndKill(window, true),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Fullscreen",
|
||||
submenu: [
|
||||
{
|
||||
label: "Toggle",
|
||||
accelerator: "f9",
|
||||
click: (() => {
|
||||
let full = false;
|
||||
return () => {
|
||||
full = !full;
|
||||
window.setFullScreen(full);
|
||||
};
|
||||
})(),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "API Server",
|
||||
submenu: [
|
||||
{
|
||||
label: api.isListening() ? 'Disable Server' : 'Enable Server',
|
||||
click: (async () => {
|
||||
let success = false;
|
||||
try {
|
||||
await api.toggleServer();
|
||||
success = true;
|
||||
} catch (error) {
|
||||
log.error(error);
|
||||
utils.showErrorBox('Error Toggling Server', error);
|
||||
}
|
||||
if (success && api.isListening()) {
|
||||
utils.writeToast(window, "Started API Server", "success");
|
||||
} else if (success && !api.isListening()) {
|
||||
utils.writeToast(window, "Stopped API Server", "success");
|
||||
} else {
|
||||
utils.writeToast(window, 'Error Toggling Server', "error");
|
||||
}
|
||||
refreshMenu(window);
|
||||
})
|
||||
},
|
||||
{
|
||||
label: api.isAutostart() ? 'Disable Autostart' : 'Enable Autostart',
|
||||
click: (async () => {
|
||||
api.toggleAutostart();
|
||||
if (api.isAutostart()) {
|
||||
utils.writeToast(window, "Enabled API Server Autostart", "success");
|
||||
} else {
|
||||
utils.writeToast(window, "Disabled API Server Autostart", "success");
|
||||
}
|
||||
refreshMenu(window);
|
||||
})
|
||||
},
|
||||
{
|
||||
label: 'Copy Auth Token',
|
||||
click: (async () => {
|
||||
const token = api.getAuthenticationToken();
|
||||
log.log('Wrote authentication token to clipboard');
|
||||
clipboard.writeText(token);
|
||||
utils.writeToast(window, "Copied Authentication Token to Clipboard", "info");
|
||||
})
|
||||
},
|
||||
{
|
||||
type: 'separator',
|
||||
},
|
||||
{
|
||||
label: 'Information',
|
||||
click: () => {
|
||||
dialog.showMessageBox({
|
||||
type: 'info',
|
||||
title: 'Bitburner > API Server Information',
|
||||
message: 'The API Server is used to write script files to your in-game home.',
|
||||
detail: 'There is an official Visual Studio Code extension that makes use of that feature.\n\n' +
|
||||
'It allows you to write your script file in an external IDE and have them pushed over to the game automatically.\n' +
|
||||
'If you want more information, head over to: https://github.com/bitburner-official/bitburner-vscode.',
|
||||
buttons: ['Dismiss', 'Open Extension Link (GitHub)'],
|
||||
defaultId: 0,
|
||||
cancelId: 0,
|
||||
noLink: true,
|
||||
}).then(({response}) => {
|
||||
if (response === 1) {
|
||||
utils.openExternal('https://github.com/bitburner-official/bitburner-vscode');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: "Debug",
|
||||
submenu: [
|
||||
{
|
||||
label: "Activate",
|
||||
click: () => window.webContents.openDevTools(),
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
function refreshMenu(window) {
|
||||
Menu.setApplicationMenu(getMenu(window));
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getMenu, refreshMenu,
|
||||
}
|
||||
325
electron/package-lock.json
generated
Normal file
325
electron/package-lock.json
generated
Normal file
@@ -0,0 +1,325 @@
|
||||
{
|
||||
"name": "bitburner",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "bitburner",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"electron-config": "^2.0.0",
|
||||
"electron-log": "^4.4.4"
|
||||
}
|
||||
},
|
||||
"node_modules/conf": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/conf/-/conf-1.4.0.tgz",
|
||||
"integrity": "sha512-bzlVWS2THbMetHqXKB8ypsXN4DQ/1qopGwNJi1eYbpwesJcd86FBjFciCQX/YwAhp9bM7NVnPFqZ5LpV7gP0Dg==",
|
||||
"dependencies": {
|
||||
"dot-prop": "^4.1.0",
|
||||
"env-paths": "^1.0.0",
|
||||
"make-dir": "^1.0.0",
|
||||
"pkg-up": "^2.0.0",
|
||||
"write-file-atomic": "^2.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/dot-prop": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.1.tgz",
|
||||
"integrity": "sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ==",
|
||||
"dependencies": {
|
||||
"is-obj": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/electron-config": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/electron-config/-/electron-config-2.0.0.tgz",
|
||||
"integrity": "sha512-5mGwRK4lsAo6tiy4KNF/zUInYpUGr7JJzLA8FHOoqBWV3kkKJWSrDXo4Uk2Ffm5aeQ1o73XuorfkYhaWFV2O4g==",
|
||||
"deprecated": "Renamed to `electron-store`.",
|
||||
"dependencies": {
|
||||
"conf": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/electron-log": {
|
||||
"version": "4.4.4",
|
||||
"resolved": "https://registry.npmjs.org/electron-log/-/electron-log-4.4.4.tgz",
|
||||
"integrity": "sha512-jcNtrVmKXG+CHchLo/jnjjQ9K4/ORguWD23H2nqApTwisQ4Qo3IRQtLiorubajX0Uxg76Xm/Yt+eNfQMoHVr5w=="
|
||||
},
|
||||
"node_modules/env-paths": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-1.0.0.tgz",
|
||||
"integrity": "sha1-QWgTO0K7BcOKNbGuQ5fIKYqzaeA=",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/find-up": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
|
||||
"integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
|
||||
"dependencies": {
|
||||
"locate-path": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/graceful-fs": {
|
||||
"version": "4.2.8",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz",
|
||||
"integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg=="
|
||||
},
|
||||
"node_modules/imurmurhash": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
|
||||
"integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
|
||||
"engines": {
|
||||
"node": ">=0.8.19"
|
||||
}
|
||||
},
|
||||
"node_modules/is-obj": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
|
||||
"integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/locate-path": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
|
||||
"integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
|
||||
"dependencies": {
|
||||
"p-locate": "^2.0.0",
|
||||
"path-exists": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/make-dir": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
|
||||
"integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
|
||||
"dependencies": {
|
||||
"pify": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/p-limit": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
|
||||
"integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
|
||||
"dependencies": {
|
||||
"p-try": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/p-locate": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
|
||||
"integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
|
||||
"dependencies": {
|
||||
"p-limit": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/p-try": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
|
||||
"integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/path-exists": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
|
||||
"integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/pify": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
|
||||
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/pkg-up": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz",
|
||||
"integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=",
|
||||
"dependencies": {
|
||||
"find-up": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/signal-exit": {
|
||||
"version": "3.0.6",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz",
|
||||
"integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ=="
|
||||
},
|
||||
"node_modules/write-file-atomic": {
|
||||
"version": "2.4.3",
|
||||
"resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz",
|
||||
"integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==",
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.1.11",
|
||||
"imurmurhash": "^0.1.4",
|
||||
"signal-exit": "^3.0.2"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"conf": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/conf/-/conf-1.4.0.tgz",
|
||||
"integrity": "sha512-bzlVWS2THbMetHqXKB8ypsXN4DQ/1qopGwNJi1eYbpwesJcd86FBjFciCQX/YwAhp9bM7NVnPFqZ5LpV7gP0Dg==",
|
||||
"requires": {
|
||||
"dot-prop": "^4.1.0",
|
||||
"env-paths": "^1.0.0",
|
||||
"make-dir": "^1.0.0",
|
||||
"pkg-up": "^2.0.0",
|
||||
"write-file-atomic": "^2.3.0"
|
||||
}
|
||||
},
|
||||
"dot-prop": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.1.tgz",
|
||||
"integrity": "sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ==",
|
||||
"requires": {
|
||||
"is-obj": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"electron-config": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/electron-config/-/electron-config-2.0.0.tgz",
|
||||
"integrity": "sha512-5mGwRK4lsAo6tiy4KNF/zUInYpUGr7JJzLA8FHOoqBWV3kkKJWSrDXo4Uk2Ffm5aeQ1o73XuorfkYhaWFV2O4g==",
|
||||
"requires": {
|
||||
"conf": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"electron-log": {
|
||||
"version": "4.4.4",
|
||||
"resolved": "https://registry.npmjs.org/electron-log/-/electron-log-4.4.4.tgz",
|
||||
"integrity": "sha512-jcNtrVmKXG+CHchLo/jnjjQ9K4/ORguWD23H2nqApTwisQ4Qo3IRQtLiorubajX0Uxg76Xm/Yt+eNfQMoHVr5w=="
|
||||
},
|
||||
"env-paths": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-1.0.0.tgz",
|
||||
"integrity": "sha1-QWgTO0K7BcOKNbGuQ5fIKYqzaeA="
|
||||
},
|
||||
"find-up": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
|
||||
"integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
|
||||
"requires": {
|
||||
"locate-path": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"graceful-fs": {
|
||||
"version": "4.2.8",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz",
|
||||
"integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg=="
|
||||
},
|
||||
"imurmurhash": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
|
||||
"integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o="
|
||||
},
|
||||
"is-obj": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
|
||||
"integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8="
|
||||
},
|
||||
"locate-path": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
|
||||
"integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
|
||||
"requires": {
|
||||
"p-locate": "^2.0.0",
|
||||
"path-exists": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"make-dir": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
|
||||
"integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
|
||||
"requires": {
|
||||
"pify": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"p-limit": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
|
||||
"integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
|
||||
"requires": {
|
||||
"p-try": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"p-locate": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
|
||||
"integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
|
||||
"requires": {
|
||||
"p-limit": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"p-try": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
|
||||
"integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M="
|
||||
},
|
||||
"path-exists": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
|
||||
"integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU="
|
||||
},
|
||||
"pify": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
|
||||
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
|
||||
},
|
||||
"pkg-up": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz",
|
||||
"integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=",
|
||||
"requires": {
|
||||
"find-up": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"signal-exit": {
|
||||
"version": "3.0.6",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz",
|
||||
"integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ=="
|
||||
},
|
||||
"write-file-atomic": {
|
||||
"version": "2.4.3",
|
||||
"resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz",
|
||||
"integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==",
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.11",
|
||||
"imurmurhash": "^0.1.4",
|
||||
"signal-exit": "^3.0.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,20 +5,24 @@
|
||||
"main": "main.js",
|
||||
"author": "Daniel Xie & Olivier Gagnon",
|
||||
"mac": {
|
||||
"icon": "./public/icons/mac/icon.icns",
|
||||
"icon": "./public/icons/mac/icon.icns",
|
||||
"category": "public.app-category.games"
|
||||
},
|
||||
"win": {
|
||||
"icon": "./public/icons/png/256x256.png"
|
||||
"icon": "./public/icons/png/256x256.png"
|
||||
},
|
||||
"files": [
|
||||
"./build/**/*",
|
||||
"./dist/**/*",
|
||||
"./node_modules/**/*",
|
||||
"./public/**/*",
|
||||
"./public/**/*",
|
||||
"*.js"
|
||||
],
|
||||
"directories": {
|
||||
"buildResources": "public"
|
||||
},
|
||||
"dependencies": {
|
||||
"electron-config": "^2.0.0",
|
||||
"electron-log": "^4.4.4"
|
||||
}
|
||||
}
|
||||
|
||||
116
electron/utils.js
Normal file
116
electron/utils.js
Normal file
@@ -0,0 +1,116 @@
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const { app, dialog, shell } = require("electron");
|
||||
const log = require("electron-log");
|
||||
|
||||
const achievements = require("./achievements");
|
||||
const api = require("./api-server");
|
||||
|
||||
function reloadAndKill(window, killScripts) {
|
||||
const setStopProcessHandler = global.app_handlers.stopProcess
|
||||
const createWindowHandler = global.app_handlers.createWindow;
|
||||
|
||||
log.info('Reloading & Killing all scripts...');
|
||||
setStopProcessHandler(app, window, false);
|
||||
|
||||
achievements.disableAchievementsInterval(window);
|
||||
api.disable();
|
||||
|
||||
window.webContents.forcefullyCrashRenderer();
|
||||
window.on('closed', () => {
|
||||
// Wait for window to be closed before opening the new one to prevent race conditions
|
||||
log.debug('Opening new window');
|
||||
createWindowHandler(killScripts);
|
||||
})
|
||||
|
||||
window.close();
|
||||
}
|
||||
|
||||
function promptForReload(window) {
|
||||
detachUnresponsiveAppHandler(window);
|
||||
dialog.showMessageBox({
|
||||
type: 'error',
|
||||
title: 'Bitburner > Application Unresponsive',
|
||||
message: 'The application is unresponsive, possibly due to an infinite loop in your scripts.',
|
||||
detail:' Did you forget a ns.sleep(x)?\n\n' +
|
||||
'The application will be restarted for you, do you want to kill all running scripts?',
|
||||
buttons: ['Restart', 'Cancel'],
|
||||
defaultId: 0,
|
||||
checkboxLabel: 'Kill all running scripts',
|
||||
checkboxChecked: true,
|
||||
noLink: true,
|
||||
}).then(({response, checkboxChecked}) => {
|
||||
if (response === 0) {
|
||||
reloadAndKill(window, checkboxChecked);
|
||||
} else {
|
||||
attachUnresponsiveAppHandler(window);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function attachUnresponsiveAppHandler(window) {
|
||||
window.unresponsiveHandler = () => promptForReload(window);
|
||||
window.on('unresponsive', window.unresponsiveHandler);
|
||||
}
|
||||
|
||||
function detachUnresponsiveAppHandler(window) {
|
||||
window.off('unresponsive', window.unresponsiveHandler);
|
||||
}
|
||||
|
||||
function showErrorBox(title, error) {
|
||||
dialog.showErrorBox(
|
||||
title,
|
||||
`${error.name}\n\n${error.message}`
|
||||
);
|
||||
}
|
||||
|
||||
function exportSaveFromIndexedDb() {
|
||||
return new Promise((resolve) => {
|
||||
const dbRequest = indexedDB.open("bitburnerSave");
|
||||
dbRequest.onsuccess = () => {
|
||||
const db = dbRequest.result;
|
||||
const transaction = db.transaction(['savestring'], "readonly");
|
||||
const store = transaction.objectStore('savestring');
|
||||
const request = store.get('save');
|
||||
request.onsuccess = () => {
|
||||
const file = new Blob([request.result], {type: 'text/plain'});
|
||||
const a = document.createElement("a");
|
||||
const url = URL.createObjectURL(file);
|
||||
a.href = url;
|
||||
a.download = 'save.json';
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
setTimeout(function () {
|
||||
document.body.removeChild(a);
|
||||
window.URL.revokeObjectURL(url);
|
||||
resolve();
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function exportSave(window) {
|
||||
await window.webContents
|
||||
.executeJavaScript(`${exportSaveFromIndexedDb.toString()}; exportSaveFromIndexedDb();`, true);
|
||||
}
|
||||
|
||||
async function writeTerminal(window, message, type = null) {
|
||||
await window.webContents
|
||||
.executeJavaScript(`window.appNotifier.terminal("${message}", "${type}");`, true)
|
||||
}
|
||||
|
||||
async function writeToast(window, message, type = "info", duration = 2000) {
|
||||
await window.webContents
|
||||
.executeJavaScript(`window.appNotifier.toast("${message}", "${type}", ${duration});`, true)
|
||||
}
|
||||
|
||||
function openExternal(url) {
|
||||
shell.openExternal(url);
|
||||
global.app_playerOpenedExternalLink = true;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
reloadAndKill, showErrorBox, exportSave,
|
||||
attachUnresponsiveAppHandler, detachUnresponsiveAppHandler,
|
||||
openExternal, writeTerminal, writeToast,
|
||||
}
|
||||
@@ -17,12 +17,13 @@
|
||||
<link rel="stylesheet" data-name="vs/editor/editor.main" href="dist/ext/monaco-editor/min/vs/editor/editor.main.css"/>
|
||||
|
||||
<script>
|
||||
var require = { paths: { vs: "dist/ext/monaco-editor/min/vs" } };
|
||||
var require = { paths: { vs: "dist/ext/monaco-editor/min/vs", "monaco-vim": "dist/ext/monaco-vim" } };
|
||||
</script>
|
||||
|
||||
<script src="dist/ext/monaco-editor/min/vs/loader.js"></script>
|
||||
<script src="dist/ext/monaco-editor/min/vs/editor/editor.main.nls.js"></script>
|
||||
<script src="dist/ext/monaco-editor/min/vs/editor/editor.main.js"></script>
|
||||
<script src="dist/ext/monaco-vim.js"></script>
|
||||
|
||||
<!-- Google Analytics -->
|
||||
<script>
|
||||
|
||||
@@ -4,6 +4,8 @@ module.exports = {
|
||||
transform: {
|
||||
"^.+\\.(js|jsx|ts|tsx)$": "babel-jest",
|
||||
},
|
||||
// testMatch: ["**/?(*.)+(test).[jt]s?(x)"],
|
||||
testPathIgnorePatterns: [
|
||||
'.cypress', 'node_modules', 'dist',
|
||||
],
|
||||
testEnvironment: "jsdom",
|
||||
};
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -18,7 +18,7 @@
|
||||
| [CharacterInfo](./bitburner.characterinfo.md) | |
|
||||
| [CharacterMult](./bitburner.charactermult.md) | |
|
||||
| [CodingAttemptOptions](./bitburner.codingattemptoptions.md) | Options to affect the behavior of [CodingContract](./bitburner.codingcontract.md) attempt. |
|
||||
| [CodingContract](./bitburner.codingcontract.md) | Coding Contact API |
|
||||
| [CodingContract](./bitburner.codingcontract.md) | Coding Contract API |
|
||||
| [Corporation](./bitburner.corporation.md) | Corporation API |
|
||||
| [CorporationInfo](./bitburner.corporationinfo.md) | General info about a corporation |
|
||||
| [CrimeStats](./bitburner.crimestats.md) | Data representing the internal values of a crime. |
|
||||
@@ -66,6 +66,7 @@
|
||||
| [StockOrder](./bitburner.stockorder.md) | Return value of [getOrders](./bitburner.tix.getorders.md) |
|
||||
| [StockOrderObject](./bitburner.stockorderobject.md) | Value in map of [StockOrder](./bitburner.stockorder.md) |
|
||||
| [TIX](./bitburner.tix.md) | Stock market API |
|
||||
| [UserInterface](./bitburner.userinterface.md) | User Interface API. |
|
||||
| [Warehouse](./bitburner.warehouse.md) | Warehouse for a division in a city |
|
||||
| [WarehouseAPI](./bitburner.warehouseapi.md) | Corporation Warehouse API |
|
||||
|
||||
|
||||
@@ -28,5 +28,5 @@ Returns the amount of time in milliseconds it takes to execute the grow Netscrip
|
||||
|
||||
RAM cost: 0.05 GB
|
||||
|
||||
Returns the amount of time in milliseconds it takes to execute the grow Netscript function on the target server. The function takes in an optional hackLvl parameter that can be specified to see what the grow time would be at different hacking levels.
|
||||
Returns the amount of time in milliseconds it takes to execute the grow Netscript function on the target server.
|
||||
|
||||
|
||||
@@ -28,5 +28,5 @@ Returns the amount of time in milliseconds it takes to execute the hack Netscrip
|
||||
|
||||
RAM cost: 0.05 GB
|
||||
|
||||
Returns the amount of time in milliseconds it takes to execute the hack Netscript function on the target server. The function takes in an optional hackLvl parameter that can be specified to see what the hack time would be at different hacking levels.
|
||||
Returns the amount of time in milliseconds it takes to execute the hack Netscript function on the target server.
|
||||
|
||||
|
||||
@@ -22,11 +22,11 @@ getWeakenTime(host: string): number;
|
||||
|
||||
number
|
||||
|
||||
Returns the amount of time in milliseconds it takes to execute the grow Netscript function. Returns Infinity if called on a Hacknet Server.
|
||||
Returns the amount of time in milliseconds it takes to execute the weaken() Netscript function on the target server. Returns Infinity if called on a Hacknet Server.
|
||||
|
||||
## 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. The function takes in an optional hackLvl parameter that can be specified to see what the weaken time would be at different hacking levels.
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## NS.hackAnalyze() method
|
||||
|
||||
Get the percent of money stolen with a single thread.
|
||||
Get the part of money stolen with a single thread.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
@@ -22,13 +22,13 @@ hackAnalyze(host: string): number;
|
||||
|
||||
number
|
||||
|
||||
The percentage of money you will steal from the target server with a single hack.
|
||||
The part of money you will steal from the target server with a single thread hack.
|
||||
|
||||
## Remarks
|
||||
|
||||
RAM cost: 1 GB
|
||||
|
||||
Returns the percentage of the specified server’s money you will steal with a single hack. This value is returned in percentage form, not decimal (Netscript functions typically return in decimal form, but not this one).
|
||||
Returns the part of the specified server’s money you will steal with a single thread hack.
|
||||
|
||||
## Example
|
||||
|
||||
@@ -36,6 +36,6 @@ Returns the percentage of the specified server’s money you will steal with a s
|
||||
```ts
|
||||
//For example, assume the following returns 0.01:
|
||||
hackAnalyze("foodnstuff");
|
||||
//This means that if hack the foodnstuff server, then you will steal 1% of its total money. If you hack using N threads, then you will steal N*0.01 times its total money.
|
||||
//This means that if hack the foodnstuff server using a single thread, then you will steal 1%, or 0.01 of its total money. If you hack using N threads, then you will steal N*0.01 times its total money.
|
||||
```
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ export async function main(ns) {
|
||||
| [sleeve](./bitburner.ns.sleeve.md) | [Sleeve](./bitburner.sleeve.md) | Namespace for sleeve functions. |
|
||||
| [stanek](./bitburner.ns.stanek.md) | [Stanek](./bitburner.stanek.md) | Namespace for stanek functions. RAM cost: 0 GB |
|
||||
| [stock](./bitburner.ns.stock.md) | [TIX](./bitburner.tix.md) | Namespace for stock functions. |
|
||||
| [ui](./bitburner.ns.ui.md) | [UserInterface](./bitburner.userinterface.md) | Namespace for user interface functions. RAM cost: 0 GB |
|
||||
|
||||
## Methods
|
||||
|
||||
@@ -110,7 +111,7 @@ export async function main(ns) {
|
||||
| [growthAnalyze(host, growthAmount, cores)](./bitburner.ns.growthanalyze.md) | Calculate the number of grow thread needed to grow a server by a certain multiplier. |
|
||||
| [growthAnalyzeSecurity(threads)](./bitburner.ns.growthanalyzesecurity.md) | Calculate the security increase for a number of thread. |
|
||||
| [hack(host, opts)](./bitburner.ns.hack.md) | Steal a servers money. |
|
||||
| [hackAnalyze(host)](./bitburner.ns.hackanalyze.md) | Get the percent of money stolen with a single thread. |
|
||||
| [hackAnalyze(host)](./bitburner.ns.hackanalyze.md) | Get the part of money stolen with a single thread. |
|
||||
| [hackAnalyzeChance(host)](./bitburner.ns.hackanalyzechance.md) | Get the chance of successfully hacking a server. |
|
||||
| [hackAnalyzeSecurity(threads)](./bitburner.ns.hackanalyzesecurity.md) | Get the security increase for a number of thread. |
|
||||
| [hackAnalyzeThreads(host, hackAmount)](./bitburner.ns.hackanalyzethreads.md) | Predict the effect of hack. |
|
||||
|
||||
@@ -31,9 +31,9 @@ The hostname of the newly purchased server.
|
||||
|
||||
Purchased a server with the specified hostname and amount of RAM.
|
||||
|
||||
The hostname argument can be any data type, but it will be converted to a string and have whitespace removed. Anything that resolves to an empty string will cause the function to fail. If there is already a server with the specified hostname, then the function will automatically append a number at the end of the hostname argument value until it finds a unique hostname. For example, if the script calls `purchaseServer(“foo”, 4)` but a server named “foo” already exists, the it will automatically change the hostname to `foo-0`<!-- -->. If there is already a server with the hostname `foo-0`<!-- -->, then it will change the hostname to `foo-1`<!-- -->, and so on.
|
||||
The hostname argument can be any data type, but it will be converted to a string and have whitespace removed. Anything that resolves to an empty string will cause the function to fail. If there is already a server with the specified hostname, then the function will automatically append a number at the end of the hostname argument value until it finds a unique hostname. For example, if the script calls `purchaseServer(“foo”, 4)` but a server named “foo” already exists, it will automatically change the hostname to `foo-0`<!-- -->. If there is already a server with the hostname `foo-0`<!-- -->, then it will change the hostname to `foo-1`<!-- -->, and so on.
|
||||
|
||||
Note that there is a maximum limit to the amount of servers you can purchase.
|
||||
Note that there is a maximum limit to the number of servers you can purchase.
|
||||
|
||||
Returns the hostname of the newly purchased server as a string. If the function fails to purchase a server, then it will return an empty string. The function will fail if the arguments passed in are invalid, if the player does not have enough money to purchase the specified server, or if the player has exceeded the maximum amount of servers.
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ Start another script on the current server.
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
run(script: string, numThreads?: number, ...args: string[]): number;
|
||||
run(script: string, numThreads?: number, ...args: Array<string | number | boolean>): number;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@@ -18,7 +18,7 @@ run(script: string, numThreads?: number, ...args: string[]): number;
|
||||
| --- | --- | --- |
|
||||
| script | string | Filename of script to run. |
|
||||
| numThreads | number | Optional thread count for new script. Set to 1 by default. Will be rounded to nearest integer. |
|
||||
| args | string\[\] | Additional arguments to pass into the new script that is being run. Note that if any arguments are being passed into the new script, then the second argument numThreads must be filled in with a value. |
|
||||
| args | Array<string | number | boolean> | Additional arguments to pass into the new script that is being run. Note that if any arguments are being passed into the new script, then the second argument numThreads must be filled in with a value. |
|
||||
|
||||
<b>Returns:</b>
|
||||
|
||||
|
||||
13
markdown/bitburner.ns.ui.md
Normal file
13
markdown/bitburner.ns.ui.md
Normal file
@@ -0,0 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [NS](./bitburner.ns.md) > [ui](./bitburner.ns.ui.md)
|
||||
|
||||
## NS.ui property
|
||||
|
||||
Namespace for user interface functions. RAM cost: 0 GB
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
readonly ui: UserInterface;
|
||||
```
|
||||
@@ -30,7 +30,7 @@ RAM cost: 5 GB
|
||||
|
||||
This function is used to automatically attempt to commit crimes. If you are already in the middle of some ‘working’ action (such as working for a company or training at a gym), then running this function will automatically cancel that action and give you your earnings.
|
||||
|
||||
This function returns the number of seconds it takes to attempt the specified crime (e.g It takes 60 seconds to attempt the ‘Rob Store’ crime, so running `commitCrime('rob store')` will return 60).
|
||||
This function returns the number of milliseconds it takes to attempt the specified crime (e.g It takes 60 seconds to attempt the ‘Rob Store’ crime, so running `commitCrime('rob store')` will return 60,000).
|
||||
|
||||
Warning: I do not recommend using the time returned from this function to try and schedule your crime attempts. Instead, I would use the isBusy Singularity function to check whether you have finished attempting a crime. This is because although the game sets a certain crime to be X amount of seconds, there is no guarantee that your browser will follow that time limit.
|
||||
|
||||
|
||||
23
markdown/bitburner.userinterface.gettheme.md
Normal file
23
markdown/bitburner.userinterface.gettheme.md
Normal file
@@ -0,0 +1,23 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [UserInterface](./bitburner.userinterface.md) > [getTheme](./bitburner.userinterface.gettheme.md)
|
||||
|
||||
## UserInterface.getTheme() method
|
||||
|
||||
Get the current theme
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
getTheme(): UserInterfaceTheme;
|
||||
```
|
||||
<b>Returns:</b>
|
||||
|
||||
UserInterfaceTheme
|
||||
|
||||
An object containing the theme's colors
|
||||
|
||||
## Remarks
|
||||
|
||||
RAM cost: cost: 0 GB
|
||||
|
||||
20
markdown/bitburner.userinterface.md
Normal file
20
markdown/bitburner.userinterface.md
Normal file
@@ -0,0 +1,20 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [UserInterface](./bitburner.userinterface.md)
|
||||
|
||||
## UserInterface interface
|
||||
|
||||
User Interface API.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
interface UserInterface
|
||||
```
|
||||
|
||||
## Methods
|
||||
|
||||
| Method | Description |
|
||||
| --- | --- |
|
||||
| [getTheme()](./bitburner.userinterface.gettheme.md) | Get the current theme |
|
||||
|
||||
551
package-lock.json
generated
551
package-lock.json
generated
@@ -1,17 +1,17 @@
|
||||
{
|
||||
"name": "bitburner",
|
||||
"version": "1.1.0",
|
||||
"version": "1.2.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "bitburner",
|
||||
"version": "1.1.0",
|
||||
"version": "1.2.0",
|
||||
"hasInstallScript": true,
|
||||
"license": "SEE LICENSE IN license.txt",
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.4.1",
|
||||
"@emotion/styled": "^11.3.0",
|
||||
"@material-ui/core": "^4.12.3",
|
||||
"@microsoft/api-documenter": "^7.13.65",
|
||||
"@microsoft/api-extractor": "^7.18.17",
|
||||
"@monaco-editor/react": "^4.2.2",
|
||||
@@ -22,6 +22,7 @@
|
||||
"@types/escodegen": "^0.0.7",
|
||||
"@types/numeral": "0.0.25",
|
||||
"@types/react": "^17.0.21",
|
||||
"@types/react-beautiful-dnd": "^13.1.2",
|
||||
"@types/react-dom": "^17.0.9",
|
||||
"@types/react-resizable": "^1.7.3",
|
||||
"acorn": "^8.4.1",
|
||||
@@ -30,17 +31,22 @@
|
||||
"better-react-mathjax": "^1.0.3",
|
||||
"clsx": "^1.1.1",
|
||||
"date-fns": "^2.25.0",
|
||||
"electron-config": "^2.0.0",
|
||||
"escodegen": "^1.11.0",
|
||||
"file-saver": "^1.3.8",
|
||||
"fs": "^0.0.1-security",
|
||||
"jquery": "^3.5.0",
|
||||
"js-sha256": "^0.9.0",
|
||||
"jszip": "^3.7.0",
|
||||
"material-ui-color": "^1.2.0",
|
||||
"material-ui-popup-state": "^1.5.3",
|
||||
"monaco-editor": "^0.27.0",
|
||||
"notistack": "^2.0.2",
|
||||
"numeral": "2.0.6",
|
||||
"prop-types": "^15.8.0",
|
||||
"raw-loader": "^4.0.2",
|
||||
"react": "^17.0.2",
|
||||
"react-beautiful-dnd": "^13.1.0",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-draggable": "^4.4.4",
|
||||
"react-resizable": "^3.0.4",
|
||||
@@ -2890,7 +2896,6 @@
|
||||
"version": "4.12.3",
|
||||
"resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.12.3.tgz",
|
||||
"integrity": "sha512-sdpgI/PL56QVsEJldwEe4FFaFTLUqN+rd7sSZiRCdx2E/C7z5yK0y/khAWVBH24tXwto7I1hCzNWfJGZIYJKnw==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.4.4",
|
||||
"@material-ui/styles": "^4.11.4",
|
||||
@@ -2927,7 +2932,6 @@
|
||||
"version": "4.11.4",
|
||||
"resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.4.tgz",
|
||||
"integrity": "sha512-KNTIZcnj/zprG5LW0Sao7zw+yG3O35pviHzejMdcSGCdWbiO8qzRgOYL8JAxAsWBKOKYwVZxXtHWaB5T2Kvxew==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.4.4",
|
||||
"@emotion/hash": "^0.8.0",
|
||||
@@ -2967,14 +2971,12 @@
|
||||
"node_modules/@material-ui/styles/node_modules/csstype": {
|
||||
"version": "2.6.18",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.18.tgz",
|
||||
"integrity": "sha512-RSU6Hyeg14am3Ah4VZEmeX8H7kLwEEirXe6aU2IPfKNvhXwTflK5HQRDNI0ypQXoqmm+QPyG2IaPuQE5zMwSIQ==",
|
||||
"peer": true
|
||||
"integrity": "sha512-RSU6Hyeg14am3Ah4VZEmeX8H7kLwEEirXe6aU2IPfKNvhXwTflK5HQRDNI0ypQXoqmm+QPyG2IaPuQE5zMwSIQ=="
|
||||
},
|
||||
"node_modules/@material-ui/system": {
|
||||
"version": "4.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.12.1.tgz",
|
||||
"integrity": "sha512-lUdzs4q9kEXZGhbN7BptyiS1rLNHe6kG9o8Y307HCvF4sQxbCgpL2qi+gUk+yI8a2DNk48gISEQxoxpgph0xIw==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.4.4",
|
||||
"@material-ui/utils": "^4.11.2",
|
||||
@@ -3002,14 +3004,12 @@
|
||||
"node_modules/@material-ui/system/node_modules/csstype": {
|
||||
"version": "2.6.18",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.18.tgz",
|
||||
"integrity": "sha512-RSU6Hyeg14am3Ah4VZEmeX8H7kLwEEirXe6aU2IPfKNvhXwTflK5HQRDNI0ypQXoqmm+QPyG2IaPuQE5zMwSIQ==",
|
||||
"peer": true
|
||||
"integrity": "sha512-RSU6Hyeg14am3Ah4VZEmeX8H7kLwEEirXe6aU2IPfKNvhXwTflK5HQRDNI0ypQXoqmm+QPyG2IaPuQE5zMwSIQ=="
|
||||
},
|
||||
"node_modules/@material-ui/types": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@material-ui/types/-/types-5.1.0.tgz",
|
||||
"integrity": "sha512-7cqRjrY50b8QzRSYyhSpx4WRw2YuO0KKIGQEVk5J8uoz2BanawykgZGoWEqKm7pVIbzFDN0SpPcVV4IhOFkl8A==",
|
||||
"peer": true,
|
||||
"peerDependencies": {
|
||||
"@types/react": "*"
|
||||
},
|
||||
@@ -3023,7 +3023,6 @@
|
||||
"version": "4.11.2",
|
||||
"resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.11.2.tgz",
|
||||
"integrity": "sha512-Uul8w38u+PICe2Fg2pDKCaIG7kOyhowZ9vjiC1FsVwPABTW8vPPKfF6OvxRq3IiBaI1faOJmgdvMG7rMJARBhA==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.4.4",
|
||||
"prop-types": "^15.7.2",
|
||||
@@ -3984,6 +3983,15 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/hoist-non-react-statics": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
|
||||
"integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==",
|
||||
"dependencies": {
|
||||
"@types/react": "*",
|
||||
"hoist-non-react-statics": "^3.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/istanbul-lib-coverage": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz",
|
||||
@@ -4062,6 +4070,14 @@
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-beautiful-dnd": {
|
||||
"version": "13.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-beautiful-dnd/-/react-beautiful-dnd-13.1.2.tgz",
|
||||
"integrity": "sha512-+OvPkB8CdE/bGdXKyIhc/Lm2U7UAYCCJgsqmopFmh9gbAudmslkI8eOrPDjg4JhwSE6wytz4a3/wRjKtovHVJg==",
|
||||
"dependencies": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-dom": {
|
||||
"version": "17.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.9.tgz",
|
||||
@@ -4078,6 +4094,17 @@
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-redux": {
|
||||
"version": "7.1.20",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.20.tgz",
|
||||
"integrity": "sha512-q42es4c8iIeTgcnB+yJgRTTzftv3eYYvCZOh1Ckn2eX/3o5TdsQYKUWpLoLuGlcY/p+VAhV9IOEZJcWk/vfkXw==",
|
||||
"dependencies": {
|
||||
"@types/hoist-non-react-statics": "^3.3.0",
|
||||
"@types/react": "*",
|
||||
"hoist-non-react-statics": "^3.3.0",
|
||||
"redux": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-resizable": {
|
||||
"version": "1.7.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-resizable/-/react-resizable-1.7.4.tgz",
|
||||
@@ -6044,8 +6071,7 @@
|
||||
"node_modules/classnames": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz",
|
||||
"integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==",
|
||||
"peer": true
|
||||
"integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA=="
|
||||
},
|
||||
"node_modules/clean-css": {
|
||||
"version": "4.2.3",
|
||||
@@ -6351,6 +6377,58 @@
|
||||
"safe-buffer": "~5.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/conf": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/conf/-/conf-1.4.0.tgz",
|
||||
"integrity": "sha512-bzlVWS2THbMetHqXKB8ypsXN4DQ/1qopGwNJi1eYbpwesJcd86FBjFciCQX/YwAhp9bM7NVnPFqZ5LpV7gP0Dg==",
|
||||
"dependencies": {
|
||||
"dot-prop": "^4.1.0",
|
||||
"env-paths": "^1.0.0",
|
||||
"make-dir": "^1.0.0",
|
||||
"pkg-up": "^2.0.0",
|
||||
"write-file-atomic": "^2.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/conf/node_modules/env-paths": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-1.0.0.tgz",
|
||||
"integrity": "sha1-QWgTO0K7BcOKNbGuQ5fIKYqzaeA=",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/conf/node_modules/make-dir": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
|
||||
"integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
|
||||
"dependencies": {
|
||||
"pify": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/conf/node_modules/pify": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
|
||||
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/conf/node_modules/write-file-atomic": {
|
||||
"version": "2.4.3",
|
||||
"resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz",
|
||||
"integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==",
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.1.11",
|
||||
"imurmurhash": "^0.1.4",
|
||||
"signal-exit": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/config-chain": {
|
||||
"version": "1.1.13",
|
||||
"resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz",
|
||||
@@ -6659,6 +6737,14 @@
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/css-box-model": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz",
|
||||
"integrity": "sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==",
|
||||
"dependencies": {
|
||||
"tiny-invariant": "^1.0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/css-select": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz",
|
||||
@@ -7508,6 +7594,17 @@
|
||||
"webidl-conversions": "^4.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/dot-prop": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.1.tgz",
|
||||
"integrity": "sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ==",
|
||||
"dependencies": {
|
||||
"is-obj": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/duplexer": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz",
|
||||
@@ -7592,6 +7689,15 @@
|
||||
"node": ">= 8.6"
|
||||
}
|
||||
},
|
||||
"node_modules/electron-config": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/electron-config/-/electron-config-2.0.0.tgz",
|
||||
"integrity": "sha512-5mGwRK4lsAo6tiy4KNF/zUInYpUGr7JJzLA8FHOoqBWV3kkKJWSrDXo4Uk2Ffm5aeQ1o73XuorfkYhaWFV2O4g==",
|
||||
"deprecated": "Renamed to `electron-store`.",
|
||||
"dependencies": {
|
||||
"conf": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/electron-notarize": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/electron-notarize/-/electron-notarize-1.1.1.tgz",
|
||||
@@ -11230,6 +11336,14 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/is-obj": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
|
||||
"integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-path-cwd": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz",
|
||||
@@ -13655,6 +13769,11 @@
|
||||
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz",
|
||||
"integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw=="
|
||||
},
|
||||
"node_modules/js-sha256": {
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.9.0.tgz",
|
||||
"integrity": "sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA=="
|
||||
},
|
||||
"node_modules/js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
@@ -14498,7 +14617,6 @@
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/material-ui-popup-state/-/material-ui-popup-state-1.9.3.tgz",
|
||||
"integrity": "sha512-+Ete5Tzw5rXlYfmqptOS8kBUH8vnK5OJsd6IQ7SHtLjU0PsvsmM73M/k8ot0xkX4RmPGuNRsFbK3mlCe/ClQuw==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@material-ui/types": "^6.0.1",
|
||||
@@ -14514,7 +14632,6 @@
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@material-ui/types/-/types-6.0.2.tgz",
|
||||
"integrity": "sha512-/XUca4wUb9pWimLLdM1PE8KS8rTbDEGohSGkGtk3WST7lm23m+8RYv9uOmrvOg/VSsl4bMiOv4t2/LCb+RLbTg==",
|
||||
"peer": true,
|
||||
"peerDependencies": {
|
||||
"@types/react": "*"
|
||||
},
|
||||
@@ -14566,6 +14683,11 @@
|
||||
"node": ">= 4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/memoize-one": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
|
||||
"integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
|
||||
},
|
||||
"node_modules/memory-fs": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
|
||||
@@ -15955,6 +16077,78 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/pkg-up": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz",
|
||||
"integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=",
|
||||
"dependencies": {
|
||||
"find-up": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/pkg-up/node_modules/find-up": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
|
||||
"integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
|
||||
"dependencies": {
|
||||
"locate-path": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/pkg-up/node_modules/locate-path": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
|
||||
"integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
|
||||
"dependencies": {
|
||||
"p-locate": "^2.0.0",
|
||||
"path-exists": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/pkg-up/node_modules/p-limit": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
|
||||
"integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
|
||||
"dependencies": {
|
||||
"p-try": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/pkg-up/node_modules/p-locate": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
|
||||
"integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
|
||||
"dependencies": {
|
||||
"p-limit": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/pkg-up/node_modules/p-try": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
|
||||
"integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/pkg-up/node_modules/path-exists": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
|
||||
"integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/plist": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/plist/-/plist-3.0.4.tgz",
|
||||
@@ -15977,8 +16171,7 @@
|
||||
"node_modules/popper.js": {
|
||||
"version": "1.16.1-lts",
|
||||
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1-lts.tgz",
|
||||
"integrity": "sha512-Kjw8nKRl1m+VrSFCoVGPph93W/qrSO7ZkqPpTf7F4bk/sqcfWK019dWBUpE/fBOsOQY1dks/Bmcbfn1heM/IsA==",
|
||||
"peer": true
|
||||
"integrity": "sha512-Kjw8nKRl1m+VrSFCoVGPph93W/qrSO7ZkqPpTf7F4bk/sqcfWK019dWBUpE/fBOsOQY1dks/Bmcbfn1heM/IsA=="
|
||||
},
|
||||
"node_modules/portfinder": {
|
||||
"version": "1.0.28",
|
||||
@@ -16131,13 +16324,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/prop-types": {
|
||||
"version": "15.7.2",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz",
|
||||
"integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==",
|
||||
"version": "15.8.0",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.0.tgz",
|
||||
"integrity": "sha512-fDGekdaHh65eI3lMi5OnErU6a8Ighg2KjcjQxO7m8VHyWjcPyj5kiOgV1LQDOOOgVy3+5FgjXvdSSX7B8/5/4g==",
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.4.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"react-is": "^16.8.1"
|
||||
"react-is": "^16.13.1"
|
||||
}
|
||||
},
|
||||
"node_modules/prop-types/node_modules/react-is": {
|
||||
@@ -16303,6 +16496,11 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/raf-schd": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz",
|
||||
"integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ=="
|
||||
},
|
||||
"node_modules/ramda": {
|
||||
"version": "0.27.1",
|
||||
"resolved": "https://registry.npmjs.org/ramda/-/ramda-0.27.1.tgz",
|
||||
@@ -16429,6 +16627,24 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-beautiful-dnd": {
|
||||
"version": "13.1.0",
|
||||
"resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.0.tgz",
|
||||
"integrity": "sha512-aGvblPZTJowOWUNiwd6tNfEpgkX5OxmpqxHKNW/4VmvZTNTbeiq7bA3bn5T+QSF2uibXB0D1DmJsb1aC/+3cUA==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.9.2",
|
||||
"css-box-model": "^1.2.0",
|
||||
"memoize-one": "^5.1.1",
|
||||
"raf-schd": "^4.0.2",
|
||||
"react-redux": "^7.2.0",
|
||||
"redux": "^4.0.4",
|
||||
"use-memo-one": "^1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.5 || ^17.0.0",
|
||||
"react-dom": "^16.8.5 || ^17.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-dom": {
|
||||
"version": "17.0.2",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz",
|
||||
@@ -16460,6 +16676,30 @@
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
|
||||
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
|
||||
},
|
||||
"node_modules/react-redux": {
|
||||
"version": "7.2.6",
|
||||
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.6.tgz",
|
||||
"integrity": "sha512-10RPdsz0UUrRL1NZE0ejTkucnclYSgXp5q+tB5SWx2qeG2ZJQJyymgAhwKy73yiL/13btfB6fPr+rgbMAaZIAQ==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.15.4",
|
||||
"@types/react-redux": "^7.1.20",
|
||||
"hoist-non-react-statics": "^3.3.2",
|
||||
"loose-envify": "^1.4.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"react-is": "^17.0.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.3 || ^17"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"react-dom": {
|
||||
"optional": true
|
||||
},
|
||||
"react-native": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/react-refresh": {
|
||||
"version": "0.10.0",
|
||||
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.10.0.tgz",
|
||||
@@ -16625,6 +16865,14 @@
|
||||
"node": ">=8.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/redux": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/redux/-/redux-4.1.2.tgz",
|
||||
"integrity": "sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.9.2"
|
||||
}
|
||||
},
|
||||
"node_modules/regenerate": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
|
||||
@@ -17596,8 +17844,7 @@
|
||||
"node_modules/signal-exit": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.5.tgz",
|
||||
"integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ=="
|
||||
},
|
||||
"node_modules/sisteransi": {
|
||||
"version": "1.0.5",
|
||||
@@ -19143,6 +19390,11 @@
|
||||
"resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz",
|
||||
"integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q="
|
||||
},
|
||||
"node_modules/tiny-invariant": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz",
|
||||
"integrity": "sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg=="
|
||||
},
|
||||
"node_modules/tiny-warning": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
|
||||
@@ -19717,6 +19969,14 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/use-memo-one": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.2.tgz",
|
||||
"integrity": "sha512-u2qFKtxLsia/r8qG0ZKkbytbztzRb317XCkT7yP8wxL0tZ/CzK2G+WWie5vWvpyeP7+YoPIwbJoIHJ4Ba4k0oQ==",
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/util": {
|
||||
"version": "0.11.1",
|
||||
"resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz",
|
||||
@@ -23848,7 +24108,6 @@
|
||||
"version": "4.12.3",
|
||||
"resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.12.3.tgz",
|
||||
"integrity": "sha512-sdpgI/PL56QVsEJldwEe4FFaFTLUqN+rd7sSZiRCdx2E/C7z5yK0y/khAWVBH24tXwto7I1hCzNWfJGZIYJKnw==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.4.4",
|
||||
"@material-ui/styles": "^4.11.4",
|
||||
@@ -23868,7 +24127,6 @@
|
||||
"version": "4.11.4",
|
||||
"resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.4.tgz",
|
||||
"integrity": "sha512-KNTIZcnj/zprG5LW0Sao7zw+yG3O35pviHzejMdcSGCdWbiO8qzRgOYL8JAxAsWBKOKYwVZxXtHWaB5T2Kvxew==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.4.4",
|
||||
"@emotion/hash": "^0.8.0",
|
||||
@@ -23891,8 +24149,7 @@
|
||||
"csstype": {
|
||||
"version": "2.6.18",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.18.tgz",
|
||||
"integrity": "sha512-RSU6Hyeg14am3Ah4VZEmeX8H7kLwEEirXe6aU2IPfKNvhXwTflK5HQRDNI0ypQXoqmm+QPyG2IaPuQE5zMwSIQ==",
|
||||
"peer": true
|
||||
"integrity": "sha512-RSU6Hyeg14am3Ah4VZEmeX8H7kLwEEirXe6aU2IPfKNvhXwTflK5HQRDNI0ypQXoqmm+QPyG2IaPuQE5zMwSIQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -23900,7 +24157,6 @@
|
||||
"version": "4.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.12.1.tgz",
|
||||
"integrity": "sha512-lUdzs4q9kEXZGhbN7BptyiS1rLNHe6kG9o8Y307HCvF4sQxbCgpL2qi+gUk+yI8a2DNk48gISEQxoxpgph0xIw==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.4.4",
|
||||
"@material-ui/utils": "^4.11.2",
|
||||
@@ -23911,8 +24167,7 @@
|
||||
"csstype": {
|
||||
"version": "2.6.18",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.18.tgz",
|
||||
"integrity": "sha512-RSU6Hyeg14am3Ah4VZEmeX8H7kLwEEirXe6aU2IPfKNvhXwTflK5HQRDNI0ypQXoqmm+QPyG2IaPuQE5zMwSIQ==",
|
||||
"peer": true
|
||||
"integrity": "sha512-RSU6Hyeg14am3Ah4VZEmeX8H7kLwEEirXe6aU2IPfKNvhXwTflK5HQRDNI0ypQXoqmm+QPyG2IaPuQE5zMwSIQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -23920,14 +24175,12 @@
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@material-ui/types/-/types-5.1.0.tgz",
|
||||
"integrity": "sha512-7cqRjrY50b8QzRSYyhSpx4WRw2YuO0KKIGQEVk5J8uoz2BanawykgZGoWEqKm7pVIbzFDN0SpPcVV4IhOFkl8A==",
|
||||
"peer": true,
|
||||
"requires": {}
|
||||
},
|
||||
"@material-ui/utils": {
|
||||
"version": "4.11.2",
|
||||
"resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.11.2.tgz",
|
||||
"integrity": "sha512-Uul8w38u+PICe2Fg2pDKCaIG7kOyhowZ9vjiC1FsVwPABTW8vPPKfF6OvxRq3IiBaI1faOJmgdvMG7rMJARBhA==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.4.4",
|
||||
"prop-types": "^15.7.2",
|
||||
@@ -24597,6 +24850,15 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/hoist-non-react-statics": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
|
||||
"integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==",
|
||||
"requires": {
|
||||
"@types/react": "*",
|
||||
"hoist-non-react-statics": "^3.3.0"
|
||||
}
|
||||
},
|
||||
"@types/istanbul-lib-coverage": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz",
|
||||
@@ -24675,6 +24937,14 @@
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"@types/react-beautiful-dnd": {
|
||||
"version": "13.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-beautiful-dnd/-/react-beautiful-dnd-13.1.2.tgz",
|
||||
"integrity": "sha512-+OvPkB8CdE/bGdXKyIhc/Lm2U7UAYCCJgsqmopFmh9gbAudmslkI8eOrPDjg4JhwSE6wytz4a3/wRjKtovHVJg==",
|
||||
"requires": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"version": "17.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.9.tgz",
|
||||
@@ -24691,6 +24961,17 @@
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"@types/react-redux": {
|
||||
"version": "7.1.20",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.20.tgz",
|
||||
"integrity": "sha512-q42es4c8iIeTgcnB+yJgRTTzftv3eYYvCZOh1Ckn2eX/3o5TdsQYKUWpLoLuGlcY/p+VAhV9IOEZJcWk/vfkXw==",
|
||||
"requires": {
|
||||
"@types/hoist-non-react-statics": "^3.3.0",
|
||||
"@types/react": "*",
|
||||
"hoist-non-react-statics": "^3.3.0",
|
||||
"redux": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"@types/react-resizable": {
|
||||
"version": "1.7.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-resizable/-/react-resizable-1.7.4.tgz",
|
||||
@@ -26256,8 +26537,7 @@
|
||||
"classnames": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz",
|
||||
"integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==",
|
||||
"peer": true
|
||||
"integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA=="
|
||||
},
|
||||
"clean-css": {
|
||||
"version": "4.2.3",
|
||||
@@ -26512,6 +26792,48 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"conf": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/conf/-/conf-1.4.0.tgz",
|
||||
"integrity": "sha512-bzlVWS2THbMetHqXKB8ypsXN4DQ/1qopGwNJi1eYbpwesJcd86FBjFciCQX/YwAhp9bM7NVnPFqZ5LpV7gP0Dg==",
|
||||
"requires": {
|
||||
"dot-prop": "^4.1.0",
|
||||
"env-paths": "^1.0.0",
|
||||
"make-dir": "^1.0.0",
|
||||
"pkg-up": "^2.0.0",
|
||||
"write-file-atomic": "^2.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"env-paths": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-1.0.0.tgz",
|
||||
"integrity": "sha1-QWgTO0K7BcOKNbGuQ5fIKYqzaeA="
|
||||
},
|
||||
"make-dir": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
|
||||
"integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
|
||||
"requires": {
|
||||
"pify": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"pify": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
|
||||
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
|
||||
},
|
||||
"write-file-atomic": {
|
||||
"version": "2.4.3",
|
||||
"resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz",
|
||||
"integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==",
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.11",
|
||||
"imurmurhash": "^0.1.4",
|
||||
"signal-exit": "^3.0.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"config-chain": {
|
||||
"version": "1.1.13",
|
||||
"resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz",
|
||||
@@ -26762,6 +27084,14 @@
|
||||
"randomfill": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"css-box-model": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz",
|
||||
"integrity": "sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==",
|
||||
"requires": {
|
||||
"tiny-invariant": "^1.0.6"
|
||||
}
|
||||
},
|
||||
"css-select": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz",
|
||||
@@ -27436,6 +27766,14 @@
|
||||
"webidl-conversions": "^4.0.2"
|
||||
}
|
||||
},
|
||||
"dot-prop": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.1.tgz",
|
||||
"integrity": "sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ==",
|
||||
"requires": {
|
||||
"is-obj": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"duplexer": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz",
|
||||
@@ -27550,6 +27888,14 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"electron-config": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/electron-config/-/electron-config-2.0.0.tgz",
|
||||
"integrity": "sha512-5mGwRK4lsAo6tiy4KNF/zUInYpUGr7JJzLA8FHOoqBWV3kkKJWSrDXo4Uk2Ffm5aeQ1o73XuorfkYhaWFV2O4g==",
|
||||
"requires": {
|
||||
"conf": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"electron-notarize": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/electron-notarize/-/electron-notarize-1.1.1.tgz",
|
||||
@@ -30375,6 +30721,11 @@
|
||||
"has-tostringtag": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"is-obj": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
|
||||
"integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8="
|
||||
},
|
||||
"is-path-cwd": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz",
|
||||
@@ -32184,6 +32535,11 @@
|
||||
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz",
|
||||
"integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw=="
|
||||
},
|
||||
"js-sha256": {
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.9.0.tgz",
|
||||
"integrity": "sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA=="
|
||||
},
|
||||
"js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
@@ -32860,7 +33216,6 @@
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/material-ui-popup-state/-/material-ui-popup-state-1.9.3.tgz",
|
||||
"integrity": "sha512-+Ete5Tzw5rXlYfmqptOS8kBUH8vnK5OJsd6IQ7SHtLjU0PsvsmM73M/k8ot0xkX4RmPGuNRsFbK3mlCe/ClQuw==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@material-ui/types": "^6.0.1",
|
||||
@@ -32872,7 +33227,6 @@
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@material-ui/types/-/types-6.0.2.tgz",
|
||||
"integrity": "sha512-/XUca4wUb9pWimLLdM1PE8KS8rTbDEGohSGkGtk3WST7lm23m+8RYv9uOmrvOg/VSsl4bMiOv4t2/LCb+RLbTg==",
|
||||
"peer": true,
|
||||
"requires": {}
|
||||
}
|
||||
}
|
||||
@@ -32913,6 +33267,11 @@
|
||||
"fs-monkey": "1.0.3"
|
||||
}
|
||||
},
|
||||
"memoize-one": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
|
||||
"integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
|
||||
},
|
||||
"memory-fs": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
|
||||
@@ -34011,6 +34370,59 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"pkg-up": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz",
|
||||
"integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=",
|
||||
"requires": {
|
||||
"find-up": "^2.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"find-up": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
|
||||
"integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
|
||||
"requires": {
|
||||
"locate-path": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"locate-path": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
|
||||
"integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
|
||||
"requires": {
|
||||
"p-locate": "^2.0.0",
|
||||
"path-exists": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"p-limit": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
|
||||
"integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
|
||||
"requires": {
|
||||
"p-try": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"p-locate": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
|
||||
"integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
|
||||
"requires": {
|
||||
"p-limit": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"p-try": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
|
||||
"integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M="
|
||||
},
|
||||
"path-exists": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
|
||||
"integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU="
|
||||
}
|
||||
}
|
||||
},
|
||||
"plist": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/plist/-/plist-3.0.4.tgz",
|
||||
@@ -34030,8 +34442,7 @@
|
||||
"popper.js": {
|
||||
"version": "1.16.1-lts",
|
||||
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1-lts.tgz",
|
||||
"integrity": "sha512-Kjw8nKRl1m+VrSFCoVGPph93W/qrSO7ZkqPpTf7F4bk/sqcfWK019dWBUpE/fBOsOQY1dks/Bmcbfn1heM/IsA==",
|
||||
"peer": true
|
||||
"integrity": "sha512-Kjw8nKRl1m+VrSFCoVGPph93W/qrSO7ZkqPpTf7F4bk/sqcfWK019dWBUpE/fBOsOQY1dks/Bmcbfn1heM/IsA=="
|
||||
},
|
||||
"portfinder": {
|
||||
"version": "1.0.28",
|
||||
@@ -34146,13 +34557,13 @@
|
||||
}
|
||||
},
|
||||
"prop-types": {
|
||||
"version": "15.7.2",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz",
|
||||
"integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==",
|
||||
"version": "15.8.0",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.0.tgz",
|
||||
"integrity": "sha512-fDGekdaHh65eI3lMi5OnErU6a8Ighg2KjcjQxO7m8VHyWjcPyj5kiOgV1LQDOOOgVy3+5FgjXvdSSX7B8/5/4g==",
|
||||
"requires": {
|
||||
"loose-envify": "^1.4.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"react-is": "^16.8.1"
|
||||
"react-is": "^16.13.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"react-is": {
|
||||
@@ -34288,6 +34699,11 @@
|
||||
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
|
||||
"dev": true
|
||||
},
|
||||
"raf-schd": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz",
|
||||
"integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ=="
|
||||
},
|
||||
"ramda": {
|
||||
"version": "0.27.1",
|
||||
"resolved": "https://registry.npmjs.org/ramda/-/ramda-0.27.1.tgz",
|
||||
@@ -34384,6 +34800,20 @@
|
||||
"object-assign": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"react-beautiful-dnd": {
|
||||
"version": "13.1.0",
|
||||
"resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.0.tgz",
|
||||
"integrity": "sha512-aGvblPZTJowOWUNiwd6tNfEpgkX5OxmpqxHKNW/4VmvZTNTbeiq7bA3bn5T+QSF2uibXB0D1DmJsb1aC/+3cUA==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.9.2",
|
||||
"css-box-model": "^1.2.0",
|
||||
"memoize-one": "^5.1.1",
|
||||
"raf-schd": "^4.0.2",
|
||||
"react-redux": "^7.2.0",
|
||||
"redux": "^4.0.4",
|
||||
"use-memo-one": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"react-dom": {
|
||||
"version": "17.0.2",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz",
|
||||
@@ -34408,6 +34838,19 @@
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
|
||||
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
|
||||
},
|
||||
"react-redux": {
|
||||
"version": "7.2.6",
|
||||
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.6.tgz",
|
||||
"integrity": "sha512-10RPdsz0UUrRL1NZE0ejTkucnclYSgXp5q+tB5SWx2qeG2ZJQJyymgAhwKy73yiL/13btfB6fPr+rgbMAaZIAQ==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.15.4",
|
||||
"@types/react-redux": "^7.1.20",
|
||||
"hoist-non-react-statics": "^3.3.2",
|
||||
"loose-envify": "^1.4.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"react-is": "^17.0.2"
|
||||
}
|
||||
},
|
||||
"react-refresh": {
|
||||
"version": "0.10.0",
|
||||
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.10.0.tgz",
|
||||
@@ -34537,6 +34980,14 @@
|
||||
"picomatch": "^2.2.1"
|
||||
}
|
||||
},
|
||||
"redux": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/redux/-/redux-4.1.2.tgz",
|
||||
"integrity": "sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.9.2"
|
||||
}
|
||||
},
|
||||
"regenerate": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
|
||||
@@ -35305,8 +35756,7 @@
|
||||
"signal-exit": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.5.tgz",
|
||||
"integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ=="
|
||||
},
|
||||
"sisteransi": {
|
||||
"version": "1.0.5",
|
||||
@@ -36569,6 +37019,11 @@
|
||||
"resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz",
|
||||
"integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q="
|
||||
},
|
||||
"tiny-invariant": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz",
|
||||
"integrity": "sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg=="
|
||||
},
|
||||
"tiny-warning": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
|
||||
@@ -37025,6 +37480,12 @@
|
||||
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
|
||||
"integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ=="
|
||||
},
|
||||
"use-memo-one": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.2.tgz",
|
||||
"integrity": "sha512-u2qFKtxLsia/r8qG0ZKkbytbztzRb317XCkT7yP8wxL0tZ/CzK2G+WWie5vWvpyeP7+YoPIwbJoIHJ4Ba4k0oQ==",
|
||||
"requires": {}
|
||||
},
|
||||
"util": {
|
||||
"version": "0.11.1",
|
||||
"resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz",
|
||||
|
||||
13
package.json
13
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "bitburner",
|
||||
"license": "SEE LICENSE IN license.txt",
|
||||
"version": "1.2.0",
|
||||
"version": "1.3.0",
|
||||
"main": "electron-main.js",
|
||||
"author": {
|
||||
"name": "Daniel Xie & Olivier Gagnon"
|
||||
@@ -12,6 +12,7 @@
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.4.1",
|
||||
"@emotion/styled": "^11.3.0",
|
||||
"@material-ui/core": "^4.12.3",
|
||||
"@microsoft/api-documenter": "^7.13.65",
|
||||
"@microsoft/api-extractor": "^7.18.17",
|
||||
"@monaco-editor/react": "^4.2.2",
|
||||
@@ -22,6 +23,7 @@
|
||||
"@types/escodegen": "^0.0.7",
|
||||
"@types/numeral": "0.0.25",
|
||||
"@types/react": "^17.0.21",
|
||||
"@types/react-beautiful-dnd": "^13.1.2",
|
||||
"@types/react-dom": "^17.0.9",
|
||||
"@types/react-resizable": "^1.7.3",
|
||||
"acorn": "^8.4.1",
|
||||
@@ -30,17 +32,22 @@
|
||||
"better-react-mathjax": "^1.0.3",
|
||||
"clsx": "^1.1.1",
|
||||
"date-fns": "^2.25.0",
|
||||
"electron-config": "^2.0.0",
|
||||
"escodegen": "^1.11.0",
|
||||
"file-saver": "^1.3.8",
|
||||
"fs": "^0.0.1-security",
|
||||
"jquery": "^3.5.0",
|
||||
"js-sha256": "^0.9.0",
|
||||
"jszip": "^3.7.0",
|
||||
"material-ui-color": "^1.2.0",
|
||||
"material-ui-popup-state": "^1.5.3",
|
||||
"monaco-editor": "^0.27.0",
|
||||
"notistack": "^2.0.2",
|
||||
"numeral": "2.0.6",
|
||||
"prop-types": "^15.8.0",
|
||||
"raw-loader": "^4.0.2",
|
||||
"react": "^17.0.2",
|
||||
"react-beautiful-dnd": "^13.1.0",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-draggable": "^4.4.4",
|
||||
"react-resizable": "^3.0.4",
|
||||
@@ -104,12 +111,14 @@
|
||||
"build": "webpack --mode production",
|
||||
"build:dev": "webpack --mode development",
|
||||
"lint": "eslint --fix . --ext js,jsx,ts,tsx",
|
||||
"lint:report": "eslint --ext js,jsx,ts,tsx .",
|
||||
"preinstall": "node ./scripts/engines-check.js",
|
||||
"test": "jest",
|
||||
"test:watch": "jest --watch",
|
||||
"watch": "webpack --watch --mode production",
|
||||
"watch:dev": "webpack --watch --mode development",
|
||||
"electron": "cp -r electron/* .package && cp index.html .package && cp main.bundle.js .package && cp dist/vendor.bundle.js .package/dist/ && cp -r dist/ext .package/dist/ && electron-packager .package bitburner --all --out .build --overwrite --icon .package/icon.png",
|
||||
"electron": "sh ./package.sh",
|
||||
"electron:packager": "electron-packager .package bitburner --all --out .build --overwrite --icon .package/icon.png --no-prune",
|
||||
"allbuild": "npm run build && npm run electron && git add --all && git commit --amend --no-edit && git push -f -u origin dev"
|
||||
}
|
||||
}
|
||||
|
||||
20
package.sh
20
package.sh
@@ -1,11 +1,13 @@
|
||||
# npm install electron --save-dev
|
||||
# npm install electron-packager --save-dev
|
||||
#!/bin/sh
|
||||
|
||||
mkdir -p .package/dist/src/ThirdParty || true
|
||||
mkdir -p .package/src/ThirdParty || true
|
||||
mkdir -p .package/node_modules || true
|
||||
|
||||
cp index.html .package
|
||||
cp electron/* .package
|
||||
cp -r electron/* .package
|
||||
cp -r dist/ext .package/dist
|
||||
|
||||
# The css files
|
||||
cp dist/vendor.css .package/dist
|
||||
cp main.css .package/main.css
|
||||
@@ -14,6 +16,14 @@ cp main.css .package/main.css
|
||||
cp dist/vendor.bundle.js .package/dist/vendor.bundle.js
|
||||
cp main.bundle.js .package/main.bundle.js
|
||||
|
||||
cp src/ThirdParty/raphael.min.js .package/src/ThirdParty/raphael.min.js
|
||||
# Source maps
|
||||
cp dist/vendor.bundle.js.map .package/dist/vendor.bundle.js.map
|
||||
cp main.bundle.js.map .package/main.bundle.js.map
|
||||
|
||||
npm run package-electron
|
||||
# Install electron sub-dependencies
|
||||
cd electron
|
||||
npm install
|
||||
cd ..
|
||||
|
||||
# And finally build the app.
|
||||
npm run electron:packager
|
||||
|
||||
@@ -36,15 +36,16 @@ export function printAliases(): void {
|
||||
|
||||
// Returns true if successful, false otherwise
|
||||
export function parseAliasDeclaration(dec: string, global = false): boolean {
|
||||
const re = /^([_|\w|!|%|,|@]+)="(.+)"$/;
|
||||
const re = /^([\w|!|%|,|@|-]+)=(("(.+)")|('(.+)'))$/;
|
||||
const matches = dec.match(re);
|
||||
if (matches == null || matches.length != 3) {
|
||||
if (matches == null || matches.length != 7) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (global) {
|
||||
addGlobalAlias(matches[1], matches[2]);
|
||||
addGlobalAlias(matches[1], matches[4] || matches[6]);
|
||||
} else {
|
||||
addAlias(matches[1], matches[2]);
|
||||
addAlias(matches[1], matches[4] || matches[6]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1844,7 +1844,7 @@ function initAugmentations(): void {
|
||||
moneyCost: 3.75e8,
|
||||
info:
|
||||
"A drug that genetically modifies the neurons in the brain " +
|
||||
"resulting in neurons never die, continuously " +
|
||||
"resulting in neurons that never die, continuously " +
|
||||
"regenerate, and strengthen themselves.",
|
||||
hacking_exp_mult: 1.4,
|
||||
});
|
||||
@@ -1925,7 +1925,7 @@ function initAugmentations(): void {
|
||||
repCost: 7.5e3,
|
||||
moneyCost: 3e7,
|
||||
info:
|
||||
"A tiny chip that sits behind the retinae. This implant lets the" + "user visually detect infrared radiation.",
|
||||
"A tiny chip that sits behind the retinae. This implant lets the user visually detect infrared radiation.",
|
||||
crime_success_mult: 1.25,
|
||||
crime_money_mult: 1.1,
|
||||
dexterity_mult: 1.1,
|
||||
|
||||
@@ -16,6 +16,8 @@ import Typography from "@mui/material/Typography";
|
||||
import Button from "@mui/material/Button";
|
||||
import Tooltip from "@mui/material/Tooltip";
|
||||
import Box from "@mui/material/Box";
|
||||
import { Settings } from "../../Settings/Settings";
|
||||
import { ConfirmationModal } from "../../ui/React/ConfirmationModal";
|
||||
|
||||
interface IProps {
|
||||
exportGameFn: () => void;
|
||||
@@ -23,6 +25,7 @@ interface IProps {
|
||||
}
|
||||
|
||||
export function AugmentationsRoot(props: IProps): React.ReactElement {
|
||||
const [installOpen, setInstallOpen] = useState(false);
|
||||
const player = use.Player();
|
||||
const setRerender = useState(false)[1];
|
||||
function rerender(): void {
|
||||
@@ -43,6 +46,14 @@ export function AugmentationsRoot(props: IProps): React.ReactElement {
|
||||
return "";
|
||||
}
|
||||
|
||||
function doInstall(): void {
|
||||
if (!Settings.SuppressBuyAugmentationConfirmation) {
|
||||
setInstallOpen(true);
|
||||
} else {
|
||||
props.installAugmentationsFn();
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Typography variant="h4">Augmentations</Typography>
|
||||
@@ -73,11 +84,36 @@ export function AugmentationsRoot(props: IProps): React.ReactElement {
|
||||
<Box mx={2}>
|
||||
<Tooltip title={<Typography>'I never asked for this'</Typography>}>
|
||||
<span>
|
||||
<Button disabled={player.queuedAugmentations.length === 0} onClick={props.installAugmentationsFn}>
|
||||
<Button disabled={player.queuedAugmentations.length === 0} onClick={doInstall}>
|
||||
Install Augmentations
|
||||
</Button>
|
||||
</span>
|
||||
</Tooltip>
|
||||
<ConfirmationModal
|
||||
open={installOpen}
|
||||
onClose={() => setInstallOpen(false)}
|
||||
onConfirm={props.installAugmentationsFn}
|
||||
confirmationText={
|
||||
<>
|
||||
Installing will reset
|
||||
<br />
|
||||
<br />- money
|
||||
<br />- skill / experience
|
||||
<br />- every server except home
|
||||
<br />- factions and reputation
|
||||
<br />
|
||||
<br />
|
||||
You will keep:
|
||||
<br />
|
||||
<br />- All scripts on home
|
||||
<br />- home ram and cores
|
||||
<br />
|
||||
<br />
|
||||
It is recommended to install several Augmentations at once. Preferably everything from any faction of your
|
||||
chosing.
|
||||
</>
|
||||
}
|
||||
/>
|
||||
<Tooltip title={<Typography>It's always a good idea to backup/export your save!</Typography>}>
|
||||
<Button sx={{ mx: 2 }} onClick={doExport} color="error">
|
||||
Backup Save {exportBonusStr()}
|
||||
|
||||
@@ -165,7 +165,7 @@ BitNodes["BitNode4"] = new BitNode(
|
||||
<br />
|
||||
Destroying this BitNode will give you Source-File 4, or if you already have this Source-File it will upgrade its
|
||||
level up to a maximum of 3. This Source-File lets you access and use the Singularity Functions in other BitNodes.
|
||||
Each level of this Source-File will open up more Singularity Functions that you can use.
|
||||
Each level of this Source-File reduces the RAM cost of singularity functions.
|
||||
</>
|
||||
),
|
||||
);
|
||||
@@ -542,7 +542,7 @@ BitNodes["BitNode13"] = new BitNode(
|
||||
<br />
|
||||
<br />
|
||||
Their leader, Allison "Mother" Stanek is said to have created her own Augmentation whose power goes beyond any
|
||||
other. Find her in Chongquing and gain her trust.
|
||||
other. Find her in Chongqing and gain her trust.
|
||||
<br />
|
||||
<br />
|
||||
In this BitNode:
|
||||
@@ -745,7 +745,7 @@ export function initBitNodeMultipliers(p: IPlayer): void {
|
||||
BitNodeMultipliers.StaneksGiftPowerMultiplier = 0.5;
|
||||
BitNodeMultipliers.StaneksGiftExtraSize = 2;
|
||||
BitNodeMultipliers.GangSoftcap = 0.8;
|
||||
BitNodeMultipliers.CorporationSoftCap = 0.9;
|
||||
BitNodeMultipliers.CorporationSoftCap = 0.7;
|
||||
BitNodeMultipliers.WorldDaemonDifficulty = 2;
|
||||
break;
|
||||
case 10: // Digital Carbon
|
||||
|
||||
@@ -34,6 +34,12 @@ import { getTimestamp } from "../utils/helpers/getTimestamp";
|
||||
import { joinFaction } from "../Faction/FactionHelpers";
|
||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||
|
||||
interface BlackOpsAttempt {
|
||||
error?: string;
|
||||
isAvailable?: boolean;
|
||||
action?: BlackOperation;
|
||||
}
|
||||
|
||||
export class Bladeburner implements IBladeburner {
|
||||
numHosp = 0;
|
||||
moneyLost = 0;
|
||||
@@ -113,6 +119,43 @@ export class Bladeburner implements IBladeburner {
|
||||
return Math.min(1, this.stamina / (0.5 * this.maxStamina));
|
||||
}
|
||||
|
||||
canAttemptBlackOp(actionId: IActionIdentifier): BlackOpsAttempt {
|
||||
// Safety measure - don't repeat BlackOps that are already done
|
||||
if (this.blackops[actionId.name] != null) {
|
||||
return { error: "Tried to start a Black Operation that had already been completed" };
|
||||
}
|
||||
|
||||
const action = this.getActionObject(actionId);
|
||||
if (!(action instanceof BlackOperation)) throw new Error(`Action should be BlackOperation but isn't`);
|
||||
if (action == null) throw new Error("Failed to get BlackOperation object for: " + actionId.name);
|
||||
|
||||
if (action.reqdRank > this.rank) {
|
||||
return { error: "Tried to start a Black Operation without the rank requirement" };
|
||||
}
|
||||
|
||||
// Can't start a BlackOp if you haven't done the one before it
|
||||
const blackops = [];
|
||||
for (const nm in BlackOperations) {
|
||||
if (BlackOperations.hasOwnProperty(nm)) {
|
||||
blackops.push(nm);
|
||||
}
|
||||
}
|
||||
blackops.sort(function (a, b) {
|
||||
return BlackOperations[a].reqdRank - BlackOperations[b].reqdRank; // Sort black ops in intended order
|
||||
});
|
||||
|
||||
const i = blackops.indexOf(actionId.name);
|
||||
if (i === -1) {
|
||||
return { error: `Invalid Black Op: '${name}'` };
|
||||
}
|
||||
|
||||
if (i > 0 && this.blackops[blackops[i - 1]] == null) {
|
||||
return { error: `Preceding Black Op must be completed before starting '${actionId.name}'.` };
|
||||
}
|
||||
|
||||
return { isAvailable: true, action };
|
||||
}
|
||||
|
||||
startAction(player: IPlayer, actionId: IActionIdentifier): void {
|
||||
if (actionId == null) return;
|
||||
this.action = actionId;
|
||||
@@ -156,18 +199,16 @@ export class Bladeburner implements IBladeburner {
|
||||
case ActionTypes["BlackOp"]:
|
||||
case ActionTypes["BlackOperation"]: {
|
||||
try {
|
||||
// Safety measure - don't repeat BlackOps that are already done
|
||||
if (this.blackops[actionId.name] != null) {
|
||||
const testBlackOp = this.canAttemptBlackOp(actionId);
|
||||
if (!testBlackOp.isAvailable) {
|
||||
this.resetAction();
|
||||
this.log("Error: Tried to start a Black Operation that had already been completed");
|
||||
this.log(`Error: ${testBlackOp.error}`);
|
||||
break;
|
||||
}
|
||||
|
||||
const action = this.getActionObject(actionId);
|
||||
if (action == null) {
|
||||
throw new Error("Failed to get BlackOperation object for: " + actionId.name);
|
||||
if (testBlackOp.action === undefined) {
|
||||
throw new Error("action should not be null");
|
||||
}
|
||||
this.actionTimeToComplete = action.getActionTime(this);
|
||||
this.actionTimeToComplete = testBlackOp.action.getActionTime(this);
|
||||
} catch (e: any) {
|
||||
exceptionAlert(e);
|
||||
}
|
||||
@@ -502,6 +543,7 @@ export class Bladeburner implements IBladeburner {
|
||||
const skill = Skills[skillName];
|
||||
if (skill == null || !(skill instanceof Skill)) {
|
||||
this.postToConsole("Invalid skill name (Note that it is case-sensitive): " + skillName);
|
||||
break;
|
||||
}
|
||||
if (args[1].toLowerCase() === "list") {
|
||||
let level = 0;
|
||||
@@ -515,7 +557,9 @@ export class Bladeburner implements IBladeburner {
|
||||
currentLevel = this.skills[skillName];
|
||||
}
|
||||
const pointCost = skill.calculateCost(currentLevel);
|
||||
if (this.skillPoints >= pointCost) {
|
||||
if (skill.maxLvl !== 0 && currentLevel >= skill.maxLvl) {
|
||||
this.postToConsole(`This skill ${skill.name} is already at max level (${currentLevel}/${skill.maxLvl}).`);
|
||||
} else if (this.skillPoints >= pointCost) {
|
||||
this.skillPoints -= pointCost;
|
||||
this.upgradeSkill(skill);
|
||||
this.log(skill.name + " upgraded to Level " + this.skills[skillName]);
|
||||
@@ -2032,44 +2076,9 @@ export class Bladeburner implements IBladeburner {
|
||||
|
||||
// Special logic for Black Ops
|
||||
if (actionId.type === ActionTypes["BlackOp"]) {
|
||||
// Can't start a BlackOp if you don't have the required rank
|
||||
const action = this.getActionObject(actionId);
|
||||
if (action == null) throw new Error(`Action not found ${actionId.type}, ${actionId.name}`);
|
||||
if (!(action instanceof BlackOperation)) throw new Error(`Action should be BlackOperation but isn't`);
|
||||
//const blackOp = (action as BlackOperation);
|
||||
if (action.reqdRank > this.rank) {
|
||||
workerScript.log("bladeburner.startAction", () => `Insufficient rank to start Black Op '${actionId.name}'.`);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Can't start a BlackOp if its already been done
|
||||
if (this.blackops[actionId.name] != null) {
|
||||
workerScript.log("bladeburner.startAction", () => `Black Op ${actionId.name} has already been completed.`);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Can't start a BlackOp if you haven't done the one before it
|
||||
const blackops = [];
|
||||
for (const nm in BlackOperations) {
|
||||
if (BlackOperations.hasOwnProperty(nm)) {
|
||||
blackops.push(nm);
|
||||
}
|
||||
}
|
||||
blackops.sort(function (a, b) {
|
||||
return BlackOperations[a].reqdRank - BlackOperations[b].reqdRank; // Sort black ops in intended order
|
||||
});
|
||||
|
||||
const i = blackops.indexOf(actionId.name);
|
||||
if (i === -1) {
|
||||
workerScript.log("bladeburner.startAction", () => `Invalid Black Op: '${name}'`);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (i > 0 && this.blackops[blackops[i - 1]] == null) {
|
||||
workerScript.log(
|
||||
"bladeburner.startAction",
|
||||
() => `Preceding Black Op must be completed before starting '${actionId.name}'.`,
|
||||
);
|
||||
const canRunOp = this.canAttemptBlackOp(actionId);
|
||||
if (!canRunOp.isAvailable) {
|
||||
workerScript.log("bladeburner.startAction", () => canRunOp.error + "");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,8 +25,8 @@ export const ConsoleHelpText: {
|
||||
"automate [var] [val] [hi/low]",
|
||||
"",
|
||||
"A simple way to automate your Bladeburner actions. This console command can be used " +
|
||||
"to automatically start an action when your stamina rises above a certain threshold, and " +
|
||||
"automatically switch to another action when your stamina drops below another threshold.",
|
||||
"to automatically start an action when your stamina rises above a certain threshold, and " +
|
||||
"automatically switch to another action when your stamina drops below another threshold.",
|
||||
" automate status - Check the current status of your automation and get a brief description of what it'll do",
|
||||
" automate en - Enable the automation feature",
|
||||
" automate dis - Disable the automation feature",
|
||||
@@ -39,9 +39,9 @@ export const ConsoleHelpText: {
|
||||
" automate general 'Field Analysis' low",
|
||||
"",
|
||||
"Using the four console commands above will set the automation to perform Tracking contracts " +
|
||||
"if your stamina is 100 or higher, and then switch to Field Analysis if your stamina drops below " +
|
||||
"50. Note that when setting the action, the name of the action is CASE-SENSITIVE. It must " +
|
||||
"exactly match whatever the name is in the UI.",
|
||||
"if your stamina is 100 or higher, and then switch to Field Analysis if your stamina drops below " +
|
||||
"50. Note that when setting the action, the name of the action is CASE-SENSITIVE. It must " +
|
||||
"exactly match whatever the name is in the UI.",
|
||||
],
|
||||
clear: ["clear", "", "Clears the console"],
|
||||
cls: ["cls", "", "Clears the console"],
|
||||
@@ -49,8 +49,8 @@ export const ConsoleHelpText: {
|
||||
"help [command]",
|
||||
"",
|
||||
"Running 'help' with no arguments displays the general help text, which lists all console commands " +
|
||||
"and a brief description of what they do. A command can be specified to get more specific help text " +
|
||||
"about that particular command. For example:",
|
||||
"and a brief description of what they do. A command can be specified to get more specific help text " +
|
||||
"about that particular command. For example:",
|
||||
"",
|
||||
" help automate",
|
||||
"",
|
||||
@@ -60,8 +60,8 @@ export const ConsoleHelpText: {
|
||||
"log [en/dis] [type]",
|
||||
"",
|
||||
"Enable or disable logging. By default, the results of completing actions such as contracts/operations are logged " +
|
||||
"in the console. There are also random events that are logged in the console as well. The five categories of " +
|
||||
"things that get logged are:",
|
||||
"in the console. There are also random events that are logged in the console as well. The five categories of " +
|
||||
"things that get logged are:",
|
||||
"",
|
||||
"[general, contracts, ops, blackops, events]",
|
||||
"",
|
||||
@@ -86,10 +86,11 @@ export const ConsoleHelpText: {
|
||||
" skill list",
|
||||
"",
|
||||
"To display information about a specific skill, specify the name of the skill afterwards. " +
|
||||
"Note that the name of the skill is case-sensitive. Enter it exactly as seen in the UI. If " +
|
||||
"the name of the skill has whitespace, enclose the name of the skill in double quotation marks:",
|
||||
"Note that the name of the skill is case-sensitive. Enter it exactly as seen in the UI. If " +
|
||||
"the name of the skill has whitespace, enclose the name of the skill in double quotation marks:",
|
||||
"",
|
||||
" skill list Reaper<br>" + " skill list 'Digital Observer'",
|
||||
" skill list Reaper",
|
||||
" skill list 'Digital Observer'",
|
||||
"",
|
||||
"This console command can also be used to level up skills:",
|
||||
"",
|
||||
@@ -99,9 +100,9 @@ export const ConsoleHelpText: {
|
||||
"start [type] [name]",
|
||||
"",
|
||||
"Start an action. An action is specified by its type and its name. The " +
|
||||
"name is case-sensitive. It must appear exactly as it does in the UI. If " +
|
||||
"the name of the action has whitespace, enclose it in double quotation marks. " +
|
||||
"Valid action types include:",
|
||||
"name is case-sensitive. It must appear exactly as it does in the UI. If " +
|
||||
"the name of the action has whitespace, enclose it in double quotation marks. " +
|
||||
"Valid action types include:",
|
||||
"",
|
||||
"[general, contract, op, blackop]",
|
||||
"",
|
||||
|
||||
@@ -54,7 +54,6 @@ interface IProps {
|
||||
|
||||
export function Console(props: IProps): React.ReactElement {
|
||||
const classes = useStyles();
|
||||
const scrollHook = useRef<HTMLDivElement>(null);
|
||||
const [command, setCommand] = useState("");
|
||||
const setRerender = useState(false)[1];
|
||||
|
||||
@@ -64,22 +63,14 @@ export function Console(props: IProps): React.ReactElement {
|
||||
|
||||
const [consoleHistoryIndex, setConsoleHistoryIndex] = useState(props.bladeburner.consoleHistory.length);
|
||||
|
||||
// TODO: Figure out how to actually make the scrolling work correctly.
|
||||
function scrollToBottom(): void {
|
||||
if (!scrollHook.current) return;
|
||||
scrollHook.current.scrollTop = scrollHook.current.scrollHeight;
|
||||
}
|
||||
|
||||
function rerender(): void {
|
||||
setRerender((old) => !old);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const id = setInterval(rerender, 1000);
|
||||
const id2 = setInterval(scrollToBottom, 100);
|
||||
return () => {
|
||||
clearInterval(id);
|
||||
clearInterval(id2);
|
||||
};
|
||||
}, []);
|
||||
|
||||
@@ -113,6 +104,7 @@ export function Console(props: IProps): React.ReactElement {
|
||||
setConsoleHistoryIndex(i);
|
||||
const prevCommand = consoleHistory[i];
|
||||
event.currentTarget.value = prevCommand;
|
||||
setCommand(prevCommand);
|
||||
}
|
||||
|
||||
if (event.keyCode === 40) {
|
||||
@@ -134,39 +126,69 @@ export function Console(props: IProps): React.ReactElement {
|
||||
setConsoleHistoryIndex(consoleHistoryIndex + 1);
|
||||
const prevCommand = consoleHistory[consoleHistoryIndex + 1];
|
||||
event.currentTarget.value = prevCommand;
|
||||
setCommand(prevCommand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Box height={"60vh"} display={"flex"} alignItems={"stretch"} component={Paper}>
|
||||
<Box>
|
||||
<List sx={{ height: "100%", overflow: "auto" }}>
|
||||
{props.bladeburner.consoleLogs.map((log: any, i: number) => (
|
||||
<Line key={i} content={log} />
|
||||
))}
|
||||
<TextField
|
||||
classes={{ root: classes.textfield }}
|
||||
autoFocus
|
||||
tabIndex={1}
|
||||
type="text"
|
||||
value={command}
|
||||
onChange={handleCommandChange}
|
||||
onKeyDown={handleKeyDown}
|
||||
InputProps={{
|
||||
// for players to hook in
|
||||
className: classes.input,
|
||||
startAdornment: (
|
||||
<>
|
||||
<Typography>> </Typography>
|
||||
</>
|
||||
),
|
||||
spellCheck: false,
|
||||
}}
|
||||
/>
|
||||
</List>
|
||||
<div ref={scrollHook}></div>
|
||||
<Paper>
|
||||
<Box sx={{
|
||||
height: '60vh',
|
||||
paddingBottom: '8px',
|
||||
display: 'flex',
|
||||
alignItems: 'stretch',
|
||||
whiteSpace: 'pre-wrap',
|
||||
}}>
|
||||
<Box>
|
||||
<Logs entries={[...props.bladeburner.consoleLogs]} />
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
<TextField
|
||||
classes={{ root: classes.textfield }}
|
||||
autoFocus
|
||||
tabIndex={1}
|
||||
type="text"
|
||||
value={command}
|
||||
onChange={handleCommandChange}
|
||||
onKeyDown={handleKeyDown}
|
||||
InputProps={{
|
||||
// for players to hook in
|
||||
className: classes.input,
|
||||
startAdornment: (
|
||||
<>
|
||||
<Typography>> </Typography>
|
||||
</>
|
||||
),
|
||||
spellCheck: false,
|
||||
}}
|
||||
/>
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
|
||||
interface ILogProps {
|
||||
entries: string[];
|
||||
}
|
||||
|
||||
function Logs({entries}: ILogProps): React.ReactElement {
|
||||
const scrollHook = useRef<HTMLUListElement>(null);
|
||||
|
||||
// TODO: Text gets shifted up as new entries appear, if the user scrolled up it should attempt to keep the text focused
|
||||
function scrollToBottom(): void {
|
||||
if (!scrollHook.current) return;
|
||||
scrollHook.current.scrollTop = scrollHook.current.scrollHeight;
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
scrollToBottom();
|
||||
}, [entries]);
|
||||
|
||||
return (
|
||||
<List sx={{ height: "100%", overflow: "auto", p: 1 }} ref={scrollHook}>
|
||||
{entries && entries.map((log: any, i: number) => (
|
||||
<Line key={i} content={log} />
|
||||
))}
|
||||
</List>
|
||||
);
|
||||
}
|
||||
|
||||
166
src/Constants.ts
166
src/Constants.ts
@@ -112,7 +112,7 @@ export const CONSTANTS: {
|
||||
LatestUpdate: string;
|
||||
} = {
|
||||
VersionString: "1.2.0",
|
||||
VersionNumber: 7,
|
||||
VersionNumber: 9,
|
||||
|
||||
// Speed (in ms) at which the main loop is updated
|
||||
_idleSpeed: 200,
|
||||
@@ -273,103 +273,89 @@ export const CONSTANTS: {
|
||||
TotalNumBitNodes: 24,
|
||||
|
||||
LatestUpdate: `
|
||||
v1.1.0 - 2021-12-18 You guys are awesome (community because they're god damn awesome)
|
||||
-------------------------------------------------------------------------------------
|
||||
v1.3.0 - 2022-01-04 Cleaning up
|
||||
-------------------------------
|
||||
|
||||
** Script Editor **
|
||||
** External IDE integration **
|
||||
|
||||
* The Steam version has a webserver that allows integration with external IDEs.
|
||||
A VSCode extension is available on the market place. (The documentation for the ext. isn't
|
||||
written yet)
|
||||
|
||||
** Source-Files **
|
||||
|
||||
* The text editor can open several files at once. (@Rez855 / @Shadow72)
|
||||
It's not perfect so keep the feedback coming.
|
||||
* SF4 has been reworked.
|
||||
* New SF -1.
|
||||
|
||||
** Steam **
|
||||
** UI **
|
||||
|
||||
* Windows has a new launch option that lets player start with killing all their scripts
|
||||
This is a safety net in case all the other safety nets fail.
|
||||
* Linux has several launch options that use different flags for different OS.
|
||||
* Debug and Fullscreen are available in the window utility bar.
|
||||
* Tried (and maybe failed) to make the game completely kill itself after closing.
|
||||
This one I still don't know wtf is going.
|
||||
* No longer has background throttling.
|
||||
* Default color should be pitch black when loading
|
||||
* Add BN13: Challenge achievement.
|
||||
* Fix some edge case with skill bat tooltips (@MartinFournier)
|
||||
* Made some background match theme color (@Kejikus)
|
||||
* Fix problem with script editor height not adjusting correctly (@billyvg)
|
||||
* Fix some formatting issues with Bladeburner (@MartinFournier, @nickofolas)
|
||||
* Fix some functions like 'alert' format messages better (@MageKing17)
|
||||
* Many community themes added.
|
||||
* New script editor theme (@Hedrauta, @Dexalt142)
|
||||
* Improvements to tail windows (@theit8514)
|
||||
* Training is more consise (@mikomyazaki)
|
||||
* Fix Investopedia not displaying properly (@JotaroS)
|
||||
* Remove alpha from theme editor (@MartinFournier)
|
||||
* Fix corporation tooltip not displaying properly (@MartinFournier)
|
||||
* Add tooltip on backdoored location names (@MartinFournier)
|
||||
* Allow toasts to be dismissed by clicking them (@nickofolas)
|
||||
* Darkweb item listing now shows what you own. (@hexnaught)
|
||||
|
||||
** Tutorial **
|
||||
** Bug fix **
|
||||
|
||||
* I watched someone play bitburner on youtube and reworked part of
|
||||
the tutorial to try to make some parts of the game clearer.
|
||||
https://www.youtube.com/watch?v=-_JETXff4Zo
|
||||
* Add option to restart tutorial.
|
||||
|
||||
** Netscript **
|
||||
|
||||
* getGangInformation returns more information.
|
||||
* getAscensionResult added
|
||||
* getMemberInformation returns more info
|
||||
* Formulas API has new functions for gang.
|
||||
* Added documentation for corp API.
|
||||
* exec has clearer error message when you send invalid data.
|
||||
* getServer returns all defined field for hacknet servers.
|
||||
* Fix a bug with scp multiple files (@theit8514)
|
||||
* Stack traces should be smarter at replacing blobs with filenames
|
||||
* Fix a weird error message that would occur when throwing raw strings.
|
||||
* Fix shortcuts not working.
|
||||
* Re-added setFocus and isFocused (@theit8514)
|
||||
* new function getHashUpgrades (@MartinFournier)
|
||||
* enableLog accepts "ALL" like disableLog (@wynro)
|
||||
* toast() doesn't crash on invalid data (@ivanjermakov)
|
||||
* alert() doesn't crash on invalid data (@Siern)
|
||||
* Fixed an issue where scripts don't run where they should.
|
||||
* Sleeve getInformation now returns cha
|
||||
* getServer does work with no argument now
|
||||
* workForFaction returns false when it mistakenly returned null
|
||||
|
||||
** Character Overview **
|
||||
|
||||
* The character overview now shows the amount of exp needed to next level (@MartinFournier)
|
||||
* Fix unit tests (@MartinFournier)
|
||||
* Fixed issue with 'cat' and 'read' not finding foldered files (@Nick-Colclasure)
|
||||
* Buying on the dark web will remove incomplete exe (@hexnaught)
|
||||
* Fix bug that would cause the game to crash trying to go to a job without a job (@hexnaught)
|
||||
* purchaseServer validation (@nickofolas)
|
||||
* Script Editor focuses code when changing tab (@MartinFournier)
|
||||
* Fix script editor for .txt files (@65-7a)
|
||||
* Fix 'buy' command not displaying correctly. (@hexnaught)
|
||||
* Fix hackAnalyzeThread returning NaN (@mikomyazaki)
|
||||
* Electron handles exceptions better (@MageKing17)
|
||||
* Electron will handle 'unresponsive' event and present the opportunity to reload the game with no scripts (@MartinFournier)
|
||||
* Fix 'cp' between folders (@theit8514)
|
||||
* Fix throwing null/undefined errors (@nickofolas)
|
||||
* Allow shortcuts to work when unfocused (@MageKing17)
|
||||
* Fix some dependency issue (@locriacyber)
|
||||
* Fix corporation state returning an object instead of a string (@antonvmironov)
|
||||
* Fix 'mv' overwriting files (@theit8514)
|
||||
* Fix joesguns not being influenced by hack/grow (@dou867, @MartinFournier)
|
||||
* Added warning when opening external links. (@MartinFournier)
|
||||
* Prevent applying for positions that aren't offered (@TheMas3212)
|
||||
* Import has validation (@MartinFournier)
|
||||
|
||||
** Misc. **
|
||||
|
||||
* Add option to supress Game Saved! toasts (@MartinFournier)
|
||||
* Fix bug where ctrl+alt+j was eaten by the wrong process. (@billyvg)
|
||||
* Theme Editor lets you paste colors (@MartinFournier)
|
||||
* ctrl + u/k/w should work on terminal (@billyvg)
|
||||
* Game now shows commit number, this is mostly for me. (@MartinFourier)
|
||||
* running a bad script will give a clearer error message (@TheCoderJT)
|
||||
* Default terminal capacity is maximum (@SayntGarmo)
|
||||
* Fix problems with cp and mv (@theit8514)
|
||||
* Make monaco load fully offline for players behind firewalls.
|
||||
* change beginer guide to use n00dles instead of foodnstuff
|
||||
* BN13 is harder
|
||||
* nerf int gain from manualHack
|
||||
* Fix UI displaying wrong stats (@DJMatch3000)
|
||||
* Fix button not disabling as it should.
|
||||
* New location in Ishima.
|
||||
* Add setting to suppress stock market popups.
|
||||
* Typo fixes (@Hedrauta, @cvr-119, @Ationi, @millennIumAMbiguity
|
||||
@TealKoi, @TheCoderJT, @cblte, @2PacIsAlive, @MageKing17,
|
||||
@Xynrati, @Adraxas, @pobiega)
|
||||
* Fix 100% territory achievement.
|
||||
* Reword message on active scripts page.
|
||||
* Fix terminal not clearing after BN
|
||||
* Remove references to .fconf
|
||||
* Augmentation pages shows BN difficulty with SF5
|
||||
* Fix scripts saving on wrong server while 'connect'ing
|
||||
* Fix gym discount not working.
|
||||
* Fix scan-analyze not working with timestamps
|
||||
* Hash upgrades remember last choice.
|
||||
* Save files now sort by date
|
||||
* The covenant no longer supports negative memory purchases
|
||||
* Fix corp shares buyback triggering by pressing enter
|
||||
* Staneks gift display avg / num charges
|
||||
* Infiltration rewards no longer decay with better stats
|
||||
* terminal 'true' is parsed as boolean not string
|
||||
* tail and kill use autocomplete()
|
||||
* Fix focus for coding contract
|
||||
* massive boost to noodle bar.
|
||||
|
||||
** Special Thanks **
|
||||
|
||||
* Special thank you to everyone on Discord who can answer
|
||||
new player questions so I can focus on more important things.
|
||||
* Added vim mode to script editor (@billyvg)
|
||||
* Clean up script editor code (@Rez855)
|
||||
* 'cat' works on scripts (@65-7a)
|
||||
* Add wordWrap for Monaco (@MartinFournier)
|
||||
* Include map bundles in electron for easier debugging (@MartinFournier)
|
||||
* Fix importing very large files (@MartinFournier)
|
||||
* Cache program blob, reducing ram usage of the game (@theit8514)
|
||||
* Dev menu can set server to $0 (@mikomyazaki)
|
||||
* 'backdoor' allows direct connect (@mikomyazaki)
|
||||
* Github workflow work (@MartinFournier)
|
||||
* workForFaction / workForCompany have a new parameter (@theit8514)
|
||||
* Alias accept single quotes (@sporkwitch, @FaintSpeaker)
|
||||
* Add grep options to 'ps' (@maxtimum)
|
||||
* Added buy all option to 'buy' (@anthonydroberts)
|
||||
* Added more shortcuts to terminal input (@Frank-py)
|
||||
* Refactor some port code (@ErzengelLichtes)
|
||||
* Settings to control GiB vs GB (@ErzengelLichtes)
|
||||
* Add electron option to export save game (@MartinFournier)
|
||||
* Electron improvements (@MartinFournier)
|
||||
* Expose some notifications functions to electron (@MartinFournier)
|
||||
* Documentation (@MartinFournier, @cyn, @millennIumAMbiguity, @2PacIsAlive,
|
||||
@TheCoderJT, @hexnaught, @sschmidTU, @FOLLGAD, @Hedrauta, @Xynrati,
|
||||
@mikomyazaki, @Icehawk78, @aaronransley, @TheMas3212, @Hedrauta, @alkemann,
|
||||
@ReeseJones, @amclark42, @thadguidry, @jasonhaxstuff, @pan-kuleczka, @jhollowe,
|
||||
@ApatheticsAnonymous, @erplsf, @daanflore, @nickofolas, @Kebap, @smolgumball,
|
||||
@woody-lam-cwl)
|
||||
`,
|
||||
};
|
||||
|
||||
@@ -108,35 +108,32 @@ function WarehouseRoot(props: IProps): React.ReactElement {
|
||||
}
|
||||
}
|
||||
|
||||
let breakdown = <></>;
|
||||
const breakdownItems: JSX.Element[] = [];
|
||||
for (const matName in props.warehouse.materials) {
|
||||
const mat = props.warehouse.materials[matName];
|
||||
if (!MaterialSizes.hasOwnProperty(matName)) continue;
|
||||
if (mat.qty === 0) continue;
|
||||
breakdown = (
|
||||
<>
|
||||
{breakdown}
|
||||
{matName}: {numeralWrapper.format(mat.qty * MaterialSizes[matName], "0,0.0")}
|
||||
<br />
|
||||
</>
|
||||
);
|
||||
breakdownItems.push(<>{matName}: {numeralWrapper.format(mat.qty * MaterialSizes[matName], "0,0.0")}</>);
|
||||
}
|
||||
|
||||
for (const prodName in division.products) {
|
||||
const prod = division.products[prodName];
|
||||
if (prod === undefined) continue;
|
||||
breakdown = (
|
||||
<>
|
||||
{breakdown}
|
||||
{prodName}: {numeralWrapper.format(prod.data[props.warehouse.loc][0] * prod.siz, "0,0.0")}
|
||||
</>
|
||||
);
|
||||
breakdownItems.push(<>{prodName}: {numeralWrapper.format(prod.data[props.warehouse.loc][0] * prod.siz, "0,0.0")}</>);
|
||||
}
|
||||
|
||||
let breakdown;
|
||||
if (breakdownItems && breakdownItems.length > 0) {
|
||||
breakdown = breakdownItems.reduce(
|
||||
(previous: JSX.Element, current: JSX.Element): JSX.Element => previous && <>{previous}<br />{current}</> || <>{current}</>);
|
||||
} else {
|
||||
breakdown = <>No items in storage.</>
|
||||
}
|
||||
|
||||
return (
|
||||
<Paper>
|
||||
<Box display="flex" alignItems="center">
|
||||
<Tooltip title={props.warehouse.sizeUsed !== 0 ? <Typography>{breakdown}</Typography> : ""}>
|
||||
<Tooltip title={props.warehouse.sizeUsed !== 0 ? <Typography><>{breakdown}</></Typography> : ""}>
|
||||
<Typography color={props.warehouse.sizeUsed >= props.warehouse.size ? "error" : "primary"}>
|
||||
Storage: {numeralWrapper.formatBigNumber(props.warehouse.sizeUsed)} /{" "}
|
||||
{numeralWrapper.formatBigNumber(props.warehouse.size)}
|
||||
|
||||
@@ -4,7 +4,9 @@ import { DarkWebItems } from "./DarkWebItems";
|
||||
import { Player } from "../Player";
|
||||
import { Terminal } from "../Terminal";
|
||||
import { SpecialServers } from "../Server/data/SpecialServers";
|
||||
import { numeralWrapper } from "../ui/numeralFormat";
|
||||
import { Money } from "../ui/React/Money";
|
||||
import { DarkWebItem } from "./DarkWebItem";
|
||||
|
||||
//Posts a "help" message if connected to DarkWeb
|
||||
export function checkIfConnectedToDarkweb(): void {
|
||||
@@ -12,8 +14,8 @@ export function checkIfConnectedToDarkweb(): void {
|
||||
if (server !== null && SpecialServers.DarkWeb == server.hostname) {
|
||||
Terminal.print(
|
||||
"You are now connected to the dark web. From the dark web you can purchase illegal items. " +
|
||||
"Use the 'buy -l' command to display a list of all the items you can buy. Use 'buy [item-name] " +
|
||||
"to purchase an item.",
|
||||
"Use the 'buy -l' command to display a list of all the items you can buy. Use 'buy [item-name]' " +
|
||||
"to purchase an item. Use the 'buy -a' command to purchase unowned all items.",
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -21,9 +23,16 @@ export function checkIfConnectedToDarkweb(): void {
|
||||
export function listAllDarkwebItems(): void {
|
||||
for (const key in DarkWebItems) {
|
||||
const item = DarkWebItems[key];
|
||||
|
||||
const cost = Player.getHomeComputer().programs.includes(item.program) ? (
|
||||
<span style={{ color: `green` }}>[OWNED]</span>
|
||||
) : (
|
||||
<Money money={item.price} />
|
||||
);
|
||||
|
||||
Terminal.printRaw(
|
||||
<>
|
||||
{item.program} - <Money money={item.price} /> - {item.description}
|
||||
<span>{item.program}</span> - <span>{cost}</span> - <span>{item.description}</span>
|
||||
</>,
|
||||
);
|
||||
}
|
||||
@@ -33,7 +42,8 @@ export function buyDarkwebItem(itemName: string): void {
|
||||
itemName = itemName.toLowerCase();
|
||||
|
||||
// find the program that matches, if any
|
||||
let item = null;
|
||||
let item: DarkWebItem | null = null;
|
||||
|
||||
for (const key in DarkWebItems) {
|
||||
const i = DarkWebItems[key];
|
||||
if (i.program.toLowerCase() == itemName) {
|
||||
@@ -61,8 +71,47 @@ export function buyDarkwebItem(itemName: string): void {
|
||||
|
||||
// buy and push
|
||||
Player.loseMoney(item.price, "other");
|
||||
|
||||
const programsRef = Player.getHomeComputer().programs;
|
||||
// Remove partially created program if there is one
|
||||
const existingPartialExeIndex = programsRef.findIndex(
|
||||
(program) => item?.program && program.startsWith(item?.program),
|
||||
);
|
||||
// findIndex returns -1 if there is no match, we only want to splice on a match
|
||||
if (existingPartialExeIndex > -1) {
|
||||
programsRef.splice(existingPartialExeIndex, 1);
|
||||
}
|
||||
// Add the newly bought, full .exe
|
||||
Player.getHomeComputer().programs.push(item.program);
|
||||
|
||||
Terminal.print(
|
||||
"You have purchased the " + item.program + " program. The new program can be found on your home computer.",
|
||||
);
|
||||
}
|
||||
|
||||
export function buyAllDarkwebItems(): void {
|
||||
const itemsToBuy: DarkWebItem[] = [];
|
||||
let cost = 0;
|
||||
|
||||
for (const key in DarkWebItems) {
|
||||
const item = DarkWebItems[key];
|
||||
if (!Player.hasProgram(item.program)) {
|
||||
itemsToBuy.push(item);
|
||||
cost += item.price;
|
||||
}
|
||||
}
|
||||
|
||||
if (itemsToBuy.length === 0) {
|
||||
Terminal.print("All available programs have been purchased already.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (cost > Player.money) {
|
||||
Terminal.error("Not enough money to purchase remaining programs, " + numeralWrapper.formatMoney(cost) + " required");
|
||||
return;
|
||||
}
|
||||
|
||||
for (const item of itemsToBuy) {
|
||||
buyDarkwebItem(item.program);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { IEngine } from "./IEngine";
|
||||
import { IRouter } from "./ui/Router";
|
||||
import { AugmentationNames } from "./Augmentation/data/AugmentationNames";
|
||||
|
||||
import React from "react";
|
||||
import React, { useEffect } from "react";
|
||||
|
||||
import { General } from "./DevMenu/ui/General";
|
||||
import { Stats } from "./DevMenu/ui/Stats";
|
||||
@@ -23,6 +23,7 @@ import { Sleeves } from "./DevMenu/ui/Sleeves";
|
||||
import { Stanek } from "./DevMenu/ui/Stanek";
|
||||
import { TimeSkip } from "./DevMenu/ui/TimeSkip";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import { Exploit } from "./Exploits/Exploit";
|
||||
|
||||
interface IProps {
|
||||
player: IPlayer;
|
||||
@@ -31,6 +32,9 @@ interface IProps {
|
||||
}
|
||||
|
||||
export function DevMenuRoot(props: IProps): React.ReactElement {
|
||||
useEffect(() => {
|
||||
props.player.giveExploit(Exploit.YoureNotMeantToAccessThis);
|
||||
}, []);
|
||||
return (
|
||||
<>
|
||||
<Typography>Development Menu - Only meant to be used for testing/debugging</Typography>
|
||||
|
||||
@@ -71,6 +71,20 @@ export function Servers(): React.ReactElement {
|
||||
}
|
||||
}
|
||||
|
||||
function minMoney(): void {
|
||||
const s = GetServer(server);
|
||||
if (s === null) return;
|
||||
if (!(s instanceof Server)) return;
|
||||
s.moneyAvailable = 0;
|
||||
}
|
||||
|
||||
function minAllMoney(): void {
|
||||
for (const s of GetAllServers()) {
|
||||
if (!(s instanceof Server)) return;
|
||||
s.moneyAvailable = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Accordion TransitionProps={{ unmountOnExit: true }}>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||||
@@ -119,6 +133,12 @@ export function Servers(): React.ReactElement {
|
||||
<td>
|
||||
<Typography>Money:</Typography>
|
||||
</td>
|
||||
<td>
|
||||
<Button onClick={minMoney}>Min one</Button>
|
||||
</td>
|
||||
<td>
|
||||
<Button onClick={minAllMoney}>Min all</Button>
|
||||
</td>
|
||||
<td>
|
||||
<Button onClick={maxMoney}>Max one</Button>
|
||||
</td>
|
||||
|
||||
@@ -14,11 +14,17 @@ import { HacknetServer } from "./Hacknet/HacknetServer";
|
||||
import { CityName } from "./Locations/data/CityNames";
|
||||
import { Player } from "./Player";
|
||||
import { Programs } from "./Programs/Programs";
|
||||
import { isScriptFilename } from "./Script/isScriptFilename";
|
||||
import { Script } from "./Script/Script";
|
||||
import { GetAllServers, GetServer } from "./Server/AllServers";
|
||||
import { SpecialServers } from "./Server/data/SpecialServers";
|
||||
import { Server } from "./Server/Server";
|
||||
import { Router } from "./ui/GameRoot";
|
||||
import { Page } from "./ui/Router";
|
||||
import { removeLeadingSlash } from "./Terminal/DirectoryHelpers";
|
||||
import { Terminal } from "./Terminal";
|
||||
import { SnackbarEvents } from "./ui/React/Snackbar";
|
||||
import { IMap } from "./types";
|
||||
|
||||
interface Achievement {
|
||||
ID: string;
|
||||
@@ -32,6 +38,7 @@ function bitNodeFinishedState(): boolean {
|
||||
return Player.bladeburner !== null && Player.bladeburner.blackops.hasOwnProperty("Operation Daedalus");
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
function sfAchievement(): Achievement[] {
|
||||
const achs: Achievement[] = [];
|
||||
for (let i = 0; i <= 11; i++) {
|
||||
@@ -232,7 +239,8 @@ const achievements: Achievement[] = [
|
||||
{
|
||||
ID: "BLADEBURNER_OVERCLOCK",
|
||||
Condition: () =>
|
||||
Player.bladeburner !== null && Player.bladeburner.skills[SkillNames.Overclock] === Skills[SkillNames.Overclock],
|
||||
Player.bladeburner !== null &&
|
||||
Player.bladeburner.skills[SkillNames.Overclock] === Skills[SkillNames.Overclock].maxLvl,
|
||||
},
|
||||
{
|
||||
ID: "BLADEBURNER_UNSPENT_100000",
|
||||
@@ -249,12 +257,14 @@ const achievements: Achievement[] = [
|
||||
Condition: () => {
|
||||
if (!hasHacknetServers(Player)) return false;
|
||||
for (const h of Player.hacknetNodes) {
|
||||
if (!(h instanceof HacknetServer)) return false;
|
||||
if (typeof h !== "string") return false;
|
||||
const hs = GetServer(h);
|
||||
if (!(hs instanceof HacknetServer)) return false;
|
||||
if (
|
||||
h.maxRam === HacknetServerConstants.MaxRam &&
|
||||
h.cores === HacknetServerConstants.MaxCores &&
|
||||
h.level === HacknetServerConstants.MaxLevel &&
|
||||
h.cache === HacknetServerConstants.MaxCache
|
||||
hs.maxRam === HacknetServerConstants.MaxRam &&
|
||||
hs.cores === HacknetServerConstants.MaxCores &&
|
||||
hs.level === HacknetServerConstants.MaxLevel &&
|
||||
hs.cache === HacknetServerConstants.MaxCache
|
||||
)
|
||||
return true;
|
||||
}
|
||||
@@ -293,7 +303,7 @@ const achievements: Achievement[] = [
|
||||
Condition: () =>
|
||||
Player.bitNodeN === 1 &&
|
||||
bitNodeFinishedState() &&
|
||||
Player.getHomeComputer().maxRam <= 32 &&
|
||||
Player.getHomeComputer().maxRam <= 128 &&
|
||||
Player.getHomeComputer().cpuCores === 1,
|
||||
},
|
||||
{
|
||||
@@ -407,6 +417,64 @@ function calculateAchievements(): void {
|
||||
}
|
||||
|
||||
export function initElectron(): void {
|
||||
setAchievements([]);
|
||||
setInterval(calculateAchievements, 5000);
|
||||
const userAgent = navigator.userAgent.toLowerCase();
|
||||
if (userAgent.indexOf(" electron/") > -1) {
|
||||
// Electron-specific code
|
||||
setAchievements([]);
|
||||
initWebserver();
|
||||
setInterval(calculateAchievements, 5000);
|
||||
initAppNotifier();
|
||||
}
|
||||
}
|
||||
|
||||
function initWebserver(): void {
|
||||
(document as any).saveFile = function (filename: string, code: string): string {
|
||||
if (removeLeadingSlash(filename).includes("/")) {
|
||||
filename = "/" + removeLeadingSlash(filename);
|
||||
}
|
||||
code = Buffer.from(code, "base64").toString();
|
||||
const home = GetServer("home");
|
||||
if (home === null) return "'home' server not found.";
|
||||
if (isScriptFilename(filename)) {
|
||||
//If the current script already exists on the server, overwrite it
|
||||
for (let i = 0; i < home.scripts.length; i++) {
|
||||
if (filename == home.scripts[i].filename) {
|
||||
home.scripts[i].saveScript(Player, filename, code, "home", home.scripts);
|
||||
return "written";
|
||||
}
|
||||
}
|
||||
|
||||
//If the current script does NOT exist, create a new one
|
||||
const script = new Script();
|
||||
script.saveScript(Player, filename, code, "home", home.scripts);
|
||||
home.scripts.push(script);
|
||||
return "written";
|
||||
}
|
||||
|
||||
return "not a script file";
|
||||
};
|
||||
}
|
||||
|
||||
// Expose certain alert functions to allow the wrapper to sends message to the game
|
||||
function initAppNotifier(): void {
|
||||
const funcs = {
|
||||
terminal: (message: string, type?: string) => {
|
||||
const typesFn: IMap<(s: string) => void> = {
|
||||
info: Terminal.info,
|
||||
warn: Terminal.warn,
|
||||
error: Terminal.error,
|
||||
success: Terminal.success,
|
||||
};
|
||||
let fn;
|
||||
if (type) fn = typesFn[type];
|
||||
if (!fn) fn = Terminal.print;
|
||||
fn.bind(Terminal)(message);
|
||||
},
|
||||
toast: (message: string, type: "info" | "success" | "warning" | "error", duration = 2000) =>
|
||||
SnackbarEvents.emit(message, type, duration),
|
||||
};
|
||||
|
||||
// Will be consumud by the electron wrapper.
|
||||
// @ts-ignore
|
||||
window.appNotifier = funcs;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ export enum Exploit {
|
||||
TimeCompression = "TimeCompression",
|
||||
RealityAlteration = "RealityAlteration",
|
||||
N00dles = "N00dles",
|
||||
YoureNotMeantToAccessThis = "YoureNotMeantToAccessThis",
|
||||
// To the players reading this. Yes you're supposed to add EditSaveFile by
|
||||
// editing your save file, yes you could add them all, no we don't care
|
||||
// that's not the point.
|
||||
@@ -35,6 +36,7 @@ const names: {
|
||||
UndocumentedFunctionCall: "by looking beyond the documentation.",
|
||||
RealityAlteration: "by altering reality to suit your whims.",
|
||||
N00dles: "by harnessing the power of the n00dles.",
|
||||
YoureNotMeantToAccessThis: "by accessing the dev menu.",
|
||||
};
|
||||
|
||||
export function ExploitName(exploit: string): string {
|
||||
|
||||
@@ -24,9 +24,9 @@ function timeCompression(): void {
|
||||
return;
|
||||
}
|
||||
last = now;
|
||||
window.setTimeout(minute, 1000);
|
||||
window.setTimeout(minute, 1000 * 60);
|
||||
}
|
||||
window.setTimeout(minute, 1000);
|
||||
window.setTimeout(minute, 1000 * 60);
|
||||
}
|
||||
|
||||
export function startExploits(): void {
|
||||
|
||||
@@ -174,7 +174,7 @@ export function AugmentationsPage(props: IProps): React.ReactElement {
|
||||
<>
|
||||
<br />
|
||||
<Typography variant="h4">Purchased Augmentations</Typography>
|
||||
<Typography>This factions also offers these augmentations but you already own them.</Typography>
|
||||
<Typography>This faction also offers these augmentations but you already own them.</Typography>
|
||||
{owned.map((aug) => purchaseableAugmentation(aug, true))}
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -353,7 +353,7 @@ export class Gang {
|
||||
const res = member.ascend();
|
||||
this.respect = Math.max(1, this.respect - res.respect);
|
||||
if (workerScript) {
|
||||
workerScript.log("ascend", () => `Ascended Gang member ${member.name}`);
|
||||
workerScript.log("gang.ascend", () => `Ascended Gang member ${member.name}`);
|
||||
}
|
||||
return res;
|
||||
} catch (e: any) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React from "react";
|
||||
import Button from "@mui/material/Button";
|
||||
import Tooltip from "@mui/material/Tooltip";
|
||||
import Typography from "@mui/material/Typography";
|
||||
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
|
||||
@@ -38,6 +39,11 @@ export function CoresButton(props: IProps): React.ReactElement {
|
||||
}
|
||||
>
|
||||
<span>
|
||||
<br />
|
||||
<Typography>
|
||||
<i>"Cores increase the effectiveness of grow() and weaken() on 'home'"</i>
|
||||
</Typography>
|
||||
<br />
|
||||
<Button disabled={!props.p.canAfford(cost)} onClick={buy}>
|
||||
Upgrade 'home' cores ({homeComputer.cpuCores} -> {homeComputer.cpuCores + 1}) -
|
||||
<Money money={cost} player={props.p} />
|
||||
|
||||
@@ -29,6 +29,7 @@ import { GetServer } from "../../Server/AllServers";
|
||||
import { CorruptableText } from "../../ui/React/CorruptableText";
|
||||
import { use } from "../../ui/Context";
|
||||
import { serverMetadata } from "../../Server/data/servers";
|
||||
import { Tooltip } from "@mui/material";
|
||||
|
||||
type IProps = {
|
||||
loc: Location;
|
||||
@@ -92,8 +93,11 @@ export function GenericLocation({ loc }: IProps): React.ReactElement {
|
||||
return (
|
||||
<>
|
||||
<Button onClick={() => router.toCity()}>Return to World</Button>
|
||||
<Typography variant="h4">
|
||||
{backdoorInstalled && !Settings.DisableTextEffects ? <CorruptableText content={loc.name} /> : loc.name}
|
||||
<Typography variant="h4" sx={{ mt: 1 }}>
|
||||
{backdoorInstalled && !Settings.DisableTextEffects ? (
|
||||
<Tooltip title={`Backdoor installed on ${loc.name}.`}>
|
||||
<span><CorruptableText content={loc.name} /></span>
|
||||
</Tooltip>) : loc.name}
|
||||
</Typography>
|
||||
{locContent}
|
||||
</>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React from "react";
|
||||
import Button from "@mui/material/Button";
|
||||
import Tooltip from "@mui/material/Tooltip";
|
||||
import Typography from "@mui/material/Typography";
|
||||
|
||||
import { CONSTANTS } from "../../Constants";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
@@ -37,6 +38,11 @@ export function RamButton(props: IProps): React.ReactElement {
|
||||
}
|
||||
>
|
||||
<span>
|
||||
<br />
|
||||
<Typography>
|
||||
<i>"More RAM means more scripts on 'home'"</i>
|
||||
</Typography>
|
||||
<br />
|
||||
<Button disabled={!props.p.canAfford(cost)} onClick={buy}>
|
||||
Upgrade 'home' RAM ({numeralWrapper.formatRAM(homeComputer.maxRam)} ->
|
||||
{numeralWrapper.formatRAM(homeComputer.maxRam * 2)}) -
|
||||
|
||||
@@ -86,7 +86,7 @@ export function SpecialLocation(props: IProps): React.ReactElement {
|
||||
|
||||
function renderNoodleBar(): React.ReactElement {
|
||||
function EatNoodles(): void {
|
||||
SnackbarEvents.emit("You ate some delicious noodles and feel refreshed", "success");
|
||||
SnackbarEvents.emit("You ate some delicious noodles and feel refreshed", "success", 2000);
|
||||
N00dles(); // This is the true power of the noodles.
|
||||
if (player.sourceFiles.length > 0) player.giveExploit(Exploit.N00dles);
|
||||
if (player.sourceFileLvl(5) > 0 || player.bitNodeN === 5) {
|
||||
|
||||
@@ -73,7 +73,7 @@ export function TechVendorLocation(props: IProps): React.ReactElement {
|
||||
{purchaseServerButtons}
|
||||
<br />
|
||||
<Typography>
|
||||
<i>"You can order bigger servers via scripts. We don't take custom order in person."</i>
|
||||
<i>"You can order bigger servers via scripts. We don't take custom orders in person."</i>
|
||||
</Typography>
|
||||
<br />
|
||||
<TorButton p={player} rerender={rerender} />
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { IPlayer } from "src/PersonObjects/IPlayer";
|
||||
import { IMap } from "../types";
|
||||
|
||||
// TODO remember to update RamCalculations.js and WorkerScript.js
|
||||
@@ -67,6 +68,16 @@ export const RamCostConstants: IMap<number> = {
|
||||
ScriptStanekDeleteAt: 0.15,
|
||||
};
|
||||
|
||||
function SF4Cost(cost: number): (player: IPlayer) => number {
|
||||
return (player: IPlayer): number => {
|
||||
if (player.bitNodeN === 4) return cost;
|
||||
const sf4 = player.sourceFileLvl(4);
|
||||
if (sf4 <= 1) return cost * 64;
|
||||
if (sf4 === 2) return cost * 8;
|
||||
return cost;
|
||||
};
|
||||
}
|
||||
|
||||
export const RamCosts: IMap<any> = {
|
||||
hacknet: {
|
||||
numNodes: 0,
|
||||
@@ -196,55 +207,55 @@ export const RamCosts: IMap<any> = {
|
||||
getFavorToDonate: RamCostConstants.ScriptGetFavorToDonate,
|
||||
|
||||
// Singularity Functions
|
||||
universityCourse: RamCostConstants.ScriptSingularityFn1RamCost,
|
||||
gymWorkout: RamCostConstants.ScriptSingularityFn1RamCost,
|
||||
travelToCity: RamCostConstants.ScriptSingularityFn1RamCost,
|
||||
goToLocation: RamCostConstants.ScriptSingularityFn1RamCost,
|
||||
purchaseTor: RamCostConstants.ScriptSingularityFn1RamCost,
|
||||
purchaseProgram: RamCostConstants.ScriptSingularityFn1RamCost,
|
||||
getCurrentServer: RamCostConstants.ScriptSingularityFn1RamCost,
|
||||
connect: RamCostConstants.ScriptSingularityFn1RamCost,
|
||||
manualHack: RamCostConstants.ScriptSingularityFn1RamCost,
|
||||
installBackdoor: RamCostConstants.ScriptSingularityFn1RamCost,
|
||||
getStats: RamCostConstants.ScriptSingularityFn1RamCost / 4,
|
||||
getCharacterInformation: RamCostConstants.ScriptSingularityFn1RamCost / 4,
|
||||
getPlayer: RamCostConstants.ScriptSingularityFn1RamCost / 4,
|
||||
hospitalize: RamCostConstants.ScriptSingularityFn1RamCost / 4,
|
||||
isBusy: RamCostConstants.ScriptSingularityFn1RamCost / 4,
|
||||
stopAction: RamCostConstants.ScriptSingularityFn1RamCost / 2,
|
||||
upgradeHomeRam: RamCostConstants.ScriptSingularityFn2RamCost,
|
||||
upgradeHomeCores: RamCostConstants.ScriptSingularityFn2RamCost,
|
||||
getUpgradeHomeRamCost: RamCostConstants.ScriptSingularityFn2RamCost / 2,
|
||||
getUpgradeHomeCoresCost: RamCostConstants.ScriptSingularityFn2RamCost / 2,
|
||||
workForCompany: RamCostConstants.ScriptSingularityFn2RamCost,
|
||||
applyToCompany: RamCostConstants.ScriptSingularityFn2RamCost,
|
||||
getCompanyRep: RamCostConstants.ScriptSingularityFn2RamCost / 3,
|
||||
getCompanyFavor: RamCostConstants.ScriptSingularityFn2RamCost / 3,
|
||||
getCompanyFavorGain: RamCostConstants.ScriptSingularityFn2RamCost / 4,
|
||||
checkFactionInvitations: RamCostConstants.ScriptSingularityFn2RamCost,
|
||||
joinFaction: RamCostConstants.ScriptSingularityFn2RamCost,
|
||||
workForFaction: RamCostConstants.ScriptSingularityFn2RamCost,
|
||||
getFactionRep: RamCostConstants.ScriptSingularityFn2RamCost / 3,
|
||||
getFactionFavor: RamCostConstants.ScriptSingularityFn2RamCost / 3,
|
||||
getFactionFavorGain: RamCostConstants.ScriptSingularityFn2RamCost / 4,
|
||||
donateToFaction: RamCostConstants.ScriptSingularityFn3RamCost,
|
||||
createProgram: RamCostConstants.ScriptSingularityFn3RamCost,
|
||||
commitCrime: RamCostConstants.ScriptSingularityFn3RamCost,
|
||||
getCrimeChance: RamCostConstants.ScriptSingularityFn3RamCost,
|
||||
getCrimeStats: RamCostConstants.ScriptSingularityFn3RamCost,
|
||||
getOwnedAugmentations: RamCostConstants.ScriptSingularityFn3RamCost,
|
||||
getOwnedSourceFiles: RamCostConstants.ScriptSingularityFn3RamCost,
|
||||
getAugmentationsFromFaction: RamCostConstants.ScriptSingularityFn3RamCost,
|
||||
getAugmentationCost: RamCostConstants.ScriptSingularityFn3RamCost,
|
||||
getAugmentationPrereq: RamCostConstants.ScriptSingularityFn3RamCost,
|
||||
getAugmentationPrice: RamCostConstants.ScriptSingularityFn3RamCost / 2,
|
||||
getAugmentationRepReq: RamCostConstants.ScriptSingularityFn3RamCost / 2,
|
||||
getAugmentationStats: RamCostConstants.ScriptSingularityFn3RamCost,
|
||||
purchaseAugmentation: RamCostConstants.ScriptSingularityFn3RamCost,
|
||||
softReset: RamCostConstants.ScriptSingularityFn3RamCost,
|
||||
installAugmentations: RamCostConstants.ScriptSingularityFn3RamCost,
|
||||
isFocused: 0.1,
|
||||
setFocus: 0.1,
|
||||
universityCourse: SF4Cost(RamCostConstants.ScriptSingularityFn1RamCost),
|
||||
gymWorkout: SF4Cost(RamCostConstants.ScriptSingularityFn1RamCost),
|
||||
travelToCity: SF4Cost(RamCostConstants.ScriptSingularityFn1RamCost),
|
||||
goToLocation: SF4Cost(RamCostConstants.ScriptSingularityFn1RamCost),
|
||||
purchaseTor: SF4Cost(RamCostConstants.ScriptSingularityFn1RamCost),
|
||||
purchaseProgram: SF4Cost(RamCostConstants.ScriptSingularityFn1RamCost),
|
||||
getCurrentServer: SF4Cost(RamCostConstants.ScriptSingularityFn1RamCost),
|
||||
connect: SF4Cost(RamCostConstants.ScriptSingularityFn1RamCost),
|
||||
manualHack: SF4Cost(RamCostConstants.ScriptSingularityFn1RamCost),
|
||||
installBackdoor: SF4Cost(RamCostConstants.ScriptSingularityFn1RamCost),
|
||||
getStats: SF4Cost(RamCostConstants.ScriptSingularityFn1RamCost / 4),
|
||||
getCharacterInformation: SF4Cost(RamCostConstants.ScriptSingularityFn1RamCost / 4),
|
||||
getPlayer: SF4Cost(RamCostConstants.ScriptSingularityFn1RamCost / 4),
|
||||
hospitalize: SF4Cost(RamCostConstants.ScriptSingularityFn1RamCost / 4),
|
||||
isBusy: SF4Cost(RamCostConstants.ScriptSingularityFn1RamCost / 4),
|
||||
stopAction: SF4Cost(RamCostConstants.ScriptSingularityFn1RamCost / 2),
|
||||
upgradeHomeRam: SF4Cost(RamCostConstants.ScriptSingularityFn2RamCost),
|
||||
upgradeHomeCores: SF4Cost(RamCostConstants.ScriptSingularityFn2RamCost),
|
||||
getUpgradeHomeRamCost: SF4Cost(RamCostConstants.ScriptSingularityFn2RamCost / 2),
|
||||
getUpgradeHomeCoresCost: SF4Cost(RamCostConstants.ScriptSingularityFn2RamCost / 2),
|
||||
workForCompany: SF4Cost(RamCostConstants.ScriptSingularityFn2RamCost),
|
||||
applyToCompany: SF4Cost(RamCostConstants.ScriptSingularityFn2RamCost),
|
||||
getCompanyRep: SF4Cost(RamCostConstants.ScriptSingularityFn2RamCost / 3),
|
||||
getCompanyFavor: SF4Cost(RamCostConstants.ScriptSingularityFn2RamCost / 3),
|
||||
getCompanyFavorGain: SF4Cost(RamCostConstants.ScriptSingularityFn2RamCost / 4),
|
||||
checkFactionInvitations: SF4Cost(RamCostConstants.ScriptSingularityFn2RamCost),
|
||||
joinFaction: SF4Cost(RamCostConstants.ScriptSingularityFn2RamCost),
|
||||
workForFaction: SF4Cost(RamCostConstants.ScriptSingularityFn2RamCost),
|
||||
getFactionRep: SF4Cost(RamCostConstants.ScriptSingularityFn2RamCost / 3),
|
||||
getFactionFavor: SF4Cost(RamCostConstants.ScriptSingularityFn2RamCost / 3),
|
||||
getFactionFavorGain: SF4Cost(RamCostConstants.ScriptSingularityFn2RamCost / 4),
|
||||
donateToFaction: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
||||
createProgram: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
||||
commitCrime: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
||||
getCrimeChance: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
||||
getCrimeStats: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
||||
getOwnedAugmentations: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
||||
getOwnedSourceFiles: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
||||
getAugmentationsFromFaction: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
||||
getAugmentationCost: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
||||
getAugmentationPrereq: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
||||
getAugmentationPrice: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost / 2),
|
||||
getAugmentationRepReq: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost / 2),
|
||||
getAugmentationStats: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
||||
purchaseAugmentation: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
||||
softReset: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
||||
installAugmentations: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
||||
isFocused: SF4Cost(0.1),
|
||||
setFocus: SF4Cost(0.1),
|
||||
|
||||
// Gang API
|
||||
gang: {
|
||||
@@ -348,13 +359,17 @@ export const RamCosts: IMap<any> = {
|
||||
remove: RamCostConstants.ScriptStanekDeleteAt,
|
||||
},
|
||||
|
||||
ui: {
|
||||
getTheme: 0,
|
||||
},
|
||||
|
||||
heart: {
|
||||
// Easter egg function
|
||||
break: 0,
|
||||
},
|
||||
};
|
||||
|
||||
export function getRamCost(...args: string[]): number {
|
||||
export function getRamCost(player: IPlayer, ...args: string[]): number {
|
||||
if (args.length === 0) {
|
||||
console.warn(`No arguments passed to getRamCost()`);
|
||||
return 0;
|
||||
@@ -379,6 +394,10 @@ export function getRamCost(...args: string[]): number {
|
||||
return curr;
|
||||
}
|
||||
|
||||
if (typeof curr === "function") {
|
||||
return curr(player);
|
||||
}
|
||||
|
||||
console.warn(`Unexpected type (${curr}) for value [${args}]`);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { isString } from "./utils/helpers/isString";
|
||||
import { GetServer } from "./Server/AllServers";
|
||||
import { WorkerScript } from "./Netscript/WorkerScript";
|
||||
import { BlobsMap } from "./NetscriptJSEvaluator";
|
||||
|
||||
export function netscriptDelay(time: number, workerScript: WorkerScript): Promise<void> {
|
||||
return new Promise(function (resolve) {
|
||||
@@ -22,8 +21,9 @@ export function makeRuntimeRejectMsg(workerScript: WorkerScript, msg: string): s
|
||||
throw new Error(`WorkerScript constructed with invalid server ip: ${workerScript.hostname}`);
|
||||
}
|
||||
|
||||
for (const url in BlobsMap) {
|
||||
msg = msg.replace(new RegExp(url, "g"), BlobsMap[url]);
|
||||
for (const scriptUrl of workerScript.scriptRef.dependencies) {
|
||||
// Return just the original msg if it's nullish so that we don't get a workerscript error
|
||||
msg = msg?.replace(new RegExp(scriptUrl.url, "g"), scriptUrl.filename) ?? msg;
|
||||
}
|
||||
|
||||
return "|DELIMITER|" + server.hostname + "|DELIMITER|" + workerScript.name + "|DELIMITER|" + msg;
|
||||
@@ -45,7 +45,7 @@ export function resolveNetscriptRequestedThreads(
|
||||
`Invalid thread count passed to ${functionName}: ${requestedThreads}. Threads must be a positive number.`,
|
||||
);
|
||||
}
|
||||
if (requestedThreads > threads) {
|
||||
if (requestedThreadsAsInt > threads) {
|
||||
throw makeRuntimeRejectMsg(
|
||||
workerScript,
|
||||
`Too many threads requested by ${functionName}. Requested: ${requestedThreads}. Has: ${threads}.`,
|
||||
|
||||
@@ -64,12 +64,13 @@ import { NetscriptSleeve } from "./NetscriptFunctions/Sleeve";
|
||||
import { NetscriptExtra } from "./NetscriptFunctions/Extra";
|
||||
import { NetscriptHacknet } from "./NetscriptFunctions/Hacknet";
|
||||
import { NetscriptStanek } from "./NetscriptFunctions/Stanek";
|
||||
|
||||
import { NetscriptUserInterface } from "./NetscriptFunctions/UserInterface";
|
||||
import { NetscriptBladeburner } from "./NetscriptFunctions/Bladeburner";
|
||||
import { NetscriptCodingContract } from "./NetscriptFunctions/CodingContract";
|
||||
import { NetscriptCorporation } from "./NetscriptFunctions/Corporation";
|
||||
import { NetscriptFormulas } from "./NetscriptFunctions/Formulas";
|
||||
import { NetscriptStockMarket } from "./NetscriptFunctions/StockMarket";
|
||||
import { IPort } from "./NetscriptPort";
|
||||
|
||||
import {
|
||||
NS as INS,
|
||||
@@ -304,7 +305,10 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
const checkSingularityAccess = function (func: any, n: any): void {
|
||||
if (Player.bitNodeN !== 4) {
|
||||
if (SourceFileFlags[4] < n) {
|
||||
throw makeRuntimeErrorMsg(func, `This singularity function requires Source-File 4-${n} to run.`);
|
||||
throw makeRuntimeErrorMsg(
|
||||
func,
|
||||
`This singularity function requires Source-File 4-${n} to run. A power up you obtain later in the game. It will be very obvious when and how you can obtain it.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -439,6 +443,26 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
getServer: safeGetServer,
|
||||
checkSingularityAccess: checkSingularityAccess,
|
||||
hack: hack,
|
||||
getValidPort: (funcName: string, port: any): IPort => {
|
||||
if (isNaN(port)) {
|
||||
throw makeRuntimeErrorMsg(
|
||||
funcName,
|
||||
`Invalid argument. Must be a port number between 1 and ${CONSTANTS.NumNetscriptPorts}, is ${port}`,
|
||||
);
|
||||
}
|
||||
port = Math.round(port);
|
||||
if (port < 1 || port > CONSTANTS.NumNetscriptPorts) {
|
||||
throw makeRuntimeErrorMsg(
|
||||
funcName,
|
||||
`Trying to use an invalid port: ${port}. Only ports 1-${CONSTANTS.NumNetscriptPorts} are valid.`,
|
||||
);
|
||||
}
|
||||
const iport = NetscriptPorts[port - 1];
|
||||
if (iport == null || !(iport instanceof Object)) {
|
||||
throw makeRuntimeErrorMsg(funcName, `Could not find port: ${port}. This is a bug. Report to dev.`);
|
||||
}
|
||||
return iport;
|
||||
},
|
||||
};
|
||||
|
||||
const gang = NetscriptGang(Player, workerScript, helper);
|
||||
@@ -452,6 +476,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
const formulas = NetscriptFormulas(Player, workerScript, helper);
|
||||
const singularity = NetscriptSingularity(Player, workerScript, helper);
|
||||
const stockmarket = NetscriptStockMarket(Player, workerScript, helper);
|
||||
const ui = NetscriptUserInterface(Player, workerScript, helper);
|
||||
|
||||
const base: INS = {
|
||||
...singularity,
|
||||
@@ -462,7 +487,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
sleeve: sleeve,
|
||||
corporation: corporation,
|
||||
stanek: stanek,
|
||||
|
||||
ui: ui,
|
||||
formulas: formulas,
|
||||
stock: stockmarket,
|
||||
args: workerScript.args,
|
||||
@@ -470,7 +495,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
sprintf: sprintf,
|
||||
vsprintf: vsprintf,
|
||||
scan: function (hostname: any = workerScript.hostname): any {
|
||||
updateDynamicRam("scan", getRamCost("scan"));
|
||||
updateDynamicRam("scan", getRamCost(Player, "scan"));
|
||||
const server = safeGetServer(hostname, "scan");
|
||||
const out = [];
|
||||
for (let i = 0; i < server.serversOnNetwork.length; i++) {
|
||||
@@ -484,11 +509,11 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return out;
|
||||
},
|
||||
hack: function (hostname: any, { threads: requestedThreads, stock }: any = {}): any {
|
||||
updateDynamicRam("hack", getRamCost("hack"));
|
||||
updateDynamicRam("hack", getRamCost(Player, "hack"));
|
||||
return hack(hostname, false, { threads: requestedThreads, stock: stock });
|
||||
},
|
||||
hackAnalyzeThreads: function (hostname: any, hackAmount: any): any {
|
||||
updateDynamicRam("hackAnalyzeThreads", getRamCost("hackAnalyzeThreads"));
|
||||
updateDynamicRam("hackAnalyzeThreads", getRamCost(Player, "hackAnalyzeThreads"));
|
||||
|
||||
// Check argument validity
|
||||
const server = safeGetServer(hostname, "hackAnalyzeThreads");
|
||||
@@ -505,6 +530,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
|
||||
if (hackAmount < 0 || hackAmount > server.moneyAvailable) {
|
||||
return -1;
|
||||
} else if (hackAmount === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const percentHacked = calculatePercentMoneyHacked(server, Player);
|
||||
@@ -512,7 +539,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return hackAmount / Math.floor(server.moneyAvailable * percentHacked);
|
||||
},
|
||||
hackAnalyze: function (hostname: any): any {
|
||||
updateDynamicRam("hackAnalyze", getRamCost("hackAnalyze"));
|
||||
updateDynamicRam("hackAnalyze", getRamCost(Player, "hackAnalyze"));
|
||||
|
||||
const server = safeGetServer(hostname, "hackAnalyze");
|
||||
if (!(server instanceof Server)) {
|
||||
@@ -526,7 +553,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return CONSTANTS.ServerFortifyAmount * threads;
|
||||
},
|
||||
hackAnalyzeChance: function (hostname: any): any {
|
||||
updateDynamicRam("hackAnalyzeChance", getRamCost("hackAnalyzeChance"));
|
||||
updateDynamicRam("hackAnalyzeChance", getRamCost(Player, "hackAnalyzeChance"));
|
||||
|
||||
const server = safeGetServer(hostname, "hackAnalyzeChance");
|
||||
if (!(server instanceof Server)) {
|
||||
@@ -555,7 +582,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
});
|
||||
},
|
||||
grow: function (hostname: any, { threads: requestedThreads, stock }: any = {}): any {
|
||||
updateDynamicRam("grow", getRamCost("grow"));
|
||||
updateDynamicRam("grow", getRamCost(Player, "grow"));
|
||||
const threads = resolveNetscriptRequestedThreads(workerScript, "grow", requestedThreads);
|
||||
if (hostname === undefined) {
|
||||
throw makeRuntimeErrorMsg("grow", "Takes 1 argument.");
|
||||
@@ -613,7 +640,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
});
|
||||
},
|
||||
growthAnalyze: function (hostname: any, growth: any, cores: any = 1): any {
|
||||
updateDynamicRam("growthAnalyze", getRamCost("growthAnalyze"));
|
||||
updateDynamicRam("growthAnalyze", getRamCost(Player, "growthAnalyze"));
|
||||
|
||||
// Check argument validity
|
||||
const server = safeGetServer(hostname, "growthAnalyze");
|
||||
@@ -631,7 +658,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return 2 * CONSTANTS.ServerFortifyAmount * threads;
|
||||
},
|
||||
weaken: function (hostname: any, { threads: requestedThreads }: any = {}): any {
|
||||
updateDynamicRam("weaken", getRamCost("weaken"));
|
||||
updateDynamicRam("weaken", getRamCost(Player, "weaken"));
|
||||
const threads = resolveNetscriptRequestedThreads(workerScript, "weaken", requestedThreads);
|
||||
if (hostname === undefined) {
|
||||
throw makeRuntimeErrorMsg("weaken", "Takes 1 argument.");
|
||||
@@ -797,7 +824,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
LogBoxEvents.emit(runningScriptObj);
|
||||
},
|
||||
nuke: function (hostname: any): boolean {
|
||||
updateDynamicRam("nuke", getRamCost("nuke"));
|
||||
updateDynamicRam("nuke", getRamCost(Player, "nuke"));
|
||||
if (hostname === undefined) {
|
||||
throw makeRuntimeErrorMsg("nuke", "Takes 1 argument.");
|
||||
}
|
||||
@@ -806,22 +833,22 @@ 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 {
|
||||
updateDynamicRam("brutessh", getRamCost("brutessh"));
|
||||
updateDynamicRam("brutessh", getRamCost(Player, "brutessh"));
|
||||
if (hostname === undefined) {
|
||||
throw makeRuntimeErrorMsg("brutessh", "Takes 1 argument.");
|
||||
}
|
||||
@@ -843,7 +870,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return true;
|
||||
},
|
||||
ftpcrack: function (hostname: any): boolean {
|
||||
updateDynamicRam("ftpcrack", getRamCost("ftpcrack"));
|
||||
updateDynamicRam("ftpcrack", getRamCost(Player, "ftpcrack"));
|
||||
if (hostname === undefined) {
|
||||
throw makeRuntimeErrorMsg("ftpcrack", "Takes 1 argument.");
|
||||
}
|
||||
@@ -865,7 +892,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return true;
|
||||
},
|
||||
relaysmtp: function (hostname: any): boolean {
|
||||
updateDynamicRam("relaysmtp", getRamCost("relaysmtp"));
|
||||
updateDynamicRam("relaysmtp", getRamCost(Player, "relaysmtp"));
|
||||
if (hostname === undefined) {
|
||||
throw makeRuntimeErrorMsg("relaysmtp", "Takes 1 argument.");
|
||||
}
|
||||
@@ -887,7 +914,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return true;
|
||||
},
|
||||
httpworm: function (hostname: any): boolean {
|
||||
updateDynamicRam("httpworm", getRamCost("httpworm"));
|
||||
updateDynamicRam("httpworm", getRamCost(Player, "httpworm"));
|
||||
if (hostname === undefined) {
|
||||
throw makeRuntimeErrorMsg("httpworm", "Takes 1 argument");
|
||||
}
|
||||
@@ -909,7 +936,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return true;
|
||||
},
|
||||
sqlinject: function (hostname: any): boolean {
|
||||
updateDynamicRam("sqlinject", getRamCost("sqlinject"));
|
||||
updateDynamicRam("sqlinject", getRamCost(Player, "sqlinject"));
|
||||
if (hostname === undefined) {
|
||||
throw makeRuntimeErrorMsg("sqlinject", "Takes 1 argument.");
|
||||
}
|
||||
@@ -931,7 +958,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return true;
|
||||
},
|
||||
run: function (scriptname: any, threads: any = 1, ...args: any[]): any {
|
||||
updateDynamicRam("run", getRamCost("run"));
|
||||
updateDynamicRam("run", getRamCost(Player, "run"));
|
||||
if (scriptname === undefined) {
|
||||
throw makeRuntimeErrorMsg("run", "Usage: run(scriptname, [numThreads], [arg1], [arg2]...)");
|
||||
}
|
||||
@@ -943,11 +970,10 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
throw makeRuntimeErrorMsg("run", "Could not find server. This is a bug. Report to dev.");
|
||||
}
|
||||
|
||||
return runScriptFromScript("run", scriptServer, scriptname, args, workerScript, threads);
|
||||
return runScriptFromScript(Player, "run", scriptServer, scriptname, args, workerScript, threads);
|
||||
},
|
||||
exec: function (scriptname: any, hostname: any, threads: any = 1, ...args: any[]): any {
|
||||
console.log(`${scriptname} ${hostname} ${threads} ${JSON.stringify(args)}`);
|
||||
updateDynamicRam("exec", getRamCost("exec"));
|
||||
updateDynamicRam("exec", getRamCost(Player, "exec"));
|
||||
if (scriptname === undefined || hostname === undefined) {
|
||||
throw makeRuntimeErrorMsg("exec", "Usage: exec(scriptname, server, [numThreads], [arg1], [arg2]...)");
|
||||
}
|
||||
@@ -955,10 +981,10 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
throw makeRuntimeErrorMsg("exec", `Invalid thread count. Must be numeric and > 0, is ${threads}`);
|
||||
}
|
||||
const server = safeGetServer(hostname, "exec");
|
||||
return runScriptFromScript("exec", server, scriptname, args, workerScript, threads);
|
||||
return runScriptFromScript(Player, "exec", server, scriptname, args, workerScript, threads);
|
||||
},
|
||||
spawn: function (scriptname: any, threads: any = 1, ...args: any[]): any {
|
||||
updateDynamicRam("spawn", getRamCost("spawn"));
|
||||
updateDynamicRam("spawn", getRamCost(Player, "spawn"));
|
||||
if (!scriptname || !threads) {
|
||||
throw makeRuntimeErrorMsg("spawn", "Usage: spawn(scriptname, threads)");
|
||||
}
|
||||
@@ -973,7 +999,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
throw makeRuntimeErrorMsg("spawn", "Could not find server. This is a bug. Report to dev");
|
||||
}
|
||||
|
||||
return runScriptFromScript("spawn", scriptServer, scriptname, args, workerScript, threads);
|
||||
return runScriptFromScript(Player, "spawn", scriptServer, scriptname, args, workerScript, threads);
|
||||
}, spawnDelay * 1e3);
|
||||
|
||||
workerScript.log("spawn", () => `Will execute '${scriptname}' in ${spawnDelay} seconds`);
|
||||
@@ -983,8 +1009,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
workerScript.log("spawn", () => "Exiting...");
|
||||
}
|
||||
},
|
||||
kill: function (filename: any, hostname: any, ...scriptArgs: any): any {
|
||||
updateDynamicRam("kill", getRamCost("kill"));
|
||||
kill: function (filename: any, hostname?: any, ...scriptArgs: any): any {
|
||||
updateDynamicRam("kill", getRamCost(Player, "kill"));
|
||||
|
||||
let res;
|
||||
const killByPid = typeof filename === "number";
|
||||
@@ -1030,7 +1056,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
}
|
||||
},
|
||||
killall: function (hostname: any = workerScript.hostname): any {
|
||||
updateDynamicRam("killall", getRamCost("killall"));
|
||||
updateDynamicRam("killall", getRamCost(Player, "killall"));
|
||||
if (hostname === undefined) {
|
||||
throw makeRuntimeErrorMsg("killall", "Takes 1 argument");
|
||||
}
|
||||
@@ -1056,7 +1082,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
}
|
||||
},
|
||||
scp: async function (scriptname: any, hostname1: any, hostname2: any): Promise<boolean> {
|
||||
updateDynamicRam("scp", getRamCost("scp"));
|
||||
updateDynamicRam("scp", getRamCost(Player, "scp"));
|
||||
if (arguments.length !== 2 && arguments.length !== 3) {
|
||||
throw makeRuntimeErrorMsg("scp", "Takes 2 or 3 arguments");
|
||||
}
|
||||
@@ -1209,11 +1235,11 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
newScript.updateRamUsage(destServer.scripts).then(() => resolve(true));
|
||||
newScript.updateRamUsage(Player, destServer.scripts).then(() => resolve(true));
|
||||
});
|
||||
},
|
||||
ls: function (hostname: any, grep: any): any {
|
||||
updateDynamicRam("ls", getRamCost("ls"));
|
||||
updateDynamicRam("ls", getRamCost(Player, "ls"));
|
||||
if (hostname === undefined) {
|
||||
throw makeRuntimeErrorMsg("ls", "Usage: ls(hostname/ip, [grep filter])");
|
||||
}
|
||||
@@ -1280,7 +1306,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return allFiles;
|
||||
},
|
||||
ps: function (hostname: any = workerScript.hostname): any {
|
||||
updateDynamicRam("ps", getRamCost("ps"));
|
||||
updateDynamicRam("ps", getRamCost(Player, "ps"));
|
||||
const server = safeGetServer(hostname, "ps");
|
||||
const processes = [];
|
||||
for (const i in server.runningScripts) {
|
||||
@@ -1295,7 +1321,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return processes;
|
||||
},
|
||||
hasRootAccess: function (hostname: any): any {
|
||||
updateDynamicRam("hasRootAccess", getRamCost("hasRootAccess"));
|
||||
updateDynamicRam("hasRootAccess", getRamCost(Player, "hasRootAccess"));
|
||||
if (hostname === undefined) {
|
||||
throw makeRuntimeErrorMsg("hasRootAccess", "Takes 1 argument");
|
||||
}
|
||||
@@ -1303,7 +1329,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return server.hasAdminRights;
|
||||
},
|
||||
getHostname: function (): any {
|
||||
updateDynamicRam("getHostname", getRamCost("getHostname"));
|
||||
updateDynamicRam("getHostname", getRamCost(Player, "getHostname"));
|
||||
const scriptServer = GetServer(workerScript.hostname);
|
||||
if (scriptServer == null) {
|
||||
throw makeRuntimeErrorMsg("getHostname", "Could not find server. This is a bug. Report to dev.");
|
||||
@@ -1311,13 +1337,13 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return scriptServer.hostname;
|
||||
},
|
||||
getHackingLevel: function (): any {
|
||||
updateDynamicRam("getHackingLevel", getRamCost("getHackingLevel"));
|
||||
updateDynamicRam("getHackingLevel", getRamCost(Player, "getHackingLevel"));
|
||||
Player.updateSkillLevels();
|
||||
workerScript.log("getHackingLevel", () => `returned ${Player.hacking}`);
|
||||
return Player.hacking;
|
||||
},
|
||||
getHackingMultipliers: function (): any {
|
||||
updateDynamicRam("getHackingMultipliers", getRamCost("getHackingMultipliers"));
|
||||
updateDynamicRam("getHackingMultipliers", getRamCost(Player, "getHackingMultipliers"));
|
||||
return {
|
||||
chance: Player.hacking_chance_mult,
|
||||
speed: Player.hacking_speed_mult,
|
||||
@@ -1326,7 +1352,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
};
|
||||
},
|
||||
getHacknetMultipliers: function (): any {
|
||||
updateDynamicRam("getHacknetMultipliers", getRamCost("getHacknetMultipliers"));
|
||||
updateDynamicRam("getHacknetMultipliers", getRamCost(Player, "getHacknetMultipliers"));
|
||||
return {
|
||||
production: Player.hacknet_node_money_mult,
|
||||
purchaseCost: Player.hacknet_node_purchase_cost_mult,
|
||||
@@ -1336,7 +1362,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
};
|
||||
},
|
||||
getBitNodeMultipliers: function (): any {
|
||||
updateDynamicRam("getBitNodeMultipliers", getRamCost("getBitNodeMultipliers"));
|
||||
updateDynamicRam("getBitNodeMultipliers", getRamCost(Player, "getBitNodeMultipliers"));
|
||||
if (SourceFileFlags[5] <= 0 && Player.bitNodeN !== 5) {
|
||||
throw makeRuntimeErrorMsg("getBitNodeMultipliers", "Requires Source-File 5 to run.");
|
||||
}
|
||||
@@ -1344,7 +1370,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return copy;
|
||||
},
|
||||
getServer: function (hostname: any = workerScript.hostname): any {
|
||||
updateDynamicRam("getServer", getRamCost("getServer"));
|
||||
updateDynamicRam("getServer", getRamCost(Player, "getServer"));
|
||||
const server = safeGetServer(hostname, "getServer");
|
||||
const copy = Object.assign({}, server) as any;
|
||||
// These fields should be hidden.
|
||||
@@ -1367,7 +1393,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return copy;
|
||||
},
|
||||
getServerMoneyAvailable: function (hostname: any): any {
|
||||
updateDynamicRam("getServerMoneyAvailable", getRamCost("getServerMoneyAvailable"));
|
||||
updateDynamicRam("getServerMoneyAvailable", getRamCost(Player, "getServerMoneyAvailable"));
|
||||
const server = safeGetServer(hostname, "getServerMoneyAvailable");
|
||||
if (!(server instanceof Server)) {
|
||||
workerScript.log("getServerMoneyAvailable", () => "Cannot be executed on this server.");
|
||||
@@ -1391,7 +1417,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return server.moneyAvailable;
|
||||
},
|
||||
getServerSecurityLevel: function (hostname: any): any {
|
||||
updateDynamicRam("getServerSecurityLevel", getRamCost("getServerSecurityLevel"));
|
||||
updateDynamicRam("getServerSecurityLevel", getRamCost(Player, "getServerSecurityLevel"));
|
||||
const server = safeGetServer(hostname, "getServerSecurityLevel");
|
||||
if (!(server instanceof Server)) {
|
||||
workerScript.log("getServerSecurityLevel", () => "Cannot be executed on this server.");
|
||||
@@ -1407,7 +1433,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return server.hackDifficulty;
|
||||
},
|
||||
getServerBaseSecurityLevel: function (hostname: any): any {
|
||||
updateDynamicRam("getServerBaseSecurityLevel", getRamCost("getServerBaseSecurityLevel"));
|
||||
updateDynamicRam("getServerBaseSecurityLevel", getRamCost(Player, "getServerBaseSecurityLevel"));
|
||||
workerScript.log(
|
||||
"getServerBaseSecurityLevel",
|
||||
() => `getServerBaseSecurityLevel is deprecated because it's not useful.`,
|
||||
@@ -1427,7 +1453,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return server.baseDifficulty;
|
||||
},
|
||||
getServerMinSecurityLevel: function (hostname: any): any {
|
||||
updateDynamicRam("getServerMinSecurityLevel", getRamCost("getServerMinSecurityLevel"));
|
||||
updateDynamicRam("getServerMinSecurityLevel", getRamCost(Player, "getServerMinSecurityLevel"));
|
||||
const server = safeGetServer(hostname, "getServerMinSecurityLevel");
|
||||
if (!(server instanceof Server)) {
|
||||
workerScript.log("getServerMinSecurityLevel", () => "Cannot be executed on this server.");
|
||||
@@ -1443,7 +1469,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return server.minDifficulty;
|
||||
},
|
||||
getServerRequiredHackingLevel: function (hostname: any): any {
|
||||
updateDynamicRam("getServerRequiredHackingLevel", getRamCost("getServerRequiredHackingLevel"));
|
||||
updateDynamicRam("getServerRequiredHackingLevel", getRamCost(Player, "getServerRequiredHackingLevel"));
|
||||
const server = safeGetServer(hostname, "getServerRequiredHackingLevel");
|
||||
if (!(server instanceof Server)) {
|
||||
workerScript.log("getServerRequiredHackingLevel", () => "Cannot be executed on this server.");
|
||||
@@ -1459,7 +1485,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return server.requiredHackingSkill;
|
||||
},
|
||||
getServerMaxMoney: function (hostname: any): any {
|
||||
updateDynamicRam("getServerMaxMoney", getRamCost("getServerMaxMoney"));
|
||||
updateDynamicRam("getServerMaxMoney", getRamCost(Player, "getServerMaxMoney"));
|
||||
const server = safeGetServer(hostname, "getServerMaxMoney");
|
||||
if (!(server instanceof Server)) {
|
||||
workerScript.log("getServerMaxMoney", () => "Cannot be executed on this server.");
|
||||
@@ -1475,7 +1501,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return server.moneyMax;
|
||||
},
|
||||
getServerGrowth: function (hostname: any): any {
|
||||
updateDynamicRam("getServerGrowth", getRamCost("getServerGrowth"));
|
||||
updateDynamicRam("getServerGrowth", getRamCost(Player, "getServerGrowth"));
|
||||
const server = safeGetServer(hostname, "getServerGrowth");
|
||||
if (!(server instanceof Server)) {
|
||||
workerScript.log("getServerGrowth", () => "Cannot be executed on this server.");
|
||||
@@ -1488,7 +1514,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return server.serverGrowth;
|
||||
},
|
||||
getServerNumPortsRequired: function (hostname: any): any {
|
||||
updateDynamicRam("getServerNumPortsRequired", getRamCost("getServerNumPortsRequired"));
|
||||
updateDynamicRam("getServerNumPortsRequired", getRamCost(Player, "getServerNumPortsRequired"));
|
||||
const server = safeGetServer(hostname, "getServerNumPortsRequired");
|
||||
if (!(server instanceof Server)) {
|
||||
workerScript.log("getServerNumPortsRequired", () => "Cannot be executed on this server.");
|
||||
@@ -1504,7 +1530,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return server.numOpenPortsRequired;
|
||||
},
|
||||
getServerRam: function (hostname: any): any {
|
||||
updateDynamicRam("getServerRam", getRamCost("getServerRam"));
|
||||
updateDynamicRam("getServerRam", getRamCost(Player, "getServerRam"));
|
||||
workerScript.log(
|
||||
"getServerRam",
|
||||
() => `getServerRam is deprecated in favor of getServerMaxRam / getServerUsedRam`,
|
||||
@@ -1517,23 +1543,23 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return [server.maxRam, server.ramUsed];
|
||||
},
|
||||
getServerMaxRam: function (hostname: any): any {
|
||||
updateDynamicRam("getServerMaxRam", getRamCost("getServerMaxRam"));
|
||||
updateDynamicRam("getServerMaxRam", getRamCost(Player, "getServerMaxRam"));
|
||||
const server = safeGetServer(hostname, "getServerMaxRam");
|
||||
workerScript.log("getServerMaxRam", () => `returned ${numeralWrapper.formatRAM(server.maxRam)}`);
|
||||
return server.maxRam;
|
||||
},
|
||||
getServerUsedRam: function (hostname: any): any {
|
||||
updateDynamicRam("getServerUsedRam", getRamCost("getServerUsedRam"));
|
||||
updateDynamicRam("getServerUsedRam", getRamCost(Player, "getServerUsedRam"));
|
||||
const server = safeGetServer(hostname, "getServerUsedRam");
|
||||
workerScript.log("getServerUsedRam", () => `returned ${numeralWrapper.formatRAM(server.ramUsed)}`);
|
||||
return server.ramUsed;
|
||||
},
|
||||
serverExists: function (hostname: any): any {
|
||||
updateDynamicRam("serverExists", getRamCost("serverExists"));
|
||||
updateDynamicRam("serverExists", getRamCost(Player, "serverExists"));
|
||||
return GetServer(hostname) !== null;
|
||||
},
|
||||
fileExists: function (filename: any, hostname: any = workerScript.hostname): any {
|
||||
updateDynamicRam("fileExists", getRamCost("fileExists"));
|
||||
updateDynamicRam("fileExists", getRamCost(Player, "fileExists"));
|
||||
if (filename === undefined) {
|
||||
throw makeRuntimeErrorMsg("fileExists", "Usage: fileExists(scriptname, [server])");
|
||||
}
|
||||
@@ -1560,7 +1586,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return false;
|
||||
},
|
||||
isRunning: function (fn: any, hostname: any = workerScript.hostname, ...scriptArgs: any): any {
|
||||
updateDynamicRam("isRunning", getRamCost("isRunning"));
|
||||
updateDynamicRam("isRunning", getRamCost(Player, "isRunning"));
|
||||
if (fn === undefined || hostname === undefined) {
|
||||
throw makeRuntimeErrorMsg("isRunning", "Usage: isRunning(scriptname, server, [arg1], [arg2]...)");
|
||||
}
|
||||
@@ -1571,17 +1597,17 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
}
|
||||
},
|
||||
getPurchasedServerLimit: function (): any {
|
||||
updateDynamicRam("getPurchasedServerLimit", getRamCost("getPurchasedServerLimit"));
|
||||
updateDynamicRam("getPurchasedServerLimit", getRamCost(Player, "getPurchasedServerLimit"));
|
||||
|
||||
return getPurchaseServerLimit();
|
||||
},
|
||||
getPurchasedServerMaxRam: function (): any {
|
||||
updateDynamicRam("getPurchasedServerMaxRam", getRamCost("getPurchasedServerMaxRam"));
|
||||
updateDynamicRam("getPurchasedServerMaxRam", getRamCost(Player, "getPurchasedServerMaxRam"));
|
||||
|
||||
return getPurchaseServerMaxRam();
|
||||
},
|
||||
getPurchasedServerCost: function (ram: any): any {
|
||||
updateDynamicRam("getPurchasedServerCost", getRamCost("getPurchasedServerCost"));
|
||||
updateDynamicRam("getPurchasedServerCost", getRamCost(Player, "getPurchasedServerCost"));
|
||||
|
||||
const cost = getPurchaseServerCost(ram);
|
||||
if (cost === Infinity) {
|
||||
@@ -1591,8 +1617,10 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
|
||||
return cost;
|
||||
},
|
||||
purchaseServer: function (name: any, ram: any): any {
|
||||
updateDynamicRam("purchaseServer", getRamCost("purchaseServer"));
|
||||
purchaseServer: function (aname: any, aram: any): any {
|
||||
const name = helper.string("purchaseServer", "name", aname);
|
||||
const ram = helper.number("purchaseServer", "ram", aram);
|
||||
updateDynamicRam("purchaseServer", getRamCost(Player, "purchaseServer"));
|
||||
let hostnameStr = String(name);
|
||||
hostnameStr = hostnameStr.replace(/\s+/g, "");
|
||||
if (hostnameStr == "") {
|
||||
@@ -1611,7 +1639,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
|
||||
const cost = getPurchaseServerCost(ram);
|
||||
if (cost === Infinity) {
|
||||
workerScript.log("purchaseServer", () => `Invalid argument: ram='${ram}'`);
|
||||
workerScript.log("purchaseServer", () => `Invalid argument: ram='${ram}' must be a positive power of 2`);
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -1645,7 +1673,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return newServ.hostname;
|
||||
},
|
||||
deleteServer: function (name: any): any {
|
||||
updateDynamicRam("deleteServer", getRamCost("deleteServer"));
|
||||
updateDynamicRam("deleteServer", getRamCost(Player, "deleteServer"));
|
||||
let hostnameStr = String(name);
|
||||
hostnameStr = hostnameStr.replace(/\s\s+/g, "");
|
||||
const server = GetServer(hostnameStr);
|
||||
@@ -1721,7 +1749,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return false;
|
||||
},
|
||||
getPurchasedServers: function (): any {
|
||||
updateDynamicRam("getPurchasedServers", getRamCost("getPurchasedServers"));
|
||||
updateDynamicRam("getPurchasedServers", getRamCost(Player, "getPurchasedServers"));
|
||||
const res: string[] = [];
|
||||
Player.purchasedServers.forEach(function (hostname) {
|
||||
res.push(hostname);
|
||||
@@ -1729,29 +1757,17 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return res;
|
||||
},
|
||||
writePort: function (port: any, data: any = ""): any {
|
||||
// Write to port
|
||||
// Port 1-10
|
||||
if (typeof data !== "string" && typeof data !== "number") {
|
||||
throw makeRuntimeErrorMsg(
|
||||
"writePort",
|
||||
`Trying to write invalid data to a port: only strings and numbers are valid.`,
|
||||
);
|
||||
}
|
||||
port = Math.round(port);
|
||||
if (port < 1 || port > CONSTANTS.NumNetscriptPorts) {
|
||||
throw makeRuntimeErrorMsg(
|
||||
"writePort",
|
||||
`Trying to write to invalid port: ${port}. Only ports 1-${CONSTANTS.NumNetscriptPorts} are valid.`,
|
||||
);
|
||||
}
|
||||
const iport = NetscriptPorts[port - 1];
|
||||
if (iport == null || !(iport instanceof Object)) {
|
||||
throw makeRuntimeErrorMsg("writePort", `Could not find port: ${port}. This is a bug. Report to dev.`);
|
||||
}
|
||||
const iport = helper.getValidPort("writePort", port);
|
||||
return Promise.resolve(iport.write(data));
|
||||
},
|
||||
write: function (port: any, data: any = "", mode: any = "a"): any {
|
||||
updateDynamicRam("write", getRamCost("write"));
|
||||
updateDynamicRam("write", getRamCost(Player, "write"));
|
||||
if (isString(port)) {
|
||||
// Write to script or text file
|
||||
let fn = port;
|
||||
@@ -1779,12 +1795,12 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
let script = workerScript.getScriptOnServer(fn, server);
|
||||
if (script == null) {
|
||||
// Create a new script
|
||||
script = new Script(fn, data, server.hostname, server.scripts);
|
||||
script = new Script(Player, fn, data, server.hostname, server.scripts);
|
||||
server.scripts.push(script);
|
||||
return script.updateRamUsage(server.scripts);
|
||||
return script.updateRamUsage(Player, server.scripts);
|
||||
}
|
||||
mode === "w" ? (script.code = data) : (script.code += data);
|
||||
return script.updateRamUsage(server.scripts);
|
||||
return script.updateRamUsage(Player, server.scripts);
|
||||
} else {
|
||||
// Write to text file
|
||||
const txtFile = getTextFile(fn, server);
|
||||
@@ -1804,7 +1820,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
}
|
||||
},
|
||||
tryWritePort: function (port: any, data: any = ""): any {
|
||||
updateDynamicRam("tryWritePort", getRamCost("tryWritePort"));
|
||||
updateDynamicRam("tryWritePort", getRamCost(Player, "tryWritePort"));
|
||||
if (!isNaN(port)) {
|
||||
port = Math.round(port);
|
||||
if (port < 1 || port > CONSTANTS.NumNetscriptPorts) {
|
||||
@@ -1824,23 +1840,12 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
},
|
||||
readPort: function (port: any): any {
|
||||
// Read from port
|
||||
// Port 1-10
|
||||
port = Math.round(port);
|
||||
if (port < 1 || port > CONSTANTS.NumNetscriptPorts) {
|
||||
throw makeRuntimeErrorMsg(
|
||||
"readPort",
|
||||
`Invalid port: ${port}. Only ports 1-${CONSTANTS.NumNetscriptPorts} are valid.`,
|
||||
);
|
||||
}
|
||||
const iport = NetscriptPorts[port - 1];
|
||||
if (iport == null || !(iport instanceof Object)) {
|
||||
throw makeRuntimeErrorMsg("readPort", `Could not find port: ${port}. This is a bug. Report to dev.`);
|
||||
}
|
||||
const iport = helper.getValidPort("readPort", port);
|
||||
const x = iport.read();
|
||||
return x;
|
||||
},
|
||||
read: function (port: any): any {
|
||||
updateDynamicRam("read", getRamCost("read"));
|
||||
updateDynamicRam("read", getRamCost(Player, "read"));
|
||||
if (isString(port)) {
|
||||
// Read from script or text file
|
||||
const fn = port;
|
||||
@@ -1869,29 +1874,13 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
}
|
||||
},
|
||||
peek: function (port: any): any {
|
||||
updateDynamicRam("peek", getRamCost("peek"));
|
||||
if (isNaN(port)) {
|
||||
throw makeRuntimeErrorMsg(
|
||||
"peek",
|
||||
`Invalid argument. Must be a port number between 1 and ${CONSTANTS.NumNetscriptPorts}, is ${port}`,
|
||||
);
|
||||
}
|
||||
port = Math.round(port);
|
||||
if (port < 1 || port > CONSTANTS.NumNetscriptPorts) {
|
||||
throw makeRuntimeErrorMsg(
|
||||
"peek",
|
||||
`Invalid argument. Must be a port number between 1 and ${CONSTANTS.NumNetscriptPorts}, is ${port}`,
|
||||
);
|
||||
}
|
||||
const iport = NetscriptPorts[port - 1];
|
||||
if (iport == null || !(iport instanceof Object)) {
|
||||
throw makeRuntimeErrorMsg("peek", `Could not find port: ${port}. This is a bug. Report to dev.`);
|
||||
}
|
||||
updateDynamicRam("peek", getRamCost(Player, "peek"));
|
||||
const iport = helper.getValidPort("peek", port);
|
||||
const x = iport.peek();
|
||||
return x;
|
||||
},
|
||||
clear: function (file: any): any {
|
||||
updateDynamicRam("clear", getRamCost("clear"));
|
||||
updateDynamicRam("clear", getRamCost(Player, "clear"));
|
||||
if (isString(file)) {
|
||||
// Clear text file
|
||||
const fn = file;
|
||||
@@ -1910,42 +1899,16 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
},
|
||||
clearPort: function (port: any): any {
|
||||
// Clear port
|
||||
port = Math.round(port);
|
||||
if (port < 1 || port > CONSTANTS.NumNetscriptPorts) {
|
||||
throw makeRuntimeErrorMsg(
|
||||
"clear",
|
||||
`Trying to clear invalid port: ${port}. Only ports 1-${CONSTANTS.NumNetscriptPorts} are valid`,
|
||||
);
|
||||
}
|
||||
const iport = NetscriptPorts[port - 1];
|
||||
if (iport == null || !(iport instanceof Object)) {
|
||||
throw makeRuntimeErrorMsg("clear", `Could not find port: ${port}. This is a bug. Report to dev.`);
|
||||
}
|
||||
const iport = helper.getValidPort("clearPort", port);
|
||||
return iport.clear();
|
||||
},
|
||||
getPortHandle: function (port: any): any {
|
||||
updateDynamicRam("getPortHandle", getRamCost("getPortHandle"));
|
||||
if (isNaN(port)) {
|
||||
throw makeRuntimeErrorMsg(
|
||||
"getPortHandle",
|
||||
`Invalid port: ${port} Must be an integer between 1 and ${CONSTANTS.NumNetscriptPorts}.`,
|
||||
);
|
||||
}
|
||||
port = Math.round(port);
|
||||
if (port < 1 || port > CONSTANTS.NumNetscriptPorts) {
|
||||
throw makeRuntimeErrorMsg(
|
||||
"getPortHandle",
|
||||
`Invalid port: ${port}. Only ports 1-${CONSTANTS.NumNetscriptPorts} are valid.`,
|
||||
);
|
||||
}
|
||||
const iport = NetscriptPorts[port - 1];
|
||||
if (iport == null || !(iport instanceof Object)) {
|
||||
throw makeRuntimeErrorMsg("getPortHandle", `Could not find port: ${port}. This is a bug. Report to dev.`);
|
||||
}
|
||||
updateDynamicRam("getPortHandle", getRamCost(Player, "getPortHandle"));
|
||||
const iport = helper.getValidPort("getPortHandle", port);
|
||||
return iport;
|
||||
},
|
||||
rm: function (fn: any, hostname: any): any {
|
||||
updateDynamicRam("rm", getRamCost("rm"));
|
||||
updateDynamicRam("rm", getRamCost(Player, "rm"));
|
||||
|
||||
if (hostname == null || hostname === "") {
|
||||
hostname = workerScript.hostname;
|
||||
@@ -1960,7 +1923,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return status.res;
|
||||
},
|
||||
scriptRunning: function (scriptname: any, hostname: any): any {
|
||||
updateDynamicRam("scriptRunning", getRamCost("scriptRunning"));
|
||||
updateDynamicRam("scriptRunning", getRamCost(Player, "scriptRunning"));
|
||||
const server = safeGetServer(hostname, "scriptRunning");
|
||||
for (let i = 0; i < server.runningScripts.length; ++i) {
|
||||
if (server.runningScripts[i].filename == scriptname) {
|
||||
@@ -1970,7 +1933,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return false;
|
||||
},
|
||||
scriptKill: function (scriptname: any, hostname: any): any {
|
||||
updateDynamicRam("scriptKill", getRamCost("scriptKill"));
|
||||
updateDynamicRam("scriptKill", getRamCost(Player, "scriptKill"));
|
||||
const server = safeGetServer(hostname, "scriptKill");
|
||||
let suc = false;
|
||||
for (let i = 0; i < server.runningScripts.length; i++) {
|
||||
@@ -1986,7 +1949,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return workerScript.name;
|
||||
},
|
||||
getScriptRam: function (scriptname: any, hostname: any = workerScript.hostname): any {
|
||||
updateDynamicRam("getScriptRam", getRamCost("getScriptRam"));
|
||||
updateDynamicRam("getScriptRam", getRamCost(Player, "getScriptRam"));
|
||||
const server = safeGetServer(hostname, "getScriptRam");
|
||||
for (let i = 0; i < server.scripts.length; ++i) {
|
||||
if (server.scripts[i].filename == scriptname) {
|
||||
@@ -1996,7 +1959,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return 0;
|
||||
},
|
||||
getRunningScript: function (fn: any, hostname: any, ...args: any[]): any {
|
||||
updateDynamicRam("getRunningScript", getRamCost("getRunningScript"));
|
||||
updateDynamicRam("getRunningScript", getRamCost(Player, "getRunningScript"));
|
||||
|
||||
let runningScript;
|
||||
if (fn === undefined && hostname === undefined && args.length === 0) {
|
||||
@@ -2024,7 +1987,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
};
|
||||
},
|
||||
getHackTime: function (hostname: any): any {
|
||||
updateDynamicRam("getHackTime", getRamCost("getHackTime"));
|
||||
updateDynamicRam("getHackTime", getRamCost(Player, "getHackTime"));
|
||||
const server = safeGetServer(hostname, "getHackTime");
|
||||
if (!(server instanceof Server)) {
|
||||
workerScript.log("getHackTime", () => "invalid for this kind of server");
|
||||
@@ -2037,7 +2000,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return calculateHackingTime(server, Player) * 1000;
|
||||
},
|
||||
getGrowTime: function (hostname: any): any {
|
||||
updateDynamicRam("getGrowTime", getRamCost("getGrowTime"));
|
||||
updateDynamicRam("getGrowTime", getRamCost(Player, "getGrowTime"));
|
||||
const server = safeGetServer(hostname, "getGrowTime");
|
||||
if (!(server instanceof Server)) {
|
||||
workerScript.log("getGrowTime", () => "invalid for this kind of server");
|
||||
@@ -2050,7 +2013,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return calculateGrowTime(server, Player) * 1000;
|
||||
},
|
||||
getWeakenTime: function (hostname: any): any {
|
||||
updateDynamicRam("getWeakenTime", getRamCost("getWeakenTime"));
|
||||
updateDynamicRam("getWeakenTime", getRamCost(Player, "getWeakenTime"));
|
||||
const server = safeGetServer(hostname, "getWeakenTime");
|
||||
if (!(server instanceof Server)) {
|
||||
workerScript.log("getWeakenTime", () => "invalid for this kind of server");
|
||||
@@ -2062,8 +2025,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
|
||||
return calculateWeakenTime(server, Player) * 1000;
|
||||
},
|
||||
getScriptIncome: function (scriptname: any, hostname: any, ...args: any[]): any {
|
||||
updateDynamicRam("getScriptIncome", getRamCost("getScriptIncome"));
|
||||
getScriptIncome: function (scriptname?: any, hostname?: any, ...args: any[]): any {
|
||||
updateDynamicRam("getScriptIncome", getRamCost(Player, "getScriptIncome"));
|
||||
if (arguments.length === 0) {
|
||||
const res = [];
|
||||
|
||||
@@ -2091,8 +2054,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return runningScriptObj.onlineMoneyMade / runningScriptObj.onlineRunningTime;
|
||||
}
|
||||
},
|
||||
getScriptExpGain: function (scriptname: any, hostname: any, ...args: any[]): any {
|
||||
updateDynamicRam("getScriptExpGain", getRamCost("getScriptExpGain"));
|
||||
getScriptExpGain: function (scriptname?: any, hostname?: any, ...args: any[]): any {
|
||||
updateDynamicRam("getScriptExpGain", getRamCost(Player, "getScriptExpGain"));
|
||||
if (arguments.length === 0) {
|
||||
let total = 0;
|
||||
for (const ws of workerScripts.values()) {
|
||||
@@ -2124,19 +2087,19 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return convertTimeMsToTimeElapsedString(milliseconds, milliPrecision);
|
||||
},
|
||||
getTimeSinceLastAug: function (): any {
|
||||
updateDynamicRam("getTimeSinceLastAug", getRamCost("getTimeSinceLastAug"));
|
||||
updateDynamicRam("getTimeSinceLastAug", getRamCost(Player, "getTimeSinceLastAug"));
|
||||
return Player.playtimeSinceLastAug;
|
||||
},
|
||||
alert: function (message: any): void {
|
||||
message = toNative(message);
|
||||
dialogBoxCreate(JSON.stringify(message));
|
||||
message = argsToString([message]);
|
||||
dialogBoxCreate(message);
|
||||
},
|
||||
toast: function (message: any, variant: any = "success"): void {
|
||||
toast: function (message: any, variant: any = "success", duration: any = 2000): void {
|
||||
if (!["success", "info", "warning", "error"].includes(variant))
|
||||
throw new Error(`variant must be one of "success", "info", "warning", or "error"`);
|
||||
|
||||
message = toNative(message);
|
||||
SnackbarEvents.emit(JSON.stringify(message), variant);
|
||||
message = argsToString([message]);
|
||||
SnackbarEvents.emit(message, variant, duration);
|
||||
},
|
||||
prompt: function (txt: any): any {
|
||||
if (!isString(txt)) {
|
||||
@@ -2162,7 +2125,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
function (data) {
|
||||
let res;
|
||||
if (isScriptFilename(target)) {
|
||||
res = s.writeToScriptFile(target, data);
|
||||
res = s.writeToScriptFile(Player, target, data);
|
||||
} else {
|
||||
res = s.writeToTextFile(target, data);
|
||||
}
|
||||
@@ -2188,11 +2151,11 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
});
|
||||
},
|
||||
getFavorToDonate: function (): any {
|
||||
updateDynamicRam("getFavorToDonate", getRamCost("getFavorToDonate"));
|
||||
updateDynamicRam("getFavorToDonate", getRamCost(Player, "getFavorToDonate"));
|
||||
return Math.floor(CONSTANTS.BaseFavorToDonate * BitNodeMultipliers.RepToDonateToFaction);
|
||||
},
|
||||
getOwnedSourceFiles: function (): SourceFileLvl[] {
|
||||
helper.updateDynamicRam("getOwnedSourceFiles", getRamCost("getOwnedSourceFiles"));
|
||||
helper.updateDynamicRam("getOwnedSourceFiles", getRamCost(Player, "getOwnedSourceFiles"));
|
||||
const res: SourceFileLvl[] = [];
|
||||
for (let i = 0; i < Player.sourceFiles.length; ++i) {
|
||||
res.push({
|
||||
@@ -2203,7 +2166,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return res;
|
||||
},
|
||||
getPlayer: function (): INetscriptPlayer {
|
||||
helper.updateDynamicRam("getPlayer", getRamCost("getPlayer"));
|
||||
helper.updateDynamicRam("getPlayer", getRamCost(Player, "getPlayer"));
|
||||
|
||||
const data = {
|
||||
hacking: Player.hacking,
|
||||
@@ -2310,10 +2273,12 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
...base,
|
||||
...extra,
|
||||
};
|
||||
function getFunctionNames(obj: NS, prefix: string): string[] {
|
||||
function getFunctionNames(obj: any, prefix: string): string[] {
|
||||
const functionNames: string[] = [];
|
||||
for (const [key, value] of Object.entries(obj)) {
|
||||
if (typeof value == "function") {
|
||||
if (key === "args") {
|
||||
continue;
|
||||
} else if (typeof value == "function") {
|
||||
functionNames.push(prefix + key);
|
||||
} else if (typeof value == "object") {
|
||||
functionNames.push(...getFunctionNames(value, key + "."));
|
||||
|
||||
@@ -57,48 +57,48 @@ export function NetscriptBladeburner(
|
||||
|
||||
return {
|
||||
getContractNames: function (): string[] {
|
||||
helper.updateDynamicRam("getContractNames", getRamCost("bladeburner", "getContractNames"));
|
||||
helper.updateDynamicRam("getContractNames", getRamCost(player, "bladeburner", "getContractNames"));
|
||||
checkBladeburnerAccess("getContractNames");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.getContractNamesNetscriptFn();
|
||||
},
|
||||
getOperationNames: function (): string[] {
|
||||
helper.updateDynamicRam("getOperationNames", getRamCost("bladeburner", "getOperationNames"));
|
||||
helper.updateDynamicRam("getOperationNames", getRamCost(player, "bladeburner", "getOperationNames"));
|
||||
checkBladeburnerAccess("getOperationNames");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.getOperationNamesNetscriptFn();
|
||||
},
|
||||
getBlackOpNames: function (): string[] {
|
||||
helper.updateDynamicRam("getBlackOpNames", getRamCost("bladeburner", "getBlackOpNames"));
|
||||
helper.updateDynamicRam("getBlackOpNames", getRamCost(player, "bladeburner", "getBlackOpNames"));
|
||||
checkBladeburnerAccess("getBlackOpNames");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.getBlackOpNamesNetscriptFn();
|
||||
},
|
||||
getBlackOpRank: function (name: any = ""): number {
|
||||
helper.updateDynamicRam("getBlackOpRank", getRamCost("bladeburner", "getBlackOpRank"));
|
||||
helper.updateDynamicRam("getBlackOpRank", getRamCost(player, "bladeburner", "getBlackOpRank"));
|
||||
checkBladeburnerAccess("getBlackOpRank");
|
||||
const action: any = getBladeburnerActionObject("getBlackOpRank", "blackops", name);
|
||||
return action.reqdRank;
|
||||
},
|
||||
getGeneralActionNames: function (): string[] {
|
||||
helper.updateDynamicRam("getGeneralActionNames", getRamCost("bladeburner", "getGeneralActionNames"));
|
||||
helper.updateDynamicRam("getGeneralActionNames", getRamCost(player, "bladeburner", "getGeneralActionNames"));
|
||||
checkBladeburnerAccess("getGeneralActionNames");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.getGeneralActionNamesNetscriptFn();
|
||||
},
|
||||
getSkillNames: function (): string[] {
|
||||
helper.updateDynamicRam("getSkillNames", getRamCost("bladeburner", "getSkillNames"));
|
||||
helper.updateDynamicRam("getSkillNames", getRamCost(player, "bladeburner", "getSkillNames"));
|
||||
checkBladeburnerAccess("getSkillNames");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.getSkillNamesNetscriptFn();
|
||||
},
|
||||
startAction: function (type: any = "", name: any = ""): boolean {
|
||||
helper.updateDynamicRam("startAction", getRamCost("bladeburner", "startAction"));
|
||||
helper.updateDynamicRam("startAction", getRamCost(player, "bladeburner", "startAction"));
|
||||
checkBladeburnerAccess("startAction");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
@@ -109,21 +109,21 @@ export function NetscriptBladeburner(
|
||||
}
|
||||
},
|
||||
stopBladeburnerAction: function (): void {
|
||||
helper.updateDynamicRam("stopBladeburnerAction", getRamCost("bladeburner", "stopBladeburnerAction"));
|
||||
helper.updateDynamicRam("stopBladeburnerAction", getRamCost(player, "bladeburner", "stopBladeburnerAction"));
|
||||
checkBladeburnerAccess("stopBladeburnerAction");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.resetAction();
|
||||
},
|
||||
getCurrentAction: function (): BladeburnerCurAction {
|
||||
helper.updateDynamicRam("getCurrentAction", getRamCost("bladeburner", "getCurrentAction"));
|
||||
helper.updateDynamicRam("getCurrentAction", getRamCost(player, "bladeburner", "getCurrentAction"));
|
||||
checkBladeburnerAccess("getCurrentAction");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.getTypeAndNameFromActionId(bladeburner.action);
|
||||
},
|
||||
getActionTime: function (type: any = "", name: any = ""): number {
|
||||
helper.updateDynamicRam("getActionTime", getRamCost("bladeburner", "getActionTime"));
|
||||
helper.updateDynamicRam("getActionTime", getRamCost(player, "bladeburner", "getActionTime"));
|
||||
checkBladeburnerAccess("getActionTime");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
@@ -136,7 +136,7 @@ export function NetscriptBladeburner(
|
||||
getActionEstimatedSuccessChance: function (type: any = "", name: any = ""): [number, number] {
|
||||
helper.updateDynamicRam(
|
||||
"getActionEstimatedSuccessChance",
|
||||
getRamCost("bladeburner", "getActionEstimatedSuccessChance"),
|
||||
getRamCost(player, "bladeburner", "getActionEstimatedSuccessChance"),
|
||||
);
|
||||
checkBladeburnerAccess("getActionEstimatedSuccessChance");
|
||||
const bladeburner = player.bladeburner;
|
||||
@@ -148,7 +148,7 @@ export function NetscriptBladeburner(
|
||||
}
|
||||
},
|
||||
getActionRepGain: function (type: any = "", name: any = "", level: any): number {
|
||||
helper.updateDynamicRam("getActionRepGain", getRamCost("bladeburner", "getActionRepGain"));
|
||||
helper.updateDynamicRam("getActionRepGain", getRamCost(player, "bladeburner", "getActionRepGain"));
|
||||
checkBladeburnerAccess("getActionRepGain");
|
||||
const action = getBladeburnerActionObject("getActionRepGain", type, name);
|
||||
let rewardMultiplier;
|
||||
@@ -161,7 +161,7 @@ export function NetscriptBladeburner(
|
||||
return action.rankGain * rewardMultiplier * BitNodeMultipliers.BladeburnerRank;
|
||||
},
|
||||
getActionCountRemaining: function (type: any = "", name: any = ""): number {
|
||||
helper.updateDynamicRam("getActionCountRemaining", getRamCost("bladeburner", "getActionCountRemaining"));
|
||||
helper.updateDynamicRam("getActionCountRemaining", getRamCost(player, "bladeburner", "getActionCountRemaining"));
|
||||
checkBladeburnerAccess("getActionCountRemaining");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
@@ -172,31 +172,31 @@ export function NetscriptBladeburner(
|
||||
}
|
||||
},
|
||||
getActionMaxLevel: function (type: any = "", name: any = ""): number {
|
||||
helper.updateDynamicRam("getActionMaxLevel", getRamCost("bladeburner", "getActionMaxLevel"));
|
||||
helper.updateDynamicRam("getActionMaxLevel", getRamCost(player, "bladeburner", "getActionMaxLevel"));
|
||||
checkBladeburnerAccess("getActionMaxLevel");
|
||||
const action = getBladeburnerActionObject("getActionMaxLevel", type, name);
|
||||
return action.maxLevel;
|
||||
},
|
||||
getActionCurrentLevel: function (type: any = "", name: any = ""): number {
|
||||
helper.updateDynamicRam("getActionCurrentLevel", getRamCost("bladeburner", "getActionCurrentLevel"));
|
||||
helper.updateDynamicRam("getActionCurrentLevel", getRamCost(player, "bladeburner", "getActionCurrentLevel"));
|
||||
checkBladeburnerAccess("getActionCurrentLevel");
|
||||
const action = getBladeburnerActionObject("getActionCurrentLevel", type, name);
|
||||
return action.level;
|
||||
},
|
||||
getActionAutolevel: function (type: any = "", name: any = ""): boolean {
|
||||
helper.updateDynamicRam("getActionAutolevel", getRamCost("bladeburner", "getActionAutolevel"));
|
||||
helper.updateDynamicRam("getActionAutolevel", getRamCost(player, "bladeburner", "getActionAutolevel"));
|
||||
checkBladeburnerAccess("getActionAutolevel");
|
||||
const action = getBladeburnerActionObject("getActionCurrentLevel", type, name);
|
||||
return action.autoLevel;
|
||||
},
|
||||
setActionAutolevel: function (type: any = "", name: any = "", autoLevel: any = true): void {
|
||||
helper.updateDynamicRam("setActionAutolevel", getRamCost("bladeburner", "setActionAutolevel"));
|
||||
helper.updateDynamicRam("setActionAutolevel", getRamCost(player, "bladeburner", "setActionAutolevel"));
|
||||
checkBladeburnerAccess("setActionAutolevel");
|
||||
const action = getBladeburnerActionObject("setActionAutolevel", type, name);
|
||||
action.autoLevel = autoLevel;
|
||||
},
|
||||
setActionLevel: function (type: any = "", name: any = "", level: any = 1): void {
|
||||
helper.updateDynamicRam("setActionLevel", getRamCost("bladeburner", "setActionLevel"));
|
||||
helper.updateDynamicRam("setActionLevel", getRamCost(player, "bladeburner", "setActionLevel"));
|
||||
checkBladeburnerAccess("setActionLevel");
|
||||
const action = getBladeburnerActionObject("setActionLevel", type, name);
|
||||
if (level < 1 || level > action.maxLevel) {
|
||||
@@ -208,21 +208,21 @@ export function NetscriptBladeburner(
|
||||
action.level = level;
|
||||
},
|
||||
getRank: function (): number {
|
||||
helper.updateDynamicRam("getRank", getRamCost("bladeburner", "getRank"));
|
||||
helper.updateDynamicRam("getRank", getRamCost(player, "bladeburner", "getRank"));
|
||||
checkBladeburnerAccess("getRank");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.rank;
|
||||
},
|
||||
getSkillPoints: function (): number {
|
||||
helper.updateDynamicRam("getSkillPoints", getRamCost("bladeburner", "getSkillPoints"));
|
||||
helper.updateDynamicRam("getSkillPoints", getRamCost(player, "bladeburner", "getSkillPoints"));
|
||||
checkBladeburnerAccess("getSkillPoints");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.skillPoints;
|
||||
},
|
||||
getSkillLevel: function (skillName: any = ""): number {
|
||||
helper.updateDynamicRam("getSkillLevel", getRamCost("bladeburner", "getSkillLevel"));
|
||||
helper.updateDynamicRam("getSkillLevel", getRamCost(player, "bladeburner", "getSkillLevel"));
|
||||
checkBladeburnerAccess("getSkillLevel");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
@@ -233,7 +233,7 @@ export function NetscriptBladeburner(
|
||||
}
|
||||
},
|
||||
getSkillUpgradeCost: function (skillName: any = ""): number {
|
||||
helper.updateDynamicRam("getSkillUpgradeCost", getRamCost("bladeburner", "getSkillUpgradeCost"));
|
||||
helper.updateDynamicRam("getSkillUpgradeCost", getRamCost(player, "bladeburner", "getSkillUpgradeCost"));
|
||||
checkBladeburnerAccess("getSkillUpgradeCost");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
@@ -244,7 +244,7 @@ export function NetscriptBladeburner(
|
||||
}
|
||||
},
|
||||
upgradeSkill: function (skillName: any): boolean {
|
||||
helper.updateDynamicRam("upgradeSkill", getRamCost("bladeburner", "upgradeSkill"));
|
||||
helper.updateDynamicRam("upgradeSkill", getRamCost(player, "bladeburner", "upgradeSkill"));
|
||||
checkBladeburnerAccess("upgradeSkill");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
@@ -255,7 +255,7 @@ export function NetscriptBladeburner(
|
||||
}
|
||||
},
|
||||
getTeamSize: function (type: any = "", name: any = ""): number {
|
||||
helper.updateDynamicRam("getTeamSize", getRamCost("bladeburner", "getTeamSize"));
|
||||
helper.updateDynamicRam("getTeamSize", getRamCost(player, "bladeburner", "getTeamSize"));
|
||||
checkBladeburnerAccess("getTeamSize");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
@@ -266,7 +266,7 @@ export function NetscriptBladeburner(
|
||||
}
|
||||
},
|
||||
setTeamSize: function (type: any = "", name: any = "", size: any): number {
|
||||
helper.updateDynamicRam("setTeamSize", getRamCost("bladeburner", "setTeamSize"));
|
||||
helper.updateDynamicRam("setTeamSize", getRamCost(player, "bladeburner", "setTeamSize"));
|
||||
checkBladeburnerAccess("setTeamSize");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
@@ -277,7 +277,10 @@ export function NetscriptBladeburner(
|
||||
}
|
||||
},
|
||||
getCityEstimatedPopulation: function (cityName: any): number {
|
||||
helper.updateDynamicRam("getCityEstimatedPopulation", getRamCost("bladeburner", "getCityEstimatedPopulation"));
|
||||
helper.updateDynamicRam(
|
||||
"getCityEstimatedPopulation",
|
||||
getRamCost(player, "bladeburner", "getCityEstimatedPopulation"),
|
||||
);
|
||||
checkBladeburnerAccess("getCityEstimatedPopulation");
|
||||
checkBladeburnerCity("getCityEstimatedPopulation", cityName);
|
||||
const bladeburner = player.bladeburner;
|
||||
@@ -285,7 +288,7 @@ export function NetscriptBladeburner(
|
||||
return bladeburner.cities[cityName].popEst;
|
||||
},
|
||||
getCityCommunities: function (cityName: any): number {
|
||||
helper.updateDynamicRam("getCityCommunities", getRamCost("bladeburner", "getCityCommunities"));
|
||||
helper.updateDynamicRam("getCityCommunities", getRamCost(player, "bladeburner", "getCityCommunities"));
|
||||
checkBladeburnerAccess("getCityCommunities");
|
||||
checkBladeburnerCity("getCityCommunities", cityName);
|
||||
const bladeburner = player.bladeburner;
|
||||
@@ -293,7 +296,7 @@ export function NetscriptBladeburner(
|
||||
return bladeburner.cities[cityName].comms;
|
||||
},
|
||||
getCityChaos: function (cityName: any): number {
|
||||
helper.updateDynamicRam("getCityChaos", getRamCost("bladeburner", "getCityChaos"));
|
||||
helper.updateDynamicRam("getCityChaos", getRamCost(player, "bladeburner", "getCityChaos"));
|
||||
checkBladeburnerAccess("getCityChaos");
|
||||
checkBladeburnerCity("getCityChaos", cityName);
|
||||
const bladeburner = player.bladeburner;
|
||||
@@ -301,14 +304,14 @@ export function NetscriptBladeburner(
|
||||
return bladeburner.cities[cityName].chaos;
|
||||
},
|
||||
getCity: function (): string {
|
||||
helper.updateDynamicRam("getCity", getRamCost("bladeburner", "getCity"));
|
||||
helper.updateDynamicRam("getCity", getRamCost(player, "bladeburner", "getCity"));
|
||||
checkBladeburnerAccess("getCityChaos");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.city;
|
||||
},
|
||||
switchCity: function (cityName: any): boolean {
|
||||
helper.updateDynamicRam("switchCity", getRamCost("bladeburner", "switchCity"));
|
||||
helper.updateDynamicRam("switchCity", getRamCost(player, "bladeburner", "switchCity"));
|
||||
checkBladeburnerAccess("switchCity");
|
||||
checkBladeburnerCity("switchCity", cityName);
|
||||
const bladeburner = player.bladeburner;
|
||||
@@ -316,21 +319,21 @@ export function NetscriptBladeburner(
|
||||
return (bladeburner.city = cityName);
|
||||
},
|
||||
getStamina: function (): [number, number] {
|
||||
helper.updateDynamicRam("getStamina", getRamCost("bladeburner", "getStamina"));
|
||||
helper.updateDynamicRam("getStamina", getRamCost(player, "bladeburner", "getStamina"));
|
||||
checkBladeburnerAccess("getStamina");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return [bladeburner.stamina, bladeburner.maxStamina];
|
||||
},
|
||||
joinBladeburnerFaction: function (): boolean {
|
||||
helper.updateDynamicRam("joinBladeburnerFaction", getRamCost("bladeburner", "joinBladeburnerFaction"));
|
||||
helper.updateDynamicRam("joinBladeburnerFaction", getRamCost(player, "bladeburner", "joinBladeburnerFaction"));
|
||||
checkBladeburnerAccess("joinBladeburnerFaction", true);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.joinBladeburnerFactionNetscriptFn(workerScript);
|
||||
},
|
||||
joinBladeburnerDivision: function (): boolean {
|
||||
helper.updateDynamicRam("joinBladeburnerDivision", getRamCost("bladeburner", "joinBladeburnerDivision"));
|
||||
helper.updateDynamicRam("joinBladeburnerDivision", getRamCost(player, "bladeburner", "joinBladeburnerDivision"));
|
||||
if (player.bitNodeN === 7 || player.sourceFileLvl(7) > 0) {
|
||||
if (player.bitNodeN === 8) {
|
||||
return false;
|
||||
@@ -358,7 +361,7 @@ export function NetscriptBladeburner(
|
||||
return false;
|
||||
},
|
||||
getBonusTime: function (): number {
|
||||
helper.updateDynamicRam("getBonusTime", getRamCost("bladeburner", "getBonusTime"));
|
||||
helper.updateDynamicRam("getBonusTime", getRamCost(player, "bladeburner", "getBonusTime"));
|
||||
checkBladeburnerAccess("getBonusTime");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
|
||||
@@ -31,7 +31,7 @@ export function NetscriptCodingContract(
|
||||
hostname: any = workerScript.hostname,
|
||||
{ returnReward }: any = {},
|
||||
): boolean | string {
|
||||
helper.updateDynamicRam("attempt", getRamCost("codingcontract", "attempt"));
|
||||
helper.updateDynamicRam("attempt", getRamCost(player, "codingcontract", "attempt"));
|
||||
const contract = getCodingContract("attempt", hostname, filename);
|
||||
|
||||
// Convert answer to string. If the answer is a 2D array, then we have to
|
||||
@@ -78,12 +78,12 @@ export function NetscriptCodingContract(
|
||||
}
|
||||
},
|
||||
getContractType: function (filename: any, hostname: any = workerScript.hostname): string {
|
||||
helper.updateDynamicRam("getContractType", getRamCost("codingcontract", "getContractType"));
|
||||
helper.updateDynamicRam("getContractType", getRamCost(player, "codingcontract", "getContractType"));
|
||||
const contract = getCodingContract("getContractType", hostname, filename);
|
||||
return contract.getType();
|
||||
},
|
||||
getData: function (filename: any, hostname: any = workerScript.hostname): any {
|
||||
helper.updateDynamicRam("getData", getRamCost("codingcontract", "getData"));
|
||||
helper.updateDynamicRam("getData", getRamCost(player, "codingcontract", "getData"));
|
||||
const contract = getCodingContract("getData", hostname, filename);
|
||||
const data = contract.getData();
|
||||
if (data.constructor === Array) {
|
||||
@@ -103,12 +103,12 @@ export function NetscriptCodingContract(
|
||||
}
|
||||
},
|
||||
getDescription: function (filename: any, hostname: any = workerScript.hostname): string {
|
||||
helper.updateDynamicRam("getDescription", getRamCost("codingcontract", "getDescription"));
|
||||
helper.updateDynamicRam("getDescription", getRamCost(player, "codingcontract", "getDescription"));
|
||||
const contract = getCodingContract("getDescription", hostname, filename);
|
||||
return contract.getDescription();
|
||||
},
|
||||
getNumTriesRemaining: function (filename: any, hostname: any = workerScript.hostname): number {
|
||||
helper.updateDynamicRam("getNumTriesRemaining", getRamCost("codingcontract", "getNumTriesRemaining"));
|
||||
helper.updateDynamicRam("getNumTriesRemaining", getRamCost(player, "codingcontract", "getNumTriesRemaining"));
|
||||
const contract = getCodingContract("getNumTriesRemaining", hostname, filename);
|
||||
return contract.getMaxNumTries() - contract.tries;
|
||||
},
|
||||
|
||||
@@ -496,7 +496,7 @@ export function NetscriptCorporation(
|
||||
shareSaleCooldown: corporation.shareSaleCooldown,
|
||||
issuedShares: corporation.issuedShares,
|
||||
sharePrice: corporation.sharePrice,
|
||||
state: corporation.state + "",
|
||||
state: corporation.state.getState(),
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
@@ -47,7 +47,7 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
|
||||
|
||||
return {
|
||||
createGang: function (faction: string): boolean {
|
||||
helper.updateDynamicRam("createGang", getRamCost("gang", "createGang"));
|
||||
helper.updateDynamicRam("createGang", getRamCost(player, "gang", "createGang"));
|
||||
// this list is copied from Faction/ui/Root.tsx
|
||||
const GangNames = [
|
||||
"Slum Snakes",
|
||||
@@ -67,18 +67,18 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
|
||||
return true;
|
||||
},
|
||||
inGang: function (): boolean {
|
||||
helper.updateDynamicRam("inGang", getRamCost("gang", "inGang"));
|
||||
helper.updateDynamicRam("inGang", getRamCost(player, "gang", "inGang"));
|
||||
return player.inGang();
|
||||
},
|
||||
getMemberNames: function (): string[] {
|
||||
helper.updateDynamicRam("getMemberNames", getRamCost("gang", "getMemberNames"));
|
||||
helper.updateDynamicRam("getMemberNames", getRamCost(player, "gang", "getMemberNames"));
|
||||
checkGangApiAccess("getMemberNames");
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
return gang.members.map((member) => member.name);
|
||||
},
|
||||
getGangInformation: function (): GangGenInfo {
|
||||
helper.updateDynamicRam("getGangInformation", getRamCost("gang", "getGangInformation"));
|
||||
helper.updateDynamicRam("getGangInformation", getRamCost(player, "gang", "getGangInformation"));
|
||||
checkGangApiAccess("getGangInformation");
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
@@ -98,7 +98,7 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
|
||||
};
|
||||
},
|
||||
getOtherGangInformation: function (): GangOtherInfo {
|
||||
helper.updateDynamicRam("getOtherGangInformation", getRamCost("gang", "getOtherGangInformation"));
|
||||
helper.updateDynamicRam("getOtherGangInformation", getRamCost(player, "gang", "getOtherGangInformation"));
|
||||
checkGangApiAccess("getOtherGangInformation");
|
||||
const cpy: any = {};
|
||||
for (const gang in AllGangs) {
|
||||
@@ -108,7 +108,7 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
|
||||
return cpy;
|
||||
},
|
||||
getMemberInformation: function (name: any): GangMemberInfo {
|
||||
helper.updateDynamicRam("getMemberInformation", getRamCost("gang", "getMemberInformation"));
|
||||
helper.updateDynamicRam("getMemberInformation", getRamCost(player, "gang", "getMemberInformation"));
|
||||
checkGangApiAccess("getMemberInformation");
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
@@ -161,14 +161,14 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
|
||||
};
|
||||
},
|
||||
canRecruitMember: function (): boolean {
|
||||
helper.updateDynamicRam("canRecruitMember", getRamCost("gang", "canRecruitMember"));
|
||||
helper.updateDynamicRam("canRecruitMember", getRamCost(player, "gang", "canRecruitMember"));
|
||||
checkGangApiAccess("canRecruitMember");
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
return gang.canRecruitMember();
|
||||
},
|
||||
recruitMember: function (name: any): boolean {
|
||||
helper.updateDynamicRam("recruitMember", getRamCost("gang", "recruitMember"));
|
||||
helper.updateDynamicRam("recruitMember", getRamCost(player, "gang", "recruitMember"));
|
||||
checkGangApiAccess("recruitMember");
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
@@ -182,7 +182,7 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
|
||||
return recruited;
|
||||
},
|
||||
getTaskNames: function (): string[] {
|
||||
helper.updateDynamicRam("getTaskNames", getRamCost("gang", "getTaskNames"));
|
||||
helper.updateDynamicRam("getTaskNames", getRamCost(player, "gang", "getTaskNames"));
|
||||
checkGangApiAccess("getTaskNames");
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
@@ -191,7 +191,7 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
|
||||
return tasks;
|
||||
},
|
||||
setMemberTask: function (memberName: any, taskName: any): boolean {
|
||||
helper.updateDynamicRam("setMemberTask", getRamCost("gang", "setMemberTask"));
|
||||
helper.updateDynamicRam("setMemberTask", getRamCost(player, "gang", "setMemberTask"));
|
||||
checkGangApiAccess("setMemberTask");
|
||||
const member = getGangMember("setMemberTask", memberName);
|
||||
const success = member.assignToTask(taskName);
|
||||
@@ -210,7 +210,7 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
|
||||
return success;
|
||||
},
|
||||
getTaskStats: function (taskName: any): GangTaskStats {
|
||||
helper.updateDynamicRam("getTaskStats", getRamCost("gang", "getTaskStats"));
|
||||
helper.updateDynamicRam("getTaskStats", getRamCost(player, "gang", "getTaskStats"));
|
||||
checkGangApiAccess("getTaskStats");
|
||||
const task = getGangTask("getTaskStats", taskName);
|
||||
const copy = Object.assign({}, task);
|
||||
@@ -218,12 +218,12 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
|
||||
return copy;
|
||||
},
|
||||
getEquipmentNames: function (): string[] {
|
||||
helper.updateDynamicRam("getEquipmentNames", getRamCost("gang", "getEquipmentNames"));
|
||||
helper.updateDynamicRam("getEquipmentNames", getRamCost(player, "gang", "getEquipmentNames"));
|
||||
checkGangApiAccess("getEquipmentNames");
|
||||
return Object.keys(GangMemberUpgrades);
|
||||
},
|
||||
getEquipmentCost: function (equipName: any): number {
|
||||
helper.updateDynamicRam("getEquipmentCost", getRamCost("gang", "getEquipmentCost"));
|
||||
helper.updateDynamicRam("getEquipmentCost", getRamCost(player, "gang", "getEquipmentCost"));
|
||||
checkGangApiAccess("getEquipmentCost");
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
@@ -232,14 +232,14 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
|
||||
return gang.getUpgradeCost(upg);
|
||||
},
|
||||
getEquipmentType: function (equipName: any): string {
|
||||
helper.updateDynamicRam("getEquipmentType", getRamCost("gang", "getEquipmentType"));
|
||||
helper.updateDynamicRam("getEquipmentType", getRamCost(player, "gang", "getEquipmentType"));
|
||||
checkGangApiAccess("getEquipmentType");
|
||||
const upg = GangMemberUpgrades[equipName];
|
||||
if (upg == null) return "";
|
||||
return upg.getType();
|
||||
},
|
||||
getEquipmentStats: function (equipName: any): EquipmentStats {
|
||||
helper.updateDynamicRam("getEquipmentStats", getRamCost("gang", "getEquipmentStats"));
|
||||
helper.updateDynamicRam("getEquipmentStats", getRamCost(player, "gang", "getEquipmentStats"));
|
||||
checkGangApiAccess("getEquipmentStats");
|
||||
const equipment = GangMemberUpgrades[equipName];
|
||||
if (!equipment) {
|
||||
@@ -249,7 +249,7 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
|
||||
return Object.assign({}, typecheck) as any;
|
||||
},
|
||||
purchaseEquipment: function (memberName: any, equipName: any): boolean {
|
||||
helper.updateDynamicRam("purchaseEquipment", getRamCost("gang", "purchaseEquipment"));
|
||||
helper.updateDynamicRam("purchaseEquipment", getRamCost(player, "gang", "purchaseEquipment"));
|
||||
checkGangApiAccess("purchaseEquipment");
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
@@ -269,7 +269,7 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
|
||||
return res;
|
||||
},
|
||||
ascendMember: function (name: any): GangMemberAscension | undefined {
|
||||
helper.updateDynamicRam("ascendMember", getRamCost("gang", "ascendMember"));
|
||||
helper.updateDynamicRam("ascendMember", getRamCost(player, "gang", "ascendMember"));
|
||||
checkGangApiAccess("ascendMember");
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
@@ -278,7 +278,7 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
|
||||
return gang.ascendMember(member, workerScript);
|
||||
},
|
||||
getAscensionResult: function (name: any): GangMemberAscension | undefined {
|
||||
helper.updateDynamicRam("getAscensionResult", getRamCost("gang", "getAscensionResult"));
|
||||
helper.updateDynamicRam("getAscensionResult", getRamCost(player, "gang", "getAscensionResult"));
|
||||
checkGangApiAccess("getAscensionResult");
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
@@ -290,7 +290,7 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
|
||||
};
|
||||
},
|
||||
setTerritoryWarfare: function (engage: any): void {
|
||||
helper.updateDynamicRam("setTerritoryWarfare", getRamCost("gang", "setTerritoryWarfare"));
|
||||
helper.updateDynamicRam("setTerritoryWarfare", getRamCost(player, "gang", "setTerritoryWarfare"));
|
||||
checkGangApiAccess("setTerritoryWarfare");
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
@@ -303,7 +303,7 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
|
||||
}
|
||||
},
|
||||
getChanceToWinClash: function (otherGang: any): number {
|
||||
helper.updateDynamicRam("getChanceToWinClash", getRamCost("gang", "getChanceToWinClash"));
|
||||
helper.updateDynamicRam("getChanceToWinClash", getRamCost(player, "gang", "getChanceToWinClash"));
|
||||
checkGangApiAccess("getChanceToWinClash");
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
@@ -317,7 +317,7 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
|
||||
return playerPower / (otherPower + playerPower);
|
||||
},
|
||||
getBonusTime: function (): number {
|
||||
helper.updateDynamicRam("getBonusTime", getRamCost("gang", "getBonusTime"));
|
||||
helper.updateDynamicRam("getBonusTime", getRamCost(player, "gang", "getBonusTime"));
|
||||
checkGangApiAccess("getBonusTime");
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
|
||||
@@ -85,15 +85,14 @@ export function NetscriptSingularity(
|
||||
}
|
||||
const runningScriptObj = new RunningScript(script, []); // No args
|
||||
runningScriptObj.threads = 1; // Only 1 thread
|
||||
startWorkerScript(runningScriptObj, home);
|
||||
startWorkerScript(player, runningScriptObj, home);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
return {
|
||||
getOwnedAugmentations: function (purchased: any = false): any {
|
||||
helper.updateDynamicRam("getOwnedAugmentations", getRamCost("getOwnedAugmentations"));
|
||||
helper.checkSingularityAccess("getOwnedAugmentations", 3);
|
||||
helper.updateDynamicRam("getOwnedAugmentations", getRamCost(player, "getOwnedAugmentations"));
|
||||
const res = [];
|
||||
for (let i = 0; i < player.augmentations.length; ++i) {
|
||||
res.push(player.augmentations[i].name);
|
||||
@@ -106,8 +105,7 @@ export function NetscriptSingularity(
|
||||
return res;
|
||||
},
|
||||
getAugmentationsFromFaction: function (facname: any): any {
|
||||
helper.updateDynamicRam("getAugmentationsFromFaction", getRamCost("getAugmentationsFromFaction"));
|
||||
helper.checkSingularityAccess("getAugmentationsFromFaction", 3);
|
||||
helper.updateDynamicRam("getAugmentationsFromFaction", getRamCost(player, "getAugmentationsFromFaction"));
|
||||
const faction = getFaction("getAugmentationsFromFaction", facname);
|
||||
|
||||
// If player has a gang with this faction, return all augmentations.
|
||||
@@ -128,38 +126,32 @@ export function NetscriptSingularity(
|
||||
return faction.augmentations.slice();
|
||||
},
|
||||
getAugmentationCost: function (name: any): any {
|
||||
helper.updateDynamicRam("getAugmentationCost", getRamCost("getAugmentationCost"));
|
||||
helper.checkSingularityAccess("getAugmentationCost", 3);
|
||||
helper.updateDynamicRam("getAugmentationCost", getRamCost(player, "getAugmentationCost"));
|
||||
const aug = getAugmentation("getAugmentationCost", name);
|
||||
return [aug.baseRepRequirement, aug.baseCost];
|
||||
},
|
||||
getAugmentationPrereq: function (name: any): any {
|
||||
helper.updateDynamicRam("getAugmentationPrereq", getRamCost("getAugmentationPrereq"));
|
||||
helper.checkSingularityAccess("getAugmentationPrereq", 3);
|
||||
helper.updateDynamicRam("getAugmentationPrereq", getRamCost(player, "getAugmentationPrereq"));
|
||||
const aug = getAugmentation("getAugmentationPrereq", name);
|
||||
return aug.prereqs.slice();
|
||||
},
|
||||
getAugmentationPrice: function (name: any): any {
|
||||
helper.updateDynamicRam("getAugmentationPrice", getRamCost("getAugmentationPrice"));
|
||||
helper.checkSingularityAccess("getAugmentationPrice", 3);
|
||||
helper.updateDynamicRam("getAugmentationPrice", getRamCost(player, "getAugmentationPrice"));
|
||||
const aug = getAugmentation("getAugmentationPrice", name);
|
||||
return aug.baseCost;
|
||||
},
|
||||
getAugmentationRepReq: function (name: any): any {
|
||||
helper.updateDynamicRam("getAugmentationRepReq", getRamCost("getAugmentationRepReq"));
|
||||
helper.checkSingularityAccess("getAugmentationRepReq", 3);
|
||||
helper.updateDynamicRam("getAugmentationRepReq", getRamCost(player, "getAugmentationRepReq"));
|
||||
const aug = getAugmentation("getAugmentationRepReq", name);
|
||||
return aug.baseRepRequirement;
|
||||
},
|
||||
getAugmentationStats: function (name: any): any {
|
||||
helper.updateDynamicRam("getAugmentationStats", getRamCost("getAugmentationStats"));
|
||||
helper.checkSingularityAccess("getAugmentationStats", 3);
|
||||
helper.updateDynamicRam("getAugmentationStats", getRamCost(player, "getAugmentationStats"));
|
||||
const aug = getAugmentation("getAugmentationStats", name);
|
||||
return Object.assign({}, aug.mults);
|
||||
},
|
||||
purchaseAugmentation: function (faction: any, name: any): any {
|
||||
helper.updateDynamicRam("purchaseAugmentation", getRamCost("purchaseAugmentation"));
|
||||
helper.checkSingularityAccess("purchaseAugmentation", 3);
|
||||
helper.updateDynamicRam("purchaseAugmentation", getRamCost(player, "purchaseAugmentation"));
|
||||
const fac = getFaction("purchaseAugmentation", faction);
|
||||
const aug = getAugmentation("purchaseAugmentation", name);
|
||||
|
||||
@@ -214,8 +206,7 @@ export function NetscriptSingularity(
|
||||
}
|
||||
},
|
||||
softReset: function (cbScript: any): any {
|
||||
helper.updateDynamicRam("softReset", getRamCost("softReset"));
|
||||
helper.checkSingularityAccess("softReset", 3);
|
||||
helper.updateDynamicRam("softReset", getRamCost(player, "softReset"));
|
||||
|
||||
workerScript.log("softReset", () => "Soft resetting. This will cause this script to be killed");
|
||||
setTimeout(() => {
|
||||
@@ -228,8 +219,7 @@ export function NetscriptSingularity(
|
||||
killWorkerScript(workerScript);
|
||||
},
|
||||
installAugmentations: function (cbScript: any): any {
|
||||
helper.updateDynamicRam("installAugmentations", getRamCost("installAugmentations"));
|
||||
helper.checkSingularityAccess("installAugmentations", 3);
|
||||
helper.updateDynamicRam("installAugmentations", getRamCost(player, "installAugmentations"));
|
||||
|
||||
if (player.queuedAugmentations.length === 0) {
|
||||
workerScript.log("installAugmentations", () => "You do not have any Augmentations to be installed.");
|
||||
@@ -250,8 +240,7 @@ export function NetscriptSingularity(
|
||||
},
|
||||
|
||||
goToLocation: function (locationName: any): boolean {
|
||||
helper.updateDynamicRam("goToLocation", getRamCost("goToLocation"));
|
||||
helper.checkSingularityAccess("goToLocation", 1);
|
||||
helper.updateDynamicRam("goToLocation", getRamCost(player, "goToLocation"));
|
||||
const location = Object.values(Locations).find((l) => l.name === locationName);
|
||||
if (!location) {
|
||||
workerScript.log("goToLocation", () => `No location named ${locationName}`);
|
||||
@@ -266,8 +255,7 @@ export function NetscriptSingularity(
|
||||
return true;
|
||||
},
|
||||
universityCourse: function (universityName: any, className: any): any {
|
||||
helper.updateDynamicRam("universityCourse", getRamCost("universityCourse"));
|
||||
helper.checkSingularityAccess("universityCourse", 1);
|
||||
helper.updateDynamicRam("universityCourse", getRamCost(player, "universityCourse"));
|
||||
if (player.isWorking) {
|
||||
const txt = player.singularityStopWork();
|
||||
workerScript.log("universityCourse", () => txt);
|
||||
@@ -346,8 +334,7 @@ export function NetscriptSingularity(
|
||||
},
|
||||
|
||||
gymWorkout: function (gymName: any, stat: any): any {
|
||||
helper.updateDynamicRam("gymWorkout", getRamCost("gymWorkout"));
|
||||
helper.checkSingularityAccess("gymWorkout", 1);
|
||||
helper.updateDynamicRam("gymWorkout", getRamCost(player, "gymWorkout"));
|
||||
if (player.isWorking) {
|
||||
const txt = player.singularityStopWork();
|
||||
workerScript.log("gymWorkout", () => txt);
|
||||
@@ -445,8 +432,7 @@ export function NetscriptSingularity(
|
||||
},
|
||||
|
||||
travelToCity: function (cityname: any): any {
|
||||
helper.updateDynamicRam("travelToCity", getRamCost("travelToCity"));
|
||||
helper.checkSingularityAccess("travelToCity", 1);
|
||||
helper.updateDynamicRam("travelToCity", getRamCost(player, "travelToCity"));
|
||||
|
||||
switch (cityname) {
|
||||
case CityName.Aevum:
|
||||
@@ -470,8 +456,7 @@ export function NetscriptSingularity(
|
||||
},
|
||||
|
||||
purchaseTor: function (): any {
|
||||
helper.updateDynamicRam("purchaseTor", getRamCost("purchaseTor"));
|
||||
helper.checkSingularityAccess("purchaseTor", 1);
|
||||
helper.updateDynamicRam("purchaseTor", getRamCost(player, "purchaseTor"));
|
||||
|
||||
if (player.hasTorRouter()) {
|
||||
workerScript.log("purchaseTor", () => "You already have a TOR router!");
|
||||
@@ -502,8 +487,7 @@ export function NetscriptSingularity(
|
||||
return true;
|
||||
},
|
||||
purchaseProgram: function (programName: any): any {
|
||||
helper.updateDynamicRam("purchaseProgram", getRamCost("purchaseProgram"));
|
||||
helper.checkSingularityAccess("purchaseProgram", 1);
|
||||
helper.updateDynamicRam("purchaseProgram", getRamCost(player, "purchaseProgram"));
|
||||
|
||||
if (!player.hasTorRouter()) {
|
||||
workerScript.log("purchaseProgram", () => "You do not have the TOR router.");
|
||||
@@ -541,13 +525,11 @@ export function NetscriptSingularity(
|
||||
return true;
|
||||
},
|
||||
getCurrentServer: function (): any {
|
||||
helper.updateDynamicRam("getCurrentServer", getRamCost("getCurrentServer"));
|
||||
helper.checkSingularityAccess("getCurrentServer", 1);
|
||||
helper.updateDynamicRam("getCurrentServer", getRamCost(player, "getCurrentServer"));
|
||||
return player.getCurrentServer().hostname;
|
||||
},
|
||||
connect: function (hostname: any): any {
|
||||
helper.updateDynamicRam("connect", getRamCost("connect"));
|
||||
helper.checkSingularityAccess("connect", 1);
|
||||
helper.updateDynamicRam("connect", getRamCost(player, "connect"));
|
||||
if (!hostname) {
|
||||
throw helper.makeRuntimeErrorMsg("connect", `Invalid hostname: '${hostname}'`);
|
||||
}
|
||||
@@ -581,14 +563,12 @@ export function NetscriptSingularity(
|
||||
return false;
|
||||
},
|
||||
manualHack: function (): any {
|
||||
helper.updateDynamicRam("manualHack", getRamCost("manualHack"));
|
||||
helper.checkSingularityAccess("manualHack", 1);
|
||||
helper.updateDynamicRam("manualHack", getRamCost(player, "manualHack"));
|
||||
const server = player.getCurrentServer();
|
||||
return helper.hack(server.hostname, true);
|
||||
},
|
||||
installBackdoor: function (): any {
|
||||
helper.updateDynamicRam("installBackdoor", getRamCost("installBackdoor"));
|
||||
helper.checkSingularityAccess("installBackdoor", 1);
|
||||
helper.updateDynamicRam("installBackdoor", getRamCost(player, "installBackdoor"));
|
||||
const baseserver = player.getCurrentServer();
|
||||
if (!(baseserver instanceof Server)) {
|
||||
workerScript.log("installBackdoor", () => "cannot backdoor this kind of server");
|
||||
@@ -623,14 +603,12 @@ export function NetscriptSingularity(
|
||||
});
|
||||
},
|
||||
isFocused: function (): boolean {
|
||||
helper.updateDynamicRam("isFocused", getRamCost("isFocused"));
|
||||
helper.checkSingularityAccess("isFocused", 2);
|
||||
helper.updateDynamicRam("isFocused", getRamCost(player, "isFocused"));
|
||||
return player.focus;
|
||||
},
|
||||
setFocus: function (afocus: any): boolean {
|
||||
const focus = helper.boolean(afocus);
|
||||
helper.updateDynamicRam("setFocus", getRamCost("setFocus"));
|
||||
helper.checkSingularityAccess("setFocus", 2);
|
||||
helper.updateDynamicRam("setFocus", getRamCost(player, "setFocus"));
|
||||
if (!player.isWorking) {
|
||||
throw helper.makeRuntimeErrorMsg("setFocus", "Not currently working");
|
||||
}
|
||||
@@ -655,8 +633,7 @@ export function NetscriptSingularity(
|
||||
return false;
|
||||
},
|
||||
getStats: function (): any {
|
||||
helper.updateDynamicRam("getStats", getRamCost("getStats"));
|
||||
helper.checkSingularityAccess("getStats", 1);
|
||||
helper.updateDynamicRam("getStats", getRamCost(player, "getStats"));
|
||||
workerScript.log("getStats", () => `getStats is deprecated, please use getplayer`);
|
||||
|
||||
return {
|
||||
@@ -670,8 +647,7 @@ export function NetscriptSingularity(
|
||||
};
|
||||
},
|
||||
getCharacterInformation: function (): any {
|
||||
helper.updateDynamicRam("getCharacterInformation", getRamCost("getCharacterInformation"));
|
||||
helper.checkSingularityAccess("getCharacterInformation", 1);
|
||||
helper.updateDynamicRam("getCharacterInformation", getRamCost(player, "getCharacterInformation"));
|
||||
workerScript.log("getCharacterInformation", () => `getCharacterInformation is deprecated, please use getplayer`);
|
||||
|
||||
return {
|
||||
@@ -718,8 +694,7 @@ export function NetscriptSingularity(
|
||||
};
|
||||
},
|
||||
hospitalize: function (): any {
|
||||
helper.updateDynamicRam("hospitalize", getRamCost("hospitalize"));
|
||||
helper.checkSingularityAccess("hospitalize", 1);
|
||||
helper.updateDynamicRam("hospitalize", getRamCost(player, "hospitalize"));
|
||||
if (player.isWorking || Router.page() === Page.Infiltration || Router.page() === Page.BitVerse) {
|
||||
workerScript.log("hospitalize", () => "Cannot go to the hospital because the player is busy.");
|
||||
return;
|
||||
@@ -727,13 +702,11 @@ export function NetscriptSingularity(
|
||||
return player.hospitalize();
|
||||
},
|
||||
isBusy: function (): any {
|
||||
helper.updateDynamicRam("isBusy", getRamCost("isBusy"));
|
||||
helper.checkSingularityAccess("isBusy", 1);
|
||||
helper.updateDynamicRam("isBusy", getRamCost(player, "isBusy"));
|
||||
return player.isWorking || Router.page() === Page.Infiltration || Router.page() === Page.BitVerse;
|
||||
},
|
||||
stopAction: function (): any {
|
||||
helper.updateDynamicRam("stopAction", getRamCost("stopAction"));
|
||||
helper.checkSingularityAccess("stopAction", 1);
|
||||
helper.updateDynamicRam("stopAction", getRamCost(player, "stopAction"));
|
||||
if (player.isWorking) {
|
||||
if (player.focus) {
|
||||
Router.toTerminal();
|
||||
@@ -745,8 +718,7 @@ export function NetscriptSingularity(
|
||||
return false;
|
||||
},
|
||||
upgradeHomeCores: function (): any {
|
||||
helper.updateDynamicRam("upgradeHomeCores", getRamCost("upgradeHomeCores"));
|
||||
helper.checkSingularityAccess("upgradeHomeCores", 2);
|
||||
helper.updateDynamicRam("upgradeHomeCores", getRamCost(player, "upgradeHomeCores"));
|
||||
|
||||
// Check if we're at max cores
|
||||
const homeComputer = player.getHomeComputer();
|
||||
@@ -775,14 +747,12 @@ export function NetscriptSingularity(
|
||||
return true;
|
||||
},
|
||||
getUpgradeHomeCoresCost: function (): any {
|
||||
helper.updateDynamicRam("getUpgradeHomeCoresCost", getRamCost("getUpgradeHomeCoresCost"));
|
||||
helper.checkSingularityAccess("getUpgradeHomeCoresCost", 2);
|
||||
helper.updateDynamicRam("getUpgradeHomeCoresCost", getRamCost(player, "getUpgradeHomeCoresCost"));
|
||||
|
||||
return player.getUpgradeHomeCoresCost();
|
||||
},
|
||||
upgradeHomeRam: function (): any {
|
||||
helper.updateDynamicRam("upgradeHomeRam", getRamCost("upgradeHomeRam"));
|
||||
helper.checkSingularityAccess("upgradeHomeRam", 2);
|
||||
helper.updateDynamicRam("upgradeHomeRam", getRamCost(player, "upgradeHomeRam"));
|
||||
|
||||
// Check if we're at max RAM
|
||||
const homeComputer = player.getHomeComputer();
|
||||
@@ -814,14 +784,12 @@ export function NetscriptSingularity(
|
||||
return true;
|
||||
},
|
||||
getUpgradeHomeRamCost: function (): any {
|
||||
helper.updateDynamicRam("getUpgradeHomeRamCost", getRamCost("getUpgradeHomeRamCost"));
|
||||
helper.checkSingularityAccess("getUpgradeHomeRamCost", 2);
|
||||
helper.updateDynamicRam("getUpgradeHomeRamCost", getRamCost(player, "getUpgradeHomeRamCost"));
|
||||
|
||||
return player.getUpgradeHomeRamCost();
|
||||
},
|
||||
workForCompany: function (companyName: any): any {
|
||||
helper.updateDynamicRam("workForCompany", getRamCost("workForCompany"));
|
||||
helper.checkSingularityAccess("workForCompany", 2);
|
||||
workForCompany: function (companyName: any, focus = true): any {
|
||||
helper.updateDynamicRam("workForCompany", getRamCost(player, "workForCompany"));
|
||||
|
||||
// Sanitize input
|
||||
if (companyName == null) {
|
||||
@@ -848,7 +816,6 @@ export function NetscriptSingularity(
|
||||
return false;
|
||||
}
|
||||
|
||||
const wasWorking = player.isWorking;
|
||||
const wasFocused = player.focus;
|
||||
if (player.isWorking) {
|
||||
const txt = player.singularityStopWork();
|
||||
@@ -861,8 +828,13 @@ export function NetscriptSingularity(
|
||||
player.startWork(companyName);
|
||||
}
|
||||
|
||||
if (!wasWorking || (wasWorking && !wasFocused)) player.stopFocusing();
|
||||
else if (wasWorking && wasFocused) player.startFocusing();
|
||||
if (focus) {
|
||||
player.startFocusing();
|
||||
Router.toWork();
|
||||
} else if (wasFocused) {
|
||||
player.stopFocusing();
|
||||
Router.toTerminal();
|
||||
}
|
||||
workerScript.log(
|
||||
"workForCompany",
|
||||
() => `Began working at '${player.companyName}' as a '${companyPositionName}'`,
|
||||
@@ -870,8 +842,7 @@ export function NetscriptSingularity(
|
||||
return true;
|
||||
},
|
||||
applyToCompany: function (companyName: any, field: any): any {
|
||||
helper.updateDynamicRam("applyToCompany", getRamCost("applyToCompany"));
|
||||
helper.checkSingularityAccess("applyToCompany", 2);
|
||||
helper.updateDynamicRam("applyToCompany", getRamCost(player, "applyToCompany"));
|
||||
getCompany("applyToCompany", companyName);
|
||||
|
||||
player.location = companyName;
|
||||
@@ -940,32 +911,27 @@ export function NetscriptSingularity(
|
||||
return res;
|
||||
},
|
||||
getCompanyRep: function (companyName: any): any {
|
||||
helper.updateDynamicRam("getCompanyRep", getRamCost("getCompanyRep"));
|
||||
helper.checkSingularityAccess("getCompanyRep", 2);
|
||||
helper.updateDynamicRam("getCompanyRep", getRamCost(player, "getCompanyRep"));
|
||||
const company = getCompany("getCompanyRep", companyName);
|
||||
return company.playerReputation;
|
||||
},
|
||||
getCompanyFavor: function (companyName: any): any {
|
||||
helper.updateDynamicRam("getCompanyFavor", getRamCost("getCompanyFavor"));
|
||||
helper.checkSingularityAccess("getCompanyFavor", 2);
|
||||
helper.updateDynamicRam("getCompanyFavor", getRamCost(player, "getCompanyFavor"));
|
||||
const company = getCompany("getCompanyFavor", companyName);
|
||||
return company.favor;
|
||||
},
|
||||
getCompanyFavorGain: function (companyName: any): any {
|
||||
helper.updateDynamicRam("getCompanyFavorGain", getRamCost("getCompanyFavorGain"));
|
||||
helper.checkSingularityAccess("getCompanyFavorGain", 2);
|
||||
helper.updateDynamicRam("getCompanyFavorGain", getRamCost(player, "getCompanyFavorGain"));
|
||||
const company = getCompany("getCompanyFavorGain", companyName);
|
||||
return company.getFavorGain();
|
||||
},
|
||||
checkFactionInvitations: function (): any {
|
||||
helper.updateDynamicRam("checkFactionInvitations", getRamCost("checkFactionInvitations"));
|
||||
helper.checkSingularityAccess("checkFactionInvitations", 2);
|
||||
helper.updateDynamicRam("checkFactionInvitations", getRamCost(player, "checkFactionInvitations"));
|
||||
// Make a copy of player.factionInvitations
|
||||
return player.factionInvitations.slice();
|
||||
},
|
||||
joinFaction: function (name: any): any {
|
||||
helper.updateDynamicRam("joinFaction", getRamCost("joinFaction"));
|
||||
helper.checkSingularityAccess("joinFaction", 2);
|
||||
helper.updateDynamicRam("joinFaction", getRamCost(player, "joinFaction"));
|
||||
getFaction("joinFaction", name);
|
||||
|
||||
if (!player.factionInvitations.includes(name)) {
|
||||
@@ -986,9 +952,8 @@ export function NetscriptSingularity(
|
||||
workerScript.log("joinFaction", () => `Joined the '${name}' faction.`);
|
||||
return true;
|
||||
},
|
||||
workForFaction: function (name: any, type: any): any {
|
||||
helper.updateDynamicRam("workForFaction", getRamCost("workForFaction"));
|
||||
helper.checkSingularityAccess("workForFaction", 2);
|
||||
workForFaction: function (name: any, type: any, focus = true): any {
|
||||
helper.updateDynamicRam("workForFaction", getRamCost(player, "workForFaction"));
|
||||
getFaction("workForFaction", name);
|
||||
|
||||
// if the player is in a gang and the target faction is any of the gang faction, fail
|
||||
@@ -1002,8 +967,7 @@ export function NetscriptSingularity(
|
||||
return false;
|
||||
}
|
||||
|
||||
const wasWorking = player.isWorking;
|
||||
const wasFocused = player.focus;
|
||||
const wasFocusing = player.focus;
|
||||
if (player.isWorking) {
|
||||
const txt = player.singularityStopWork();
|
||||
workerScript.log("workForFaction", () => txt);
|
||||
@@ -1102,8 +1066,13 @@ export function NetscriptSingularity(
|
||||
return false;
|
||||
}
|
||||
player.startFactionHackWork(fac);
|
||||
if (!wasWorking || (wasWorking && !wasFocused)) player.stopFocusing();
|
||||
else if (wasWorking && wasFocused) player.startFocusing();
|
||||
if (focus) {
|
||||
player.startFocusing();
|
||||
Router.toWork();
|
||||
} else if (wasFocusing) {
|
||||
player.stopFocusing();
|
||||
Router.toTerminal();
|
||||
}
|
||||
workerScript.log("workForFaction", () => `Started carrying out hacking contracts for '${fac.name}'`);
|
||||
return true;
|
||||
case "field":
|
||||
@@ -1114,8 +1083,13 @@ export function NetscriptSingularity(
|
||||
return false;
|
||||
}
|
||||
player.startFactionFieldWork(fac);
|
||||
if (!wasWorking || (wasWorking && !wasFocused)) player.stopFocusing();
|
||||
else if (wasWorking && wasFocused) player.startFocusing();
|
||||
if (focus) {
|
||||
player.startFocusing();
|
||||
Router.toWork();
|
||||
} else if (wasFocusing) {
|
||||
player.stopFocusing();
|
||||
Router.toTerminal();
|
||||
}
|
||||
workerScript.log("workForFaction", () => `Started carrying out field missions for '${fac.name}'`);
|
||||
return true;
|
||||
case "security":
|
||||
@@ -1126,8 +1100,13 @@ export function NetscriptSingularity(
|
||||
return false;
|
||||
}
|
||||
player.startFactionSecurityWork(fac);
|
||||
if (!wasWorking || (wasWorking && !wasFocused)) player.stopFocusing();
|
||||
else if (wasWorking && wasFocused) player.startFocusing();
|
||||
if (focus) {
|
||||
player.startFocusing();
|
||||
Router.toWork();
|
||||
} else if (wasFocusing) {
|
||||
player.stopFocusing();
|
||||
Router.toTerminal();
|
||||
}
|
||||
workerScript.log("workForFaction", () => `Started carrying out security work for '${fac.name}'`);
|
||||
return true;
|
||||
default:
|
||||
@@ -1136,26 +1115,22 @@ export function NetscriptSingularity(
|
||||
return true;
|
||||
},
|
||||
getFactionRep: function (name: any): any {
|
||||
helper.updateDynamicRam("getFactionRep", getRamCost("getFactionRep"));
|
||||
helper.checkSingularityAccess("getFactionRep", 2);
|
||||
helper.updateDynamicRam("getFactionRep", getRamCost(player, "getFactionRep"));
|
||||
const faction = getFaction("getFactionRep", name);
|
||||
return faction.playerReputation;
|
||||
},
|
||||
getFactionFavor: function (name: any): any {
|
||||
helper.updateDynamicRam("getFactionFavor", getRamCost("getFactionFavor"));
|
||||
helper.checkSingularityAccess("getFactionFavor", 2);
|
||||
helper.updateDynamicRam("getFactionFavor", getRamCost(player, "getFactionFavor"));
|
||||
const faction = getFaction("getFactionFavor", name);
|
||||
return faction.favor;
|
||||
},
|
||||
getFactionFavorGain: function (name: any): any {
|
||||
helper.updateDynamicRam("getFactionFavorGain", getRamCost("getFactionFavorGain"));
|
||||
helper.checkSingularityAccess("getFactionFavorGain", 2);
|
||||
helper.updateDynamicRam("getFactionFavorGain", getRamCost(player, "getFactionFavorGain"));
|
||||
const faction = getFaction("getFactionFavorGain", name);
|
||||
return faction.getFavorGain();
|
||||
},
|
||||
donateToFaction: function (name: any, amt: any): any {
|
||||
helper.updateDynamicRam("donateToFaction", getRamCost("donateToFaction"));
|
||||
helper.checkSingularityAccess("donateToFaction", 3);
|
||||
helper.updateDynamicRam("donateToFaction", getRamCost(player, "donateToFaction"));
|
||||
const faction = getFaction("donateToFaction", name);
|
||||
|
||||
if (typeof amt !== "number" || amt <= 0) {
|
||||
@@ -1191,8 +1166,7 @@ export function NetscriptSingularity(
|
||||
return true;
|
||||
},
|
||||
createProgram: function (name: any): any {
|
||||
helper.updateDynamicRam("createProgram", getRamCost("createProgram"));
|
||||
helper.checkSingularityAccess("createProgram", 3);
|
||||
helper.updateDynamicRam("createProgram", getRamCost(player, "createProgram"));
|
||||
|
||||
if (player.isWorking) {
|
||||
const txt = player.singularityStopWork();
|
||||
@@ -1232,8 +1206,7 @@ export function NetscriptSingularity(
|
||||
return true;
|
||||
},
|
||||
commitCrime: function (crimeRoughName: any): any {
|
||||
helper.updateDynamicRam("commitCrime", getRamCost("commitCrime"));
|
||||
helper.checkSingularityAccess("commitCrime", 3);
|
||||
helper.updateDynamicRam("commitCrime", getRamCost(player, "commitCrime"));
|
||||
|
||||
if (player.isWorking) {
|
||||
const txt = player.singularityStopWork();
|
||||
@@ -1252,8 +1225,7 @@ export function NetscriptSingularity(
|
||||
return crime.commit(Router, player, 1, workerScript);
|
||||
},
|
||||
getCrimeChance: function (crimeRoughName: any): any {
|
||||
helper.updateDynamicRam("getCrimeChance", getRamCost("getCrimeChance"));
|
||||
helper.checkSingularityAccess("getCrimeChance", 3);
|
||||
helper.updateDynamicRam("getCrimeChance", getRamCost(player, "getCrimeChance"));
|
||||
|
||||
const crime = findCrime(crimeRoughName.toLowerCase());
|
||||
if (crime == null) {
|
||||
@@ -1263,8 +1235,7 @@ export function NetscriptSingularity(
|
||||
return crime.successRate(player);
|
||||
},
|
||||
getCrimeStats: function (crimeRoughName: any): any {
|
||||
helper.updateDynamicRam("getCrimeStats", getRamCost("getCrimeStats"));
|
||||
helper.checkSingularityAccess("getCrimeStats", 3);
|
||||
helper.updateDynamicRam("getCrimeStats", getRamCost(player, "getCrimeStats"));
|
||||
|
||||
const crime = findCrime(crimeRoughName.toLowerCase());
|
||||
if (crime == null) {
|
||||
|
||||
@@ -32,20 +32,20 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel
|
||||
|
||||
return {
|
||||
getNumSleeves: function (): number {
|
||||
helper.updateDynamicRam("getNumSleeves", getRamCost("sleeve", "getNumSleeves"));
|
||||
helper.updateDynamicRam("getNumSleeves", getRamCost(player, "sleeve", "getNumSleeves"));
|
||||
checkSleeveAPIAccess("getNumSleeves");
|
||||
return player.sleeves.length;
|
||||
},
|
||||
setToShockRecovery: function (asleeveNumber: any = 0): boolean {
|
||||
const sleeveNumber = helper.number("setToShockRecovery", "sleeveNumber", asleeveNumber);
|
||||
helper.updateDynamicRam("setToShockRecovery", getRamCost("sleeve", "setToShockRecovery"));
|
||||
helper.updateDynamicRam("setToShockRecovery", getRamCost(player, "sleeve", "setToShockRecovery"));
|
||||
checkSleeveAPIAccess("setToShockRecovery");
|
||||
checkSleeveNumber("setToShockRecovery", sleeveNumber);
|
||||
return player.sleeves[sleeveNumber].shockRecovery(player);
|
||||
},
|
||||
setToSynchronize: function (asleeveNumber: any = 0): boolean {
|
||||
const sleeveNumber = helper.number("setToSynchronize", "sleeveNumber", asleeveNumber);
|
||||
helper.updateDynamicRam("setToSynchronize", getRamCost("sleeve", "setToSynchronize"));
|
||||
helper.updateDynamicRam("setToSynchronize", getRamCost(player, "sleeve", "setToSynchronize"));
|
||||
checkSleeveAPIAccess("setToSynchronize");
|
||||
checkSleeveNumber("setToSynchronize", sleeveNumber);
|
||||
return player.sleeves[sleeveNumber].synchronize(player);
|
||||
@@ -53,7 +53,7 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel
|
||||
setToCommitCrime: function (asleeveNumber: any = 0, aCrimeRoughName: any = ""): boolean {
|
||||
const sleeveNumber = helper.number("setToCommitCrime", "sleeveNumber", asleeveNumber);
|
||||
const crimeRoughName = helper.string("setToCommitCrime", "crimeName", aCrimeRoughName);
|
||||
helper.updateDynamicRam("setToCommitCrime", getRamCost("sleeve", "setToCommitCrime"));
|
||||
helper.updateDynamicRam("setToCommitCrime", getRamCost(player, "sleeve", "setToCommitCrime"));
|
||||
checkSleeveAPIAccess("setToCommitCrime");
|
||||
checkSleeveNumber("setToCommitCrime", sleeveNumber);
|
||||
const crime = findCrime(crimeRoughName);
|
||||
@@ -66,7 +66,7 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel
|
||||
const sleeveNumber = helper.number("setToUniversityCourse", "sleeveNumber", asleeveNumber);
|
||||
const universityName = helper.string("setToUniversityCourse", "universityName", auniversityName);
|
||||
const className = helper.string("setToUniversityCourse", "className", aclassName);
|
||||
helper.updateDynamicRam("setToUniversityCourse", getRamCost("sleeve", "setToUniversityCourse"));
|
||||
helper.updateDynamicRam("setToUniversityCourse", getRamCost(player, "sleeve", "setToUniversityCourse"));
|
||||
checkSleeveAPIAccess("setToUniversityCourse");
|
||||
checkSleeveNumber("setToUniversityCourse", sleeveNumber);
|
||||
return player.sleeves[sleeveNumber].takeUniversityCourse(player, universityName, className);
|
||||
@@ -74,7 +74,7 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel
|
||||
travel: function (asleeveNumber: any = 0, acityName: any = ""): boolean {
|
||||
const sleeveNumber = helper.number("travel", "sleeveNumber", asleeveNumber);
|
||||
const cityName = helper.string("setToUniversityCourse", "cityName", acityName);
|
||||
helper.updateDynamicRam("travel", getRamCost("sleeve", "travel"));
|
||||
helper.updateDynamicRam("travel", getRamCost(player, "sleeve", "travel"));
|
||||
checkSleeveAPIAccess("travel");
|
||||
checkSleeveNumber("travel", sleeveNumber);
|
||||
return player.sleeves[sleeveNumber].travel(player, cityName as CityName);
|
||||
@@ -82,7 +82,7 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel
|
||||
setToCompanyWork: function (asleeveNumber: any = 0, acompanyName: any = ""): boolean {
|
||||
const sleeveNumber = helper.number("setToCompanyWork", "sleeveNumber", asleeveNumber);
|
||||
const companyName = helper.string("setToUniversityCourse", "companyName", acompanyName);
|
||||
helper.updateDynamicRam("setToCompanyWork", getRamCost("sleeve", "setToCompanyWork"));
|
||||
helper.updateDynamicRam("setToCompanyWork", getRamCost(player, "sleeve", "setToCompanyWork"));
|
||||
checkSleeveAPIAccess("setToCompanyWork");
|
||||
checkSleeveNumber("setToCompanyWork", sleeveNumber);
|
||||
|
||||
@@ -106,7 +106,7 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel
|
||||
const sleeveNumber = helper.number("setToFactionWork", "sleeveNumber", asleeveNumber);
|
||||
const factionName = helper.string("setToUniversityCourse", "factionName", afactionName);
|
||||
const workType = helper.string("setToUniversityCourse", "workType", aworkType);
|
||||
helper.updateDynamicRam("setToFactionWork", getRamCost("sleeve", "setToFactionWork"));
|
||||
helper.updateDynamicRam("setToFactionWork", getRamCost(player, "sleeve", "setToFactionWork"));
|
||||
checkSleeveAPIAccess("setToFactionWork");
|
||||
checkSleeveNumber("setToFactionWork", sleeveNumber);
|
||||
|
||||
@@ -130,7 +130,7 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel
|
||||
const sleeveNumber = helper.number("setToGymWorkout", "sleeveNumber", asleeveNumber);
|
||||
const gymName = helper.string("setToUniversityCourse", "gymName", agymName);
|
||||
const stat = helper.string("setToUniversityCourse", "stat", astat);
|
||||
helper.updateDynamicRam("setToGymWorkout", getRamCost("sleeve", "setToGymWorkout"));
|
||||
helper.updateDynamicRam("setToGymWorkout", getRamCost(player, "sleeve", "setToGymWorkout"));
|
||||
checkSleeveAPIAccess("setToGymWorkout");
|
||||
checkSleeveNumber("setToGymWorkout", sleeveNumber);
|
||||
|
||||
@@ -147,7 +147,7 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel
|
||||
charisma: number;
|
||||
} {
|
||||
const sleeveNumber = helper.number("getSleeveStats", "sleeveNumber", asleeveNumber);
|
||||
helper.updateDynamicRam("getSleeveStats", getRamCost("sleeve", "getSleeveStats"));
|
||||
helper.updateDynamicRam("getSleeveStats", getRamCost(player, "sleeve", "getSleeveStats"));
|
||||
checkSleeveAPIAccess("getSleeveStats");
|
||||
checkSleeveNumber("getSleeveStats", sleeveNumber);
|
||||
|
||||
@@ -171,7 +171,7 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel
|
||||
factionWorkType: string;
|
||||
} {
|
||||
const sleeveNumber = helper.number("getTask", "sleeveNumber", asleeveNumber);
|
||||
helper.updateDynamicRam("getTask", getRamCost("sleeve", "getTask"));
|
||||
helper.updateDynamicRam("getTask", getRamCost(player, "sleeve", "getTask"));
|
||||
checkSleeveAPIAccess("getTask");
|
||||
checkSleeveNumber("getTask", sleeveNumber);
|
||||
|
||||
@@ -186,7 +186,7 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel
|
||||
},
|
||||
getInformation: function (asleeveNumber: any = 0): any {
|
||||
const sleeveNumber = helper.number("getInformation", "sleeveNumber", asleeveNumber);
|
||||
helper.updateDynamicRam("getInformation", getRamCost("sleeve", "getInformation"));
|
||||
helper.updateDynamicRam("getInformation", getRamCost(player, "sleeve", "getInformation"));
|
||||
checkSleeveAPIAccess("getInformation");
|
||||
checkSleeveNumber("getInformation", sleeveNumber);
|
||||
|
||||
@@ -251,7 +251,7 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel
|
||||
},
|
||||
getSleeveAugmentations: function (asleeveNumber: any = 0): string[] {
|
||||
const sleeveNumber = helper.number("getSleeveAugmentations", "sleeveNumber", asleeveNumber);
|
||||
helper.updateDynamicRam("getSleeveAugmentations", getRamCost("sleeve", "getSleeveAugmentations"));
|
||||
helper.updateDynamicRam("getSleeveAugmentations", getRamCost(player, "sleeve", "getSleeveAugmentations"));
|
||||
checkSleeveAPIAccess("getSleeveAugmentations");
|
||||
checkSleeveNumber("getSleeveAugmentations", sleeveNumber);
|
||||
|
||||
@@ -266,7 +266,7 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel
|
||||
cost: number;
|
||||
}[] {
|
||||
const sleeveNumber = helper.number("getSleevePurchasableAugs", "sleeveNumber", asleeveNumber);
|
||||
helper.updateDynamicRam("getSleevePurchasableAugs", getRamCost("sleeve", "getSleevePurchasableAugs"));
|
||||
helper.updateDynamicRam("getSleevePurchasableAugs", getRamCost(player, "sleeve", "getSleevePurchasableAugs"));
|
||||
checkSleeveAPIAccess("getSleevePurchasableAugs");
|
||||
checkSleeveNumber("getSleevePurchasableAugs", sleeveNumber);
|
||||
|
||||
@@ -285,7 +285,7 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel
|
||||
purchaseSleeveAug: function (asleeveNumber: any = 0, aaugName: any = ""): boolean {
|
||||
const sleeveNumber = helper.number("purchaseSleeveAug", "sleeveNumber", asleeveNumber);
|
||||
const augName = helper.string("setToUniversityCourse", "augName", aaugName);
|
||||
helper.updateDynamicRam("purchaseSleeveAug", getRamCost("sleeve", "purchaseSleeveAug"));
|
||||
helper.updateDynamicRam("purchaseSleeveAug", getRamCost(player, "sleeve", "purchaseSleeveAug"));
|
||||
checkSleeveAPIAccess("purchaseSleeveAug");
|
||||
checkSleeveNumber("purchaseSleeveAug", sleeveNumber);
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ export function NetscriptStanek(player: IPlayer, workerScript: WorkerScript, hel
|
||||
const rootX = helper.number("stanek.charge", "rootX", arootX);
|
||||
const rootY = helper.number("stanek.charge", "rootY", arootY);
|
||||
|
||||
helper.updateDynamicRam("charge", getRamCost("stanek", "charge"));
|
||||
helper.updateDynamicRam("charge", getRamCost(player, "stanek", "charge"));
|
||||
checkStanekAPIAccess("charge");
|
||||
const fragment = staneksGift.findFragment(rootX, rootY);
|
||||
if (!fragment) throw helper.makeRuntimeErrorMsg("stanek.charge", `No fragment with root (${rootX}, ${rootY}).`);
|
||||
@@ -47,13 +47,13 @@ export function NetscriptStanek(player: IPlayer, workerScript: WorkerScript, hel
|
||||
});
|
||||
},
|
||||
fragmentDefinitions: function (): IFragment[] {
|
||||
helper.updateDynamicRam("fragmentDefinitions", getRamCost("stanek", "fragmentDefinitions"));
|
||||
helper.updateDynamicRam("fragmentDefinitions", getRamCost(player, "stanek", "fragmentDefinitions"));
|
||||
checkStanekAPIAccess("fragmentDefinitions");
|
||||
workerScript.log("stanek.fragmentDefinitions", () => `Returned ${Fragments.length} fragments`);
|
||||
return Fragments.map((f) => f.copy());
|
||||
},
|
||||
activeFragments: function (): IActiveFragment[] {
|
||||
helper.updateDynamicRam("activeFragments", getRamCost("stanek", "activeFragments"));
|
||||
helper.updateDynamicRam("activeFragments", getRamCost(player, "stanek", "activeFragments"));
|
||||
checkStanekAPIAccess("activeFragments");
|
||||
workerScript.log("stanek.activeFragments", () => `Returned ${staneksGift.fragments.length} fragments`);
|
||||
return staneksGift.fragments.map((af) => {
|
||||
@@ -61,7 +61,7 @@ export function NetscriptStanek(player: IPlayer, workerScript: WorkerScript, hel
|
||||
});
|
||||
},
|
||||
clear: function (): void {
|
||||
helper.updateDynamicRam("clear", getRamCost("stanek", "clear"));
|
||||
helper.updateDynamicRam("clear", getRamCost(player, "stanek", "clear"));
|
||||
checkStanekAPIAccess("clear");
|
||||
workerScript.log("stanek.clear", () => `Cleared Stanek's Gift.`);
|
||||
staneksGift.clear();
|
||||
@@ -71,7 +71,7 @@ export function NetscriptStanek(player: IPlayer, workerScript: WorkerScript, hel
|
||||
const rootY = helper.number("stanek.canPlace", "rootY", arootY);
|
||||
const rotation = helper.number("stanek.canPlace", "rotation", arotation);
|
||||
const fragmentId = helper.number("stanek.canPlace", "fragmentId", afragmentId);
|
||||
helper.updateDynamicRam("canPlace", getRamCost("stanek", "canPlace"));
|
||||
helper.updateDynamicRam("canPlace", getRamCost(player, "stanek", "canPlace"));
|
||||
checkStanekAPIAccess("canPlace");
|
||||
const fragment = FragmentById(fragmentId);
|
||||
if (!fragment) throw helper.makeRuntimeErrorMsg("stanek.canPlace", `Invalid fragment id: ${fragmentId}`);
|
||||
@@ -83,7 +83,7 @@ export function NetscriptStanek(player: IPlayer, workerScript: WorkerScript, hel
|
||||
const rootY = helper.number("stanek.place", "rootY", arootY);
|
||||
const rotation = helper.number("stanek.place", "rotation", arotation);
|
||||
const fragmentId = helper.number("stanek.place", "fragmentId", afragmentId);
|
||||
helper.updateDynamicRam("place", getRamCost("stanek", "place"));
|
||||
helper.updateDynamicRam("place", getRamCost(player, "stanek", "place"));
|
||||
checkStanekAPIAccess("place");
|
||||
const fragment = FragmentById(fragmentId);
|
||||
if (!fragment) throw helper.makeRuntimeErrorMsg("stanek.place", `Invalid fragment id: ${fragmentId}`);
|
||||
@@ -92,7 +92,7 @@ export function NetscriptStanek(player: IPlayer, workerScript: WorkerScript, hel
|
||||
get: function (arootX: any, arootY: any): IActiveFragment | undefined {
|
||||
const rootX = helper.number("stanek.get", "rootX", arootX);
|
||||
const rootY = helper.number("stanek.get", "rootY", arootY);
|
||||
helper.updateDynamicRam("get", getRamCost("stanek", "get"));
|
||||
helper.updateDynamicRam("get", getRamCost(player, "stanek", "get"));
|
||||
checkStanekAPIAccess("get");
|
||||
const fragment = staneksGift.findFragment(rootX, rootY);
|
||||
if (fragment !== undefined) return fragment.copy();
|
||||
@@ -101,7 +101,7 @@ export function NetscriptStanek(player: IPlayer, workerScript: WorkerScript, hel
|
||||
remove: function (arootX: any, arootY: any): boolean {
|
||||
const rootX = helper.number("stanek.remove", "rootX", arootX);
|
||||
const rootY = helper.number("stanek.remove", "rootY", arootY);
|
||||
helper.updateDynamicRam("remove", getRamCost("stanek", "remove"));
|
||||
helper.updateDynamicRam("remove", getRamCost(player, "stanek", "remove"));
|
||||
checkStanekAPIAccess("remove");
|
||||
return staneksGift.delete(rootX, rootY);
|
||||
},
|
||||
|
||||
@@ -35,33 +35,33 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
|
||||
};
|
||||
return {
|
||||
getSymbols: function (): any {
|
||||
helper.updateDynamicRam("getSymbols", getRamCost("stock", "getSymbols"));
|
||||
helper.updateDynamicRam("getSymbols", getRamCost(player, "stock", "getSymbols"));
|
||||
checkTixApiAccess("getSymbols");
|
||||
return Object.values(StockSymbols);
|
||||
},
|
||||
getPrice: function (symbol: any): any {
|
||||
helper.updateDynamicRam("getPrice", getRamCost("stock", "getPrice"));
|
||||
helper.updateDynamicRam("getPrice", getRamCost(player, "stock", "getPrice"));
|
||||
checkTixApiAccess("getPrice");
|
||||
const stock = getStockFromSymbol(symbol, "getPrice");
|
||||
|
||||
return stock.price;
|
||||
},
|
||||
getAskPrice: function (symbol: any): any {
|
||||
helper.updateDynamicRam("getAskPrice", getRamCost("stock", "getAskPrice"));
|
||||
helper.updateDynamicRam("getAskPrice", getRamCost(player, "stock", "getAskPrice"));
|
||||
checkTixApiAccess("getAskPrice");
|
||||
const stock = getStockFromSymbol(symbol, "getAskPrice");
|
||||
|
||||
return stock.getAskPrice();
|
||||
},
|
||||
getBidPrice: function (symbol: any): any {
|
||||
helper.updateDynamicRam("getBidPrice", getRamCost("stock", "getBidPrice"));
|
||||
helper.updateDynamicRam("getBidPrice", getRamCost(player, "stock", "getBidPrice"));
|
||||
checkTixApiAccess("getBidPrice");
|
||||
const stock = getStockFromSymbol(symbol, "getBidPrice");
|
||||
|
||||
return stock.getBidPrice();
|
||||
},
|
||||
getPosition: function (symbol: any): any {
|
||||
helper.updateDynamicRam("getPosition", getRamCost("stock", "getPosition"));
|
||||
helper.updateDynamicRam("getPosition", getRamCost(player, "stock", "getPosition"));
|
||||
checkTixApiAccess("getPosition");
|
||||
const stock = SymbolToStockMap[symbol];
|
||||
if (stock == null) {
|
||||
@@ -70,14 +70,14 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
|
||||
return [stock.playerShares, stock.playerAvgPx, stock.playerShortShares, stock.playerAvgShortPx];
|
||||
},
|
||||
getMaxShares: function (symbol: any): any {
|
||||
helper.updateDynamicRam("getMaxShares", getRamCost("stock", "getMaxShares"));
|
||||
helper.updateDynamicRam("getMaxShares", getRamCost(player, "stock", "getMaxShares"));
|
||||
checkTixApiAccess("getMaxShares");
|
||||
const stock = getStockFromSymbol(symbol, "getMaxShares");
|
||||
|
||||
return stock.maxShares;
|
||||
},
|
||||
getPurchaseCost: function (symbol: any, shares: any, posType: any): any {
|
||||
helper.updateDynamicRam("getPurchaseCost", getRamCost("stock", "getPurchaseCost"));
|
||||
helper.updateDynamicRam("getPurchaseCost", getRamCost(player, "stock", "getPurchaseCost"));
|
||||
checkTixApiAccess("getPurchaseCost");
|
||||
const stock = getStockFromSymbol(symbol, "getPurchaseCost");
|
||||
shares = Math.round(shares);
|
||||
@@ -100,7 +100,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
|
||||
return res;
|
||||
},
|
||||
getSaleGain: function (symbol: any, shares: any, posType: any): any {
|
||||
helper.updateDynamicRam("getSaleGain", getRamCost("stock", "getSaleGain"));
|
||||
helper.updateDynamicRam("getSaleGain", getRamCost(player, "stock", "getSaleGain"));
|
||||
checkTixApiAccess("getSaleGain");
|
||||
const stock = getStockFromSymbol(symbol, "getSaleGain");
|
||||
shares = Math.round(shares);
|
||||
@@ -123,14 +123,14 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
|
||||
return res;
|
||||
},
|
||||
buy: function (symbol: any, shares: any): any {
|
||||
helper.updateDynamicRam("buy", getRamCost("stock", "buy"));
|
||||
helper.updateDynamicRam("buy", getRamCost(player, "stock", "buy"));
|
||||
checkTixApiAccess("buy");
|
||||
const stock = getStockFromSymbol(symbol, "buy");
|
||||
const res = buyStock(stock, shares, workerScript, {});
|
||||
return res ? stock.getAskPrice() : 0;
|
||||
},
|
||||
sell: function (symbol: any, shares: any): any {
|
||||
helper.updateDynamicRam("sell", getRamCost("stock", "sell"));
|
||||
helper.updateDynamicRam("sell", getRamCost(player, "stock", "sell"));
|
||||
checkTixApiAccess("sell");
|
||||
const stock = getStockFromSymbol(symbol, "sell");
|
||||
const res = sellStock(stock, shares, workerScript, {});
|
||||
@@ -138,7 +138,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
|
||||
return res ? stock.getBidPrice() : 0;
|
||||
},
|
||||
short: function (symbol: any, shares: any): any {
|
||||
helper.updateDynamicRam("short", getRamCost("stock", "short"));
|
||||
helper.updateDynamicRam("short", getRamCost(player, "stock", "short"));
|
||||
checkTixApiAccess("short");
|
||||
if (player.bitNodeN !== 8) {
|
||||
if (player.sourceFileLvl(8) <= 1) {
|
||||
@@ -154,7 +154,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
|
||||
return res ? stock.getBidPrice() : 0;
|
||||
},
|
||||
sellShort: function (symbol: any, shares: any): any {
|
||||
helper.updateDynamicRam("sellShort", getRamCost("stock", "sellShort"));
|
||||
helper.updateDynamicRam("sellShort", getRamCost(player, "stock", "sellShort"));
|
||||
checkTixApiAccess("sellShort");
|
||||
if (player.bitNodeN !== 8) {
|
||||
if (player.sourceFileLvl(8) <= 1) {
|
||||
@@ -170,7 +170,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
|
||||
return res ? stock.getAskPrice() : 0;
|
||||
},
|
||||
placeOrder: function (symbol: any, shares: any, price: any, type: any, pos: any): any {
|
||||
helper.updateDynamicRam("placeOrder", getRamCost("stock", "placeOrder"));
|
||||
helper.updateDynamicRam("placeOrder", getRamCost(player, "stock", "placeOrder"));
|
||||
checkTixApiAccess("placeOrder");
|
||||
if (player.bitNodeN !== 8) {
|
||||
if (player.sourceFileLvl(8) <= 2) {
|
||||
@@ -209,7 +209,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
|
||||
return placeOrder(stock, shares, price, orderType, orderPos, workerScript);
|
||||
},
|
||||
cancelOrder: function (symbol: any, shares: any, price: any, type: any, pos: any): any {
|
||||
helper.updateDynamicRam("cancelOrder", getRamCost("stock", "cancelOrder"));
|
||||
helper.updateDynamicRam("cancelOrder", getRamCost(player, "stock", "cancelOrder"));
|
||||
checkTixApiAccess("cancelOrder");
|
||||
if (player.bitNodeN !== 8) {
|
||||
if (player.sourceFileLvl(8) <= 2) {
|
||||
@@ -259,7 +259,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
|
||||
return cancelOrder(params, workerScript);
|
||||
},
|
||||
getOrders: function (): any {
|
||||
helper.updateDynamicRam("getOrders", getRamCost("stock", "getOrders"));
|
||||
helper.updateDynamicRam("getOrders", getRamCost(player, "stock", "getOrders"));
|
||||
checkTixApiAccess("getOrders");
|
||||
if (player.bitNodeN !== 8) {
|
||||
if (player.sourceFileLvl(8) <= 2) {
|
||||
@@ -291,7 +291,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
|
||||
return orders;
|
||||
},
|
||||
getVolatility: function (symbol: any): any {
|
||||
helper.updateDynamicRam("getVolatility", getRamCost("stock", "getVolatility"));
|
||||
helper.updateDynamicRam("getVolatility", getRamCost(player, "stock", "getVolatility"));
|
||||
if (!player.has4SDataTixApi) {
|
||||
throw helper.makeRuntimeErrorMsg("getVolatility", "You don't have 4S Market Data TIX API Access!");
|
||||
}
|
||||
@@ -300,7 +300,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
|
||||
return stock.mv / 100; // Convert from percentage to decimal
|
||||
},
|
||||
getForecast: function (symbol: any): any {
|
||||
helper.updateDynamicRam("getForecast", getRamCost("stock", "getForecast"));
|
||||
helper.updateDynamicRam("getForecast", getRamCost(player, "stock", "getForecast"));
|
||||
if (!player.has4SDataTixApi) {
|
||||
throw helper.makeRuntimeErrorMsg("getForecast", "You don't have 4S Market Data TIX API Access!");
|
||||
}
|
||||
@@ -311,7 +311,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
|
||||
return forecast / 100; // Convert from percentage to decimal
|
||||
},
|
||||
purchase4SMarketData: function () {
|
||||
helper.updateDynamicRam("purchase4SMarketData", getRamCost("stock", "purchase4SMarketData"));
|
||||
helper.updateDynamicRam("purchase4SMarketData", getRamCost(player, "stock", "purchase4SMarketData"));
|
||||
checkTixApiAccess("purchase4SMarketData");
|
||||
|
||||
if (player.has4SData) {
|
||||
@@ -330,7 +330,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
|
||||
return true;
|
||||
},
|
||||
purchase4SMarketDataTixApi: function () {
|
||||
helper.updateDynamicRam("purchase4SMarketDataTixApi", getRamCost("stock", "purchase4SMarketDataTixApi"));
|
||||
helper.updateDynamicRam("purchase4SMarketDataTixApi", getRamCost(player, "stock", "purchase4SMarketDataTixApi"));
|
||||
checkTixApiAccess("purchase4SMarketDataTixApi");
|
||||
|
||||
if (player.has4SDataTixApi) {
|
||||
|
||||
19
src/NetscriptFunctions/UserInterface.ts
Normal file
19
src/NetscriptFunctions/UserInterface.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { INetscriptHelper } from "./INetscriptHelper";
|
||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { getRamCost } from "../Netscript/RamCostGenerator";
|
||||
import { UserInterface as IUserInterface, UserInterfaceTheme } from "../ScriptEditor/NetscriptDefinitions";
|
||||
import { Settings } from "../Settings/Settings";
|
||||
|
||||
export function NetscriptUserInterface(
|
||||
player: IPlayer,
|
||||
workerScript: WorkerScript,
|
||||
helper: INetscriptHelper,
|
||||
): IUserInterface {
|
||||
return {
|
||||
getTheme: function (): UserInterfaceTheme {
|
||||
helper.updateDynamicRam("getTheme", getRamCost(player, "ui", "getTheme"));
|
||||
return { ...Settings.theme };
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -4,6 +4,7 @@ const defaultInterpreter = new Interpreter("", () => undefined);
|
||||
|
||||
// the acorn interpreter has a bug where it doesn't convert arrays correctly.
|
||||
// so we have to more or less copy it here.
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
export function toNative(pseudoObj: any): any {
|
||||
if (pseudoObj == null) return null;
|
||||
if (
|
||||
|
||||
@@ -2,15 +2,18 @@ import { makeRuntimeRejectMsg } from "./NetscriptEvaluator";
|
||||
import { ScriptUrl } from "./Script/ScriptUrl";
|
||||
import { WorkerScript } from "./Netscript/WorkerScript";
|
||||
import { Script } from "./Script/Script";
|
||||
|
||||
export const BlobsMap: { [key: string]: string } = {};
|
||||
import { computeHash } from "./utils/helpers/computeHash";
|
||||
import { BlobCache } from "./utils/BlobCache";
|
||||
import { ImportCache } from "./utils/ImportCache";
|
||||
import { areImportsEquals } from "./Terminal/DirectoryHelpers";
|
||||
import { IPlayer } from "./PersonObjects/IPlayer";
|
||||
|
||||
// Makes a blob that contains the code of a given script.
|
||||
function makeScriptBlob(code: string): Blob {
|
||||
return new Blob([code], { type: "text/javascript" });
|
||||
}
|
||||
|
||||
export async function compile(script: Script, scripts: Script[]): Promise<void> {
|
||||
export async function compile(player: IPlayer, script: Script, scripts: Script[]): Promise<void> {
|
||||
if (!shouldCompile(script, scripts)) return;
|
||||
// The URL at the top is the one we want to import. It will
|
||||
// recursively import all the other modules in the urlStack.
|
||||
@@ -19,15 +22,24 @@ export async function compile(script: Script, scripts: Script[]): Promise<void>
|
||||
// but not really behaves like import. Particularly, it cannot
|
||||
// load fully dynamic content. So we hide the import from webpack
|
||||
// by placing it inside an eval call.
|
||||
await script.updateRamUsage(scripts);
|
||||
await script.updateRamUsage(player, scripts);
|
||||
const uurls = _getScriptUrls(script, scripts, []);
|
||||
if (script.url) {
|
||||
URL.revokeObjectURL(script.url); // remove the old reference.
|
||||
delete BlobsMap[script.url];
|
||||
const url = uurls[uurls.length - 1].url;
|
||||
if (script.url && script.url !== url) {
|
||||
// Thoughts: Should we be revoking any URLs here?
|
||||
// If a script is modified repeatedly between two states,
|
||||
// we could reuse the blob at a later time.
|
||||
// BlobCache.removeByValue(script.url);
|
||||
// URL.revokeObjectURL(script.url);
|
||||
// if (script.dependencies.length > 0) {
|
||||
// script.dependencies.forEach((dep) => {
|
||||
// removeBlobFromCache(dep.url);
|
||||
// URL.revokeObjectURL(dep.url);
|
||||
// });
|
||||
// }
|
||||
}
|
||||
if (script.dependencies.length > 0) script.dependencies.forEach((dep) => URL.revokeObjectURL(dep.url));
|
||||
script.url = uurls[uurls.length - 1].url;
|
||||
script.module = new Promise((resolve) => resolve(eval("import(uurls[uurls.length - 1].url)")));
|
||||
script.url = url;
|
||||
script.module = new Promise((resolve) => resolve(eval("import(url)")));
|
||||
script.dependencies = uurls;
|
||||
}
|
||||
|
||||
@@ -39,10 +51,14 @@ export async function compile(script: Script, scripts: Script[]): Promise<void>
|
||||
// (i.e. hack, grow, etc.).
|
||||
// When the promise returned by this resolves, we'll have finished
|
||||
// running the main function of the script.
|
||||
export async function executeJSScript(scripts: Script[] = [], workerScript: WorkerScript): Promise<void> {
|
||||
export async function executeJSScript(
|
||||
player: IPlayer,
|
||||
scripts: Script[] = [],
|
||||
workerScript: WorkerScript,
|
||||
): Promise<void> {
|
||||
const script = workerScript.getScript();
|
||||
if (script === null) throw new Error("script is null");
|
||||
await compile(script, scripts);
|
||||
await compile(player, script, scripts);
|
||||
workerScript.ramUsage = script.ramUsage;
|
||||
const loadedModule = await script.module;
|
||||
|
||||
@@ -117,18 +133,27 @@ function _getScriptUrls(script: Script, scripts: Script[], seen: Script[]): Scri
|
||||
let transformedCode = script.code.replace(
|
||||
/((?:from|import)\s+(?:'|"))(?:\.\/)?([^'"]+)('|")/g,
|
||||
(unmodified, prefix, filename, suffix) => {
|
||||
const isAllowedImport = scripts.some((s) => s.filename == filename);
|
||||
const isAllowedImport = scripts.some((s) => areImportsEquals(s.filename, filename));
|
||||
if (!isAllowedImport) return unmodified;
|
||||
|
||||
// Find the corresponding script.
|
||||
const [importedScript] = scripts.filter((s) => s.filename == filename);
|
||||
const [importedScript] = scripts.filter((s) => areImportsEquals(s.filename, filename));
|
||||
|
||||
// Try to get a URL for the requested script and its dependencies.
|
||||
const urls = _getScriptUrls(importedScript, scripts, seen);
|
||||
// Check to see if the urls for this script are stored in the cache by the hash value.
|
||||
let urls = ImportCache.get(importedScript.hash());
|
||||
// If we don't have it in the cache, then we need to generate the urls for it.
|
||||
if (!urls) {
|
||||
// Try to get a URL for the requested script and its dependencies.
|
||||
urls = _getScriptUrls(importedScript, scripts, seen);
|
||||
}
|
||||
|
||||
// The top url in the stack is the replacement import file for this script.
|
||||
urlStack.push(...urls);
|
||||
return [prefix, urls[urls.length - 1].url, suffix].join("");
|
||||
const blob = urls[urls.length - 1].url;
|
||||
ImportCache.store(importedScript.hash(), urls);
|
||||
|
||||
// Replace the blob inside the import statement.
|
||||
return [prefix, blob, suffix].join("");
|
||||
},
|
||||
);
|
||||
|
||||
@@ -136,11 +161,19 @@ function _getScriptUrls(script: Script, scripts: Script[], seen: Script[]): Scri
|
||||
// accidental calls to window.print() do not bring up the "print screen" dialog
|
||||
transformedCode += `\n\nfunction print() {throw new Error("Invalid call to window.print(). Did you mean to use Netscript's print()?");}`;
|
||||
|
||||
// If we successfully transformed the code, create a blob url for it and
|
||||
// push that URL onto the top of the stack.
|
||||
const su = new ScriptUrl(script.filename, URL.createObjectURL(makeScriptBlob(transformedCode)));
|
||||
urlStack.push(su);
|
||||
BlobsMap[su.url] = su.filename;
|
||||
// If we successfully transformed the code, create a blob url for it
|
||||
// Compute the hash for the transformed code
|
||||
const transformedHash = computeHash(transformedCode);
|
||||
// Check to see if this transformed hash is in our cache
|
||||
let blob = BlobCache.get(transformedHash);
|
||||
if (!blob) {
|
||||
blob = URL.createObjectURL(makeScriptBlob(transformedCode));
|
||||
}
|
||||
// Store this blob in the cache. Any script that transforms the same
|
||||
// (e.g. same scripts on server, same hash value, etc) can use this blob url.
|
||||
BlobCache.store(transformedHash, blob);
|
||||
// Push the blob URL onto the top of the stack.
|
||||
urlStack.push(new ScriptUrl(script.filename, blob));
|
||||
return urlStack;
|
||||
} catch (err) {
|
||||
// If there is an error, we need to clean up the URLs.
|
||||
|
||||
@@ -34,6 +34,8 @@ import { parse } from "acorn";
|
||||
import { simple as walksimple } from "acorn-walk";
|
||||
import { areFilesEqual } from "./Terminal/DirectoryHelpers";
|
||||
import { Player } from "./Player";
|
||||
import { Terminal } from "./Terminal";
|
||||
import { IPlayer } from "./PersonObjects/IPlayer";
|
||||
|
||||
// Netscript Ports are instantiated here
|
||||
export const NetscriptPorts: IPort[] = [];
|
||||
@@ -54,7 +56,7 @@ export function prestigeWorkerScripts(): void {
|
||||
// JS script promises need a little massaging to have the same guarantees as netscript
|
||||
// promises. This does said massaging and kicks the script off. It returns a promise
|
||||
// that resolves or rejects when the corresponding worker script is done.
|
||||
function startNetscript2Script(workerScript: WorkerScript): Promise<WorkerScript> {
|
||||
function startNetscript2Script(player: IPlayer, workerScript: WorkerScript): Promise<WorkerScript> {
|
||||
workerScript.running = true;
|
||||
|
||||
// The name of the currently running netscript function, to prevent concurrent
|
||||
@@ -80,7 +82,7 @@ function startNetscript2Script(workerScript: WorkerScript): Promise<WorkerScript
|
||||
if (propName === "asleep") return f(...args); // OK for multiple simultaneous calls to sleep.
|
||||
|
||||
const msg =
|
||||
"Concurrent calls to Netscript functions not allowed! " +
|
||||
"Concurrent calls to Netscript functions are not allowed! " +
|
||||
"Did you forget to await hack(), grow(), or some other " +
|
||||
"promise-returning function? (Currently running: %s tried to run: %s)";
|
||||
if (runningFn) {
|
||||
@@ -120,12 +122,13 @@ function startNetscript2Script(workerScript: WorkerScript): Promise<WorkerScript
|
||||
// Note: the environment that we pass to the JS script only needs to contain the functions visible
|
||||
// to that script, which env.vars does at this point.
|
||||
return new Promise<WorkerScript>((resolve, reject) => {
|
||||
executeJSScript(workerScript.getServer().scripts, workerScript)
|
||||
executeJSScript(player, workerScript.getServer().scripts, workerScript)
|
||||
.then(() => {
|
||||
resolve(workerScript);
|
||||
})
|
||||
.catch((e) => reject(e));
|
||||
}).catch((e) => {
|
||||
console.log(e);
|
||||
if (e instanceof Error) {
|
||||
if (e instanceof SyntaxError) {
|
||||
workerScript.errorMessage = makeRuntimeRejectMsg(workerScript, e.message + " (sorry we can't be more helpful)");
|
||||
@@ -455,8 +458,13 @@ function processNetscript1Imports(code: string, workerScript: WorkerScript): any
|
||||
* @param {Server} server - Server on which the script is to be run
|
||||
* @returns {number} pid of started script
|
||||
*/
|
||||
export function startWorkerScript(runningScript: RunningScript, server: BaseServer, parent?: WorkerScript): number {
|
||||
if (createAndAddWorkerScript(runningScript, server, parent)) {
|
||||
export function startWorkerScript(
|
||||
player: IPlayer,
|
||||
runningScript: RunningScript,
|
||||
server: BaseServer,
|
||||
parent?: WorkerScript,
|
||||
): number {
|
||||
if (createAndAddWorkerScript(player, runningScript, server, parent)) {
|
||||
// Push onto runningScripts.
|
||||
// This has to come after createAndAddWorkerScript() because that fn updates RAM usage
|
||||
server.runScript(runningScript);
|
||||
@@ -476,7 +484,12 @@ export function startWorkerScript(runningScript: RunningScript, server: BaseServ
|
||||
* @param {Server} server - Server on which the script is to be run
|
||||
* returns {boolean} indicating whether or not the workerScript was successfully added
|
||||
*/
|
||||
function createAndAddWorkerScript(runningScriptObj: RunningScript, server: BaseServer, parent?: WorkerScript): boolean {
|
||||
function createAndAddWorkerScript(
|
||||
player: IPlayer,
|
||||
runningScriptObj: RunningScript,
|
||||
server: BaseServer,
|
||||
parent?: WorkerScript,
|
||||
): boolean {
|
||||
// Update server's ram usage
|
||||
let threads = 1;
|
||||
if (runningScriptObj.threads && !isNaN(runningScriptObj.threads)) {
|
||||
@@ -520,7 +533,7 @@ function createAndAddWorkerScript(runningScriptObj: RunningScript, server: BaseS
|
||||
// Start the script's execution
|
||||
let p: Promise<WorkerScript> | null = null; // Script's resulting promise
|
||||
if (s.name.endsWith(".js") || s.name.endsWith(".ns")) {
|
||||
p = startNetscript2Script(s);
|
||||
p = startNetscript2Script(player, s);
|
||||
} else {
|
||||
p = startNetscript1Script(s);
|
||||
if (!(p instanceof Promise)) {
|
||||
@@ -605,9 +618,10 @@ export function updateOnlineScriptTimes(numCycles = 1): void {
|
||||
* Called when the game is loaded. Loads all running scripts (from all servers)
|
||||
* into worker scripts so that they will start running
|
||||
*/
|
||||
export function loadAllRunningScripts(): void {
|
||||
export function loadAllRunningScripts(player: IPlayer): void {
|
||||
const skipScriptLoad = window.location.href.toLowerCase().indexOf("?noscripts") !== -1;
|
||||
if (skipScriptLoad) {
|
||||
Terminal.warn("Skipped loading player scripts during startup");
|
||||
console.info("Skipping the load of any scripts during startup");
|
||||
}
|
||||
for (const server of GetAllServers()) {
|
||||
@@ -624,7 +638,7 @@ export function loadAllRunningScripts(): void {
|
||||
server.runningScripts.length = 0;
|
||||
} else {
|
||||
for (let j = 0; j < server.runningScripts.length; ++j) {
|
||||
createAndAddWorkerScript(server.runningScripts[j], server);
|
||||
createAndAddWorkerScript(player, server.runningScripts[j], server);
|
||||
|
||||
// Offline production
|
||||
scriptCalculateOfflineProduction(server.runningScripts[j]);
|
||||
@@ -637,6 +651,7 @@ export function loadAllRunningScripts(): void {
|
||||
* Run a script from inside another script (run(), exec(), spawn(), etc.)
|
||||
*/
|
||||
export function runScriptFromScript(
|
||||
player: IPlayer,
|
||||
caller: string,
|
||||
server: BaseServer,
|
||||
scriptname: string,
|
||||
@@ -684,7 +699,7 @@ export function runScriptFromScript(
|
||||
// Check for admin rights and that there is enough RAM availble to run
|
||||
const script = server.scripts[i];
|
||||
let ramUsage = script.ramUsage;
|
||||
threads = Math.round(Number(threads));
|
||||
threads = Math.floor(Number(threads));
|
||||
if (threads === 0) {
|
||||
return 0;
|
||||
}
|
||||
@@ -711,7 +726,7 @@ export function runScriptFromScript(
|
||||
runningScriptObj.threads = threads;
|
||||
runningScriptObj.server = server.hostname;
|
||||
|
||||
return startWorkerScript(runningScriptObj, server, workerScript);
|
||||
return startWorkerScript(player, runningScriptObj, server, workerScript);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -242,6 +242,7 @@ export interface IPlayer {
|
||||
getIntelligenceBonus(weight: number): number;
|
||||
getCasinoWinnings(): number;
|
||||
quitJob(company: string): void;
|
||||
hasJob(): boolean;
|
||||
createHacknetServer(): HacknetServer;
|
||||
startCreateProgramWork(router: IRouter, programName: string, time: number, reqLevel: number): void;
|
||||
queueAugmentation(augmentationName: string): void;
|
||||
|
||||
@@ -247,6 +247,7 @@ export class PlayerObject implements IPlayer {
|
||||
getIntelligenceBonus: (weight: number) => number;
|
||||
getCasinoWinnings: () => number;
|
||||
quitJob: (company: string) => void;
|
||||
hasJob: () => boolean;
|
||||
process: (router: IRouter, numCycles?: number) => void;
|
||||
createHacknetServer: () => HacknetServer;
|
||||
startCreateProgramWork: (router: IRouter, programName: string, time: number, reqLevel: number) => void;
|
||||
@@ -531,6 +532,7 @@ export class PlayerObject implements IPlayer {
|
||||
this.applyForJob = generalMethods.applyForJob;
|
||||
this.getNextCompanyPosition = generalMethods.getNextCompanyPosition;
|
||||
this.quitJob = generalMethods.quitJob;
|
||||
this.hasJob = generalMethods.hasJob;
|
||||
this.applyForSoftwareJob = generalMethods.applyForSoftwareJob;
|
||||
this.applyForSoftwareConsultantJob = generalMethods.applyForSoftwareConsultantJob;
|
||||
this.applyForItJob = generalMethods.applyForItJob;
|
||||
|
||||
@@ -26,7 +26,11 @@ import { Locations } from "../../Locations/Locations";
|
||||
import { CityName } from "../../Locations/data/CityNames";
|
||||
import { LocationName } from "../../Locations/data/LocationNames";
|
||||
import { Sleeve } from "../../PersonObjects/Sleeve/Sleeve";
|
||||
import { calculateSkill as calculateSkillF, calculateSkillProgress as calculateSkillProgressF, getEmptySkillProgress, ISkillProgress } from "../formulas/skill";
|
||||
import {
|
||||
calculateSkill as calculateSkillF,
|
||||
calculateSkillProgress as calculateSkillProgressF,
|
||||
ISkillProgress,
|
||||
} from "../formulas/skill";
|
||||
import { calculateIntelligenceBonus } from "../formulas/intelligence";
|
||||
import {
|
||||
getHackingWorkRepGain,
|
||||
@@ -650,6 +654,8 @@ export function finishWork(this: IPlayer, cancelled: boolean, sing = false): str
|
||||
this.workRepGained *= this.cancelationPenalty();
|
||||
}
|
||||
|
||||
const penaltyString = this.cancelationPenalty() === 0.5 ? "half" : "three-quarters";
|
||||
|
||||
const company = Companies[this.companyName];
|
||||
company.playerReputation += this.workRepGained;
|
||||
|
||||
@@ -661,12 +667,12 @@ export function finishWork(this: IPlayer, cancelled: boolean, sing = false): str
|
||||
<Money money={this.workMoneyGained} />
|
||||
<br />
|
||||
<Reputation reputation={this.workRepGained} /> reputation for the company <br />
|
||||
{numeralWrapper.formatExp(this.workHackExpGained)} hacking exp <br />
|
||||
{numeralWrapper.formatExp(this.workStrExpGained)} strength exp <br />
|
||||
{numeralWrapper.formatExp(this.workDefExpGained)} defense exp <br />
|
||||
{numeralWrapper.formatExp(this.workDexExpGained)} dexterity exp <br />
|
||||
{numeralWrapper.formatExp(this.workAgiExpGained)} agility exp <br />
|
||||
{numeralWrapper.formatExp(this.workChaExpGained)} charisma exp
|
||||
{this.workHackExpGained > 0 && <>{numeralWrapper.formatExp(this.workHackExpGained)} hacking exp <br /></>}
|
||||
{this.workStrExpGained > 0 && <>{numeralWrapper.formatExp(this.workStrExpGained)} strength exp <br /></>}
|
||||
{this.workDefExpGained > 0 && <>{numeralWrapper.formatExp(this.workDefExpGained)} defense exp <br /></>}
|
||||
{this.workDexExpGained > 0 && <>{numeralWrapper.formatExp(this.workDexExpGained)} dexterity exp <br /></>}
|
||||
{this.workAgiExpGained > 0 && <>{numeralWrapper.formatExp(this.workAgiExpGained)} agility exp <br /></>}
|
||||
{this.workChaExpGained > 0 && <>{numeralWrapper.formatExp(this.workChaExpGained)} charisma exp <br /></>}
|
||||
<br />
|
||||
</>
|
||||
);
|
||||
@@ -676,7 +682,7 @@ export function finishWork(this: IPlayer, cancelled: boolean, sing = false): str
|
||||
<>
|
||||
You worked a short shift of {convertTimeMsToTimeElapsedString(this.timeWorked)} <br />
|
||||
<br />
|
||||
Since you cancelled your work early, you only gained half of the reputation you earned. <br />
|
||||
Since you cancelled your work early, you only gained {penaltyString} of the reputation you earned. <br />
|
||||
<br />
|
||||
{content}
|
||||
</>
|
||||
@@ -1648,7 +1654,7 @@ export function regenerateHp(this: IPlayer, amt: number): void {
|
||||
|
||||
export function hospitalize(this: IPlayer): number {
|
||||
const cost = getHospitalizationCost(this);
|
||||
SnackbarEvents.emit(`You've been Hospitalized for ${numeralWrapper.formatMoney(cost)}`, "warning");
|
||||
SnackbarEvents.emit(`You've been Hospitalized for ${numeralWrapper.formatMoney(cost)}`, "warning", 2000);
|
||||
|
||||
this.loseMoney(cost, "hospitalization");
|
||||
this.hp = this.max_hp;
|
||||
@@ -1684,6 +1690,11 @@ export function applyForJob(this: IPlayer, entryPosType: CompanyPosition, sing =
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if this company has the position
|
||||
if (!company.hasPosition(pos)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
const newPos = getNextCompanyPositionHelper(pos);
|
||||
if (newPos == null) {
|
||||
@@ -1782,6 +1793,15 @@ export function quitJob(this: IPlayer, company: string): void {
|
||||
delete this.jobs[company];
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to see if the player has at least one job assigned to them
|
||||
* @param this The player instance
|
||||
* @returns Whether the user has at least one job
|
||||
*/
|
||||
export function hasJob(this: IPlayer): boolean {
|
||||
return Boolean(Object.keys(this.jobs).length);
|
||||
}
|
||||
|
||||
export function applyForSoftwareJob(this: IPlayer, sing = false): boolean {
|
||||
return this.applyForJob(CompanyPositions[posNames.SoftwareCompanyPositions[0]], sing);
|
||||
}
|
||||
@@ -1848,9 +1868,14 @@ export function applyForAgentJob(this: IPlayer, sing = false): boolean {
|
||||
|
||||
export function applyForEmployeeJob(this: IPlayer, sing = false): boolean {
|
||||
const company = Companies[this.location]; //Company being applied to
|
||||
if (this.isQualified(company, CompanyPositions[posNames.MiscCompanyPositions[1]])) {
|
||||
const position = posNames.MiscCompanyPositions[1];
|
||||
// Check if this company has the position
|
||||
if (!company.hasPosition(position)) {
|
||||
return false;
|
||||
}
|
||||
if (this.isQualified(company, CompanyPositions[position])) {
|
||||
this.companyName = company.name;
|
||||
this.jobs[company.name] = posNames.MiscCompanyPositions[1];
|
||||
this.jobs[company.name] = position;
|
||||
if (!sing) {
|
||||
dialogBoxCreate("Congratulations, you are now employed at " + this.location);
|
||||
}
|
||||
@@ -1867,8 +1892,13 @@ export function applyForEmployeeJob(this: IPlayer, sing = false): boolean {
|
||||
|
||||
export function applyForPartTimeEmployeeJob(this: IPlayer, sing = false): boolean {
|
||||
const company = Companies[this.location]; //Company being applied to
|
||||
if (this.isQualified(company, CompanyPositions[posNames.PartTimeCompanyPositions[1]])) {
|
||||
this.jobs[company.name] = posNames.PartTimeCompanyPositions[1];
|
||||
const position = posNames.PartTimeCompanyPositions[1];
|
||||
// Check if this company has the position
|
||||
if (!company.hasPosition(position)) {
|
||||
return false;
|
||||
}
|
||||
if (this.isQualified(company, CompanyPositions[position])) {
|
||||
this.jobs[company.name] = position;
|
||||
if (!sing) {
|
||||
dialogBoxCreate("Congratulations, you are now employed part-time at " + this.location);
|
||||
}
|
||||
@@ -1885,9 +1915,14 @@ export function applyForPartTimeEmployeeJob(this: IPlayer, sing = false): boolea
|
||||
|
||||
export function applyForWaiterJob(this: IPlayer, sing = false): boolean {
|
||||
const company = Companies[this.location]; //Company being applied to
|
||||
if (this.isQualified(company, CompanyPositions[posNames.MiscCompanyPositions[0]])) {
|
||||
const position = posNames.MiscCompanyPositions[0];
|
||||
// Check if this company has the position
|
||||
if (!company.hasPosition(position)) {
|
||||
return false;
|
||||
}
|
||||
if (this.isQualified(company, CompanyPositions[position])) {
|
||||
this.companyName = company.name;
|
||||
this.jobs[company.name] = posNames.MiscCompanyPositions[0];
|
||||
this.jobs[company.name] = position;
|
||||
if (!sing) {
|
||||
dialogBoxCreate("Congratulations, you are now employed as a waiter at " + this.location);
|
||||
}
|
||||
@@ -1902,9 +1937,14 @@ export function applyForWaiterJob(this: IPlayer, sing = false): boolean {
|
||||
|
||||
export function applyForPartTimeWaiterJob(this: IPlayer, sing = false): boolean {
|
||||
const company = Companies[this.location]; //Company being applied to
|
||||
if (this.isQualified(company, CompanyPositions[posNames.PartTimeCompanyPositions[0]])) {
|
||||
const position = posNames.PartTimeCompanyPositions[0];
|
||||
// Check if this company has the position
|
||||
if (!company.hasPosition(position)) {
|
||||
return false;
|
||||
}
|
||||
if (this.isQualified(company, CompanyPositions[position])) {
|
||||
this.companyName = company.name;
|
||||
this.jobs[company.name] = posNames.PartTimeCompanyPositions[0];
|
||||
this.jobs[company.name] = position;
|
||||
if (!sing) {
|
||||
dialogBoxCreate("Congratulations, you are now employed as a part-time waiter at " + this.location);
|
||||
}
|
||||
@@ -2582,7 +2622,7 @@ export function canAccessResleeving(this: IPlayer): boolean {
|
||||
export function giveExploit(this: IPlayer, exploit: Exploit): void {
|
||||
if (!this.exploits.includes(exploit)) {
|
||||
this.exploits.push(exploit);
|
||||
SnackbarEvents.emit("SF -1 acquired!", "success");
|
||||
SnackbarEvents.emit("SF -1 acquired!", "success", 2000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,9 +9,25 @@ export function calculateExp(skill: number, mult = 1): number {
|
||||
export function calculateSkillProgress(exp: number, mult = 1): ISkillProgress {
|
||||
const currentSkill = calculateSkill(exp, mult);
|
||||
const nextSkill = currentSkill + 1;
|
||||
|
||||
let baseExperience = calculateExp(currentSkill, mult);
|
||||
if (baseExperience < 0) baseExperience = 0;
|
||||
const nextExperience = calculateExp(nextSkill, mult)
|
||||
|
||||
let nextExperience = calculateExp(nextSkill, mult)
|
||||
if (nextExperience < 0) nextExperience = 0;
|
||||
|
||||
const normalize = (value: number): number => ((value - baseExperience) * 100) / (nextExperience - baseExperience);
|
||||
let progress = (nextExperience - baseExperience !== 0) ? normalize(exp) : 99.99;
|
||||
|
||||
// Clamp progress: When sleeves are working out, the player gets way too much progress
|
||||
if (progress < 0) progress = 0
|
||||
if (progress > 100) progress = 100;
|
||||
|
||||
// Clamp floating point imprecisions
|
||||
let currentExperience = exp - baseExperience;
|
||||
let remainingExperience = nextExperience - exp;
|
||||
if (currentExperience < 0) currentExperience = 0;
|
||||
if (remainingExperience < 0) remainingExperience = 0;
|
||||
|
||||
return {
|
||||
currentSkill,
|
||||
@@ -19,7 +35,9 @@ export function calculateSkillProgress(exp: number, mult = 1): ISkillProgress {
|
||||
baseExperience,
|
||||
experience: exp,
|
||||
nextExperience,
|
||||
progress: exp / nextExperience,
|
||||
currentExperience,
|
||||
remainingExperience,
|
||||
progress
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,13 +47,16 @@ export interface ISkillProgress {
|
||||
baseExperience: number;
|
||||
experience: number;
|
||||
nextExperience: number;
|
||||
currentExperience: number;
|
||||
remainingExperience: number;
|
||||
progress: number;
|
||||
}
|
||||
|
||||
export function getEmptySkillProgress() {
|
||||
export function getEmptySkillProgress(): ISkillProgress {
|
||||
return {
|
||||
currentSkill: 0, nextSkill: 0,
|
||||
baseExperience: 0, experience: 0, nextExperience: 0,
|
||||
currentExperience: 0, remainingExperience: 0,
|
||||
progress: 0,
|
||||
};
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user