Merge branch 'dev' into add-ns-getRecentScripts

This commit is contained in:
hydroflame 2022-04-12 14:21:18 -04:00 committed by GitHub
commit 68abd27d2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
518 changed files with 15410 additions and 160938 deletions

@ -43,7 +43,7 @@ module.exports = {
curly: ["off"],
"default-case": ["off"],
"dot-notation": ["off"],
"eol-last": ["off"],
"eol-last": ["error"],
eqeqeq: ["off"],
"for-direction": ["error"],
"func-call-spacing": ["off"],
@ -137,7 +137,7 @@ module.exports = {
"no-ex-assign": ["off"],
"no-extra-boolean-cast": ["error"],
"no-extra-parens": ["off"],
"no-extra-semi": ["off"],
"no-extra-semi": ["error"],
"no-eval": ["off"],
"no-extend-native": ["off"],
"no-extra-bind": ["error"],
@ -166,12 +166,12 @@ module.exports = {
"no-label-var": ["error"],
"no-labels": ["off"],
"no-lone-blocks": ["error"],
"no-lonely-if": ["off"],
"no-lonely-if": ["error"],
"no-loop-func": ["off"],
"no-magic-numbers": ["off"],
"no-mixed-operators": ["off"],
"no-mixed-requires": ["error"],
"no-mixed-spaces-and-tabs": ["off"],
"no-mixed-spaces-and-tabs": ["error"],
"no-multi-assign": ["off"],
"no-multi-spaces": ["off"],
"no-multi-str": ["error"],
@ -236,7 +236,7 @@ module.exports = {
"no-ternary": ["off"],
"no-this-before-super": ["off"],
"no-throw-literal": ["error"],
"no-trailing-spaces": ["off"],
"no-trailing-spaces": ["error"],
"no-undef": ["off"],
"no-undef-init": ["error"],
"no-undefined": ["off"],
@ -253,7 +253,7 @@ module.exports = {
"no-use-before-define": ["off"],
"no-useless-call": ["off"],
"no-useless-computed-key": ["error"],
"no-useless-concat": ["off"],
"no-useless-concat": ["error"],
"no-useless-constructor": ["error"],
"no-useless-escape": ["off"],
"no-useless-rename": [
@ -353,6 +353,7 @@ module.exports = {
"no-useless-constructor": [
"off", // Valid for typescript due to property ctor shorthand
],
"@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/ban-ts-ignore": "off",
"@typescript-eslint/camelcase": "off",

@ -9,3 +9,6 @@
- Include how it was tested
- Include screenshot / gif (if possible)
Make sure you run `npm run format` and `npm run lint` before pushing.

@ -4,28 +4,28 @@ on:
workflow_dispatch:
inputs:
version:
description: 'Version (format: x.y.z)'
description: "Version (format: x.y.z)"
required: true
versionNumber:
description: 'Version Number (for saves migration)'
description: "Version Number (for saves migration)"
required: true
changelog:
description: 'Changelog (url that points to RAW markdown)'
default: ''
description: "Changelog (url that points to RAW markdown)"
default: ""
buildApp:
description: 'Include Application Build'
description: "Include Application Build"
type: boolean
default: 'true'
default: "true"
required: true
buildDoc:
description: 'Include Documentation Build'
description: "Include Documentation Build"
type: boolean
default: 'true'
default: "true"
required: true
prepareRelease:
description: 'Prepare Draft Release'
description: "Prepare Draft Release"
type: boolean
default: 'true'
default: "true"
required: true
jobs:
@ -46,7 +46,7 @@ jobs:
uses: actions/setup-node@v2
with:
node-version: 16.13.1
cache: 'npm'
cache: "npm"
- name: Install NPM dependencies for version updater
working-directory: ./tools/bump-version
run: npm ci

@ -0,0 +1,85 @@
name: Check for Generated Files
on:
# Triggers the workflow on push or pull request events but only for the dev branch
pull_request:
branches: [dev]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
jobs:
checkFiles:
name: Check Files
runs-on: ubuntu-latest
steps:
- name: Checkout files
uses: actions/checkout@v2
- name: Check bundle files
id: changed-bundle-files
uses: tj-actions/changed-files@v18.4
with:
files: |
dist/*
index.html
main.bundle.js
main.bundle.js.map
- name: Check documentation changes
id: changed-markdown-doc-files
uses: tj-actions/changed-files@v18.4
with:
files: |
markdown/*.md
- name: Warn when bundle files were changed
id: warn-bundles-changed
if: steps.changed-bundle-files.outputs.any_changed == 'true'
run: |
echo "One or more files in the bundle files were changed." >> warnings.txt
- name: Warn when documentation markdown files were changed
id: warn-markdown-changed
if: steps.changed-markdown-doc-files.outputs.any_changed == 'true'
run: |
echo "One or more files in the markdown documentation were changed." >> warnings.txt
- name: Print Warnings
id: get-warnings
run: |
if [ -f warnings.txt ]
then
echo "::set-output name=has_warnings::true"
else
echo "::set-output name=has_warnings::false"
touch warnings.txt
fi
- name: Get Comment Body
id: get-comment-body
if: steps.get-warnings.outputs.has_warnings == 'true'
run: |
cat warnings.txt > comment.txt
echo "" >> comment.txt
echo "Please do not commit files generated by webpack or generated markdown" >> comment.txt
echo "" >> comment.txt
echo "See [CONTRIBUTING.md](https://github.com/danielyxie/bitburner/blob/dev/doc/CONTRIBUTING.md) for details." >> comment.txt
body=$(cat comment.txt)
body="${body//'%'/'%25'}"
body="${body//$'\n'/'%0A'}"
body="${body//$'\r'/'%0D'}"
echo ::set-output name=body::$body
- name: Add github comment on problem
if: steps.get-warnings.outputs.has_warnings == 'true'
uses: peter-evans/commit-comment@v1
with:
body: ${{ steps.get-comment-body.outputs.body }}
- name: Flag as error
if: steps.get-warnings.outputs.has_warnings == 'true'
run: |
COMMIT_WARNINGS=$(cat warnings.txt)
echo "::warning:: $COMMIT_WARNINGS"
exit 1

@ -3,9 +3,9 @@ name: CI
on:
# Triggers the workflow on push or pull request events but only for the dev branch
push:
branches: [ dev ]
branches: [dev]
pull_request:
branches: [ dev ]
branches: [dev]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
@ -20,7 +20,7 @@ jobs:
uses: actions/setup-node@v2
with:
node-version: 16.13.1
cache: 'npm'
cache: "npm"
- name: Install npm dependencies
run: npm ci
- name: Build the production app
@ -34,11 +34,25 @@ jobs:
uses: actions/setup-node@v2
with:
node-version: 16.13.1
cache: 'npm'
cache: "npm"
- name: Install npm dependencies
run: npm ci
- name: Run linter
run: npm run lint:report
prettier:
name: Prettier
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 prettier check
run: npm run format:report
test:
name: Test
runs-on: ubuntu-latest
@ -48,7 +62,7 @@ jobs:
uses: actions/setup-node@v2
with:
node-version: 16.13.1
cache: 'npm'
cache: "npm"
- name: Install npm dependencies
run: npm ci
- name: Run tests

@ -3,10 +3,10 @@ on:
workflow_dispatch:
inputs:
fromCommit:
description: 'From Commit SHA (full-length)'
description: "From Commit SHA (full-length)"
required: true
toCommit:
description: 'To Commit SHA (full-length, if omitted will use latest)'
description: "To Commit SHA (full-length, if omitted will use latest)"
jobs:
fetchChangelog:
@ -17,7 +17,7 @@ jobs:
uses: actions/setup-node@v2
with:
node-version: 16.13.1
cache: 'npm'
cache: "npm"
- name: Install NPM dependencies
working-directory: ./tools/fetch-changelog
run: npm ci

1
CODE_OF_CONDUCT.md Normal file

@ -0,0 +1 @@
Don't be an ass.

@ -1,23 +0,0 @@
.staneksgift_row {
padding: 0;
margin: 0;
}
.staneksgift_cell {
width: 25px;
height: 25px;
background-color: #808080;
font-color: white;
padding: 0px;
margin: 0px;
border: 1px solid black;
float: left;
}
.staneksgift_cell:first-child {
clear: left;
}
.staneksgift_container {
position: fixed;
}

462
dist/bitburner.d.ts vendored

@ -15,65 +15,65 @@ export declare interface ActiveFragment {
* @public
*/
export declare interface AugmentationStats {
/** Multipler to hacking skill */
/** Multiplier to hacking skill */
hacking_mult?: number;
/** Multipler to strength skill */
/** Multiplier to strength skill */
strength_mult?: number;
/** Multipler to defense skill */
/** Multiplier to defense skill */
defense_mult?: number;
/** Multipler to dexterity skill */
/** Multiplier to dexterity skill */
dexterity_mult?: number;
/** Multipler to agility skill */
/** Multiplier to agility skill */
agility_mult?: number;
/** Multipler to charisma skill */
/** Multiplier to charisma skill */
charisma_mult?: number;
/** Multipler to hacking experience gain rate */
/** Multiplier to hacking experience gain rate */
hacking_exp_mult?: number;
/** Multipler to strength experience gain rate */
/** Multiplier to strength experience gain rate */
strength_exp_mult?: number;
/** Multipler to defense experience gain rate */
/** Multiplier to defense experience gain rate */
defense_exp_mult?: number;
/** Multipler to dexterity experience gain rate */
/** Multiplier to dexterity experience gain rate */
dexterity_exp_mult?: number;
/** Multipler to agility experience gain rate */
/** Multiplier to agility experience gain rate */
agility_exp_mult?: number;
/** Multipler to charisma experience gain rate */
/** Multiplier to charisma experience gain rate */
charisma_exp_mult?: number;
/** Multipler to chance of successfully performing a hack */
/** Multiplier to chance of successfully performing a hack */
hacking_chance_mult?: number;
/** Multipler to hacking speed */
/** Multiplier to hacking speed */
hacking_speed_mult?: number;
/** Multipler to amount of money the player gains from hacking */
/** Multiplier to amount of money the player gains from hacking */
hacking_money_mult?: number;
/** Multipler to amount of money injected into servers using grow */
/** Multiplier to amount of money injected into servers using grow */
hacking_grow_mult?: number;
/** Multipler to amount of reputation gained when working */
/** Multiplier to amount of reputation gained when working */
company_rep_mult?: number;
/** Multipler to amount of reputation gained when working */
/** Multiplier to amount of reputation gained when working */
faction_rep_mult?: number;
/** Multipler to amount of money gained from crimes */
/** Multiplier to amount of money gained from crimes */
crime_money_mult?: number;
/** Multipler to crime success rate */
/** Multiplier to crime success rate */
crime_success_mult?: number;
/** Multipler to amount of money gained from working */
/** Multiplier to amount of money gained from working */
work_money_mult?: number;
/** Multipler to amount of money produced by Hacknet Nodes */
/** Multiplier to amount of money produced by Hacknet Nodes */
hacknet_node_money_mult?: number;
/** Multipler to cost of purchasing a Hacknet Node */
/** Multiplier to cost of purchasing a Hacknet Node */
hacknet_node_purchase_cost_mult?: number;
/** Multipler to cost of ram for a Hacknet Node */
/** Multiplier to cost of ram for a Hacknet Node */
hacknet_node_ram_cost_mult?: number;
/** Multipler to cost of core for a Hacknet Node */
/** Multiplier to cost of core for a Hacknet Node */
hacknet_node_core_cost_mult?: number;
/** Multipler to cost of leveling up a Hacknet Node */
/** Multiplier to cost of leveling up a Hacknet Node */
hacknet_node_level_cost_mult?: number;
/** Multipler to Bladeburner max stamina */
/** Multiplier to Bladeburner max stamina */
bladeburner_max_stamina_mult?: number;
/** Multipler to Bladeburner stamina gain rate */
/** Multiplier to Bladeburner stamina gain rate */
bladeburner_stamina_gain_mult?: number;
/** Multipler to effectiveness in Bladeburner Field Analysis */
/** Multiplier to effectiveness in Bladeburner Field Analysis */
bladeburner_analysis_mult?: number;
/** Multipler to success chance in Bladeburner contracts/operations */
/** Multiplier to success chance in Bladeburner contracts/operations */
bladeburner_success_chance_mult?: number;
}
@ -88,6 +88,17 @@ export declare interface AugmentPair {
cost: number;
}
/**
* Used for autocompletion
* @public
*/
export declare interface AutocompleteData {
servers: string[];
scripts: string[];
txts: string[];
flags(schema: [string, string | number | boolean | string[]][]): any;
}
/**
* Options to affect the behavior of {@link NS.hack | hack}, {@link NS.grow | grow}, and {@link NS.weaken | weaken}.
* @public
@ -124,6 +135,8 @@ export declare interface BitNodeMultipliers {
CompanyWorkExpGain: number;
/** Influences how much money the player earns when completing working their job. */
CompanyWorkMoney: number;
/** Influences the money gain from dividends of corporations created by the player. */
CorporationSoftCap: number;
/** Influences the valuation of corporations created by the player. */
CorporationValuation: number;
/** Influences the base experience gained for each ability when the player commits a crime. */
@ -178,7 +191,7 @@ export declare interface BitNodeMultipliers {
ScriptHackMoneyGain: number;
/** Influences the growth percentage per cycle against a server. */
ServerGrowthRate: number;
/** Influences the maxmimum money that a server can grow to. */
/** Influences the maximum money that a server can grow to. */
ServerMaxMoney: number;
/** Influences the initial money that a server starts with. */
ServerStartingMoney: number;
@ -348,7 +361,7 @@ export declare interface Bladeburner {
*
* Note that this is meant to be used for Contracts and Operations.
* This function will return Infinity for actions such as Training and Field Analysis.
* This function will return 1 for BlackOps not yet completed regardless of wether
* This function will return 1 for BlackOps not yet completed regardless of whether
* the player has the required rank to attempt the mission or not.
*
* @param type - Type of action.
@ -388,7 +401,7 @@ export declare interface Bladeburner {
getActionCurrentLevel(type: string, name: string): number;
/**
* Get wether an action is set to autolevel.
* Get whether an action is set to autolevel.
* @remarks
* RAM cost: 4 GB
*
@ -777,7 +790,7 @@ export declare interface CodingAttemptOptions {
*/
export declare interface CodingContract {
/**
* Attemps a coding contract.
* Attempts a coding contract.
* @remarks
* RAM cost: 10 GB
*
@ -958,6 +971,28 @@ export declare interface Corporation extends WarehouseAPI, OfficeAPI {
* @param percent - Percent of profit to issue as dividends.
*/
issueDividends(percent: number): void;
/**
* Buyback Shares
* @param amount - Amount of shares to buy back.
*
*/
buyBackShares(amount: number): void;
/**
* Sell Shares
* @param amount - Amount of shares to sell.
*
*/
sellShares(amount: number): void;
/**
* Get bonus time.
*
* Bonus time is accumulated when the game is offline or if the game is inactive in the browser.
*
* Bonus time makes the game progress faster.
*
* @returns Bonus time for the Corporation mechanic in milliseconds.
*/
getBonusTime(): number;
}
/**
@ -1005,7 +1040,7 @@ export declare interface CrimeStats {
/** How much money is given */
money: number;
/** Name of crime */
name: number;
name: string;
/** Milliseconds it takes to attempt the crime */
time: number;
/** Description of the crime activity */
@ -1045,7 +1080,7 @@ export declare interface CrimeStats {
export declare interface Division {
/** Name of the division */
name: string;
/** Type of division, like Aggriculture */
/** Type of division, like Agriculture */
type: string;
/** Awareness of the division */
awareness: number;
@ -1540,42 +1575,75 @@ export declare interface GangMemberAscension {
* @public
*/
export declare interface GangMemberInfo {
/** Name of the gang member */
name: string;
/** Currently assigned task */
task: string;
earnedRespect: number;
/** Hack skill level */
hack: number;
/** Strength skill level */
str: number;
/** Defense skill level */
def: number;
/** Dexterity skill level */
dex: number;
/** Agility skill level */
agi: number;
/** Charisma skill level */
cha: number;
/** Current hack experience */
hack_exp: number;
/** Current strength experience */
str_exp: number;
/** Current defense experience */
def_exp: number;
/** Current dexterity experience */
dex_exp: number;
/** Current agility experience */
agi_exp: number;
/** Current charisma experience */
cha_exp: number;
/** Hack multiplier from equipment */
hack_mult: number;
/** Strength multiplier from equipment */
str_mult: number;
/** Defense multiplier from equipment */
def_mult: number;
/** Dexterity multiplier from equipment */
dex_mult: number;
/** Agility multiplier from equipment */
agi_mult: number;
/** Charisma multiplier from equipment */
cha_mult: number;
/** Hack multiplier from ascensions */
hack_asc_mult: number;
/** Strength multiplier from ascensions */
str_asc_mult: number;
/** Defense multiplier from ascensions */
def_asc_mult: number;
/** Dexterity multiplier from ascensions */
dex_asc_mult: number;
/** Agility multiplier from ascensions */
agi_asc_mult: number;
/** Charisma multiplier from ascensions */
cha_asc_mult: number;
/** Total earned hack experience */
hack_asc_points: number;
/** Total earned strength experience */
str_asc_points: number;
/** Total earned defense experience */
def_asc_points: number;
/** Total earned dexterity experience */
dex_asc_points: number;
/** Total earned agility experience */
agi_asc_points: number;
/** Total earned charisma experience */
cha_asc_points: number;
upgrades: string[];
@ -1630,7 +1698,7 @@ export declare interface GangTaskStats {
baseMoney: number;
/** Hacking skill impact on task scaling */
hackWeight: number;
/** Stength skill impact on task scaling */
/** Strength skill impact on task scaling */
strWeight: number;
/** Defense skill impact on task scaling */
defWeight: number;
@ -1658,6 +1726,49 @@ export declare interface GangTerritory {
wanted: number;
}
/**
* Grafting API
* @remarks
* This API requires Source-File 10 to use.
* @public
*/
export declare interface Grafting {
/**
* Retrieve the grafting cost of an aug.
* @remarks
* RAM cost: 3.75 GB
*
* @param augName - Name of the aug to check the price of. Must be an exact match.
* @returns The cost required to graft the named augmentation.
* @throws Will error if an invalid Augmentation name is provided.
*/
getAugmentationGraftPrice(augName: string): number;
/**
* Retrieves the time required to graft an aug.
* @remarks
* RAM cost: 3.75 GB
*
* @param augName - Name of the aug to check the grafting time of. Must be an exact match.
* @returns The time required, in millis, to graft the named augmentation.
* @throws Will error if an invalid Augmentation name is provided.
*/
getAugmentationGraftTime(augName: string): number;
/**
* Begins grafting the named aug. You must be in New Tokyo to use this.
* @remarks
* RAM cost: 7.5 GB
*
* @param augName - The name of the aug to begin grafting. Must be an exact match.
* @param focus - Acquire player focus on this Augmentation grafting. Optional. Defaults to true.
* @returns True if the aug successfully began grafting, false otherwise (e.g. not enough money, or
* invalid Augmentation name provided).
* @throws Will error if called while you are not in New Tokyo.
*/
graftAugmentation(augName: string, focus?: boolean): boolean;
}
/**
* Hacking formulas
* @public
@ -1665,6 +1776,7 @@ export declare interface GangTerritory {
export declare interface HackingFormulas {
/**
* Calculate hack chance.
* (Ex: 0.25 would indicate a 25% chance of success.)
* @param server - Server info from {@link NS.getServer | getServer}
* @param player - Player info from {@link NS.getPlayer | getPlayer}
* @returns The calculated hack chance.
@ -1681,6 +1793,7 @@ export declare interface HackingFormulas {
hackExp(server: Server, player: Player): number;
/**
* Calculate hack percent for one thread.
* (Ex: 0.25 would steal 25% of the server's current value.)
* @remarks
* Multiply by thread to get total percent hacked.
* @param server - Server info from {@link NS.getServer | getServer}
@ -1689,7 +1802,8 @@ export declare interface HackingFormulas {
*/
hackPercent(server: Server, player: Player): number;
/**
* Calculate the percent a server would grow.
* Calculate the percent a server would grow to.
* (Ex: 3.0 would would grow the server to 300% of its current value.)
* @param server - Server info from {@link NS.getServer | getServer}
* @param threads - Amount of thread.
* @param player - Player info from {@link NS.getPlayer | getPlayer}
@ -1987,7 +2101,7 @@ export declare interface Hacknet {
* // NS1:
* var upgradeName = "Sell for Corporation Funds";
* if (hacknet.numHashes() > hacknet.hashCost(upgradeName)) {
* hacknet.spendHashes(upgName);
* hacknet.spendHashes(upgradeName);
* }
* ```
* @example
@ -1995,7 +2109,7 @@ export declare interface Hacknet {
* // NS2:
* const upgradeName = "Sell for Corporation Funds";
* if (ns.hacknet.numHashes() > ns.hacknet.hashCost(upgradeName)) {
* ns.hacknet.spendHashes(upgName);
* ns.hacknet.spendHashes(upgradeName);
* }
* ```
* @param upgName - Name of the upgrade of Hacknet Node.
@ -2069,7 +2183,7 @@ export declare interface Hacknet {
getHashUpgradeLevel(upgName: string): number;
/**
* Get the multipler to study.
* Get the multiplier to study.
* @remarks
* RAM cost: 0 GB
*
@ -2080,7 +2194,7 @@ export declare interface Hacknet {
getStudyMult(): number;
/**
* Get the multipler to training.
* Get the multiplier to training.
* @remarks
* RAM cost: 0 GB
*
@ -2453,7 +2567,7 @@ export declare interface NodeStats {
* ns.getHostname();
* // Some related functions are gathered under a sub-property of the ns object
* ns.stock.getPrice();
* // Some functions need to be await ed
* // Some functions need to be awaited
* await ns.hack('n00dles');
* }
* ```
@ -2521,6 +2635,13 @@ export declare interface NS extends Singularity {
*/
readonly ui: UserInterface;
/**
* Namespace for grafting functions.
* @remarks
* RAM cost: 0 GB
*/
readonly grafting: Grafting;
/**
* Arguments passed into the script.
*
@ -2555,13 +2676,11 @@ export declare interface NS extends Singularity {
* ```ts
* // NS1:
* var earnedMoney = hack("foodnstuff");
* earnedMoney = earnedMoney + hack("foodnstuff", { threads: 5 }); // Only use 5 threads to hack
* ```
* @example
* ```ts
* // NS2:
* let earnedMoney = await ns.hack("foodnstuff");
* earnedMoney += await ns.hack("foodnstuff", { threads: 5 }); // Only use 5 threads to hack
* ```
* @param host - Hostname of the target server to hack.
* @param opts - Optional parameters for configuring function behavior.
@ -2589,16 +2708,14 @@ export declare interface NS extends Singularity {
* @example
* ```ts
* // NS1:
* var availableMoney = getServerMoneyAvailable("foodnstuff");
* var currentMoney = getServerMoneyAvailable("foodnstuff");
* currentMoney = currentMoney * (1 + grow("foodnstuff"));
* currentMoney = currentMoney * (1 + grow("foodnstuff", { threads: 5 })); // Only use 5 threads to grow
* ```
* @example
* ```ts
* // NS2:
* let availableMoney = ns.getServerMoneyAvailable("foodnstuff");
* let currentMoney = ns.getServerMoneyAvailable("foodnstuff");
* currentMoney *= (1 + await ns.grow("foodnstuff"));
* currentMoney *= (1 + await ns.grow("foodnstuff", { threads: 5 })); // Only use 5 threads to grow
* ```
* @param host - Hostname of the target server to grow.
* @param opts - Optional parameters for configuring function behavior.
@ -2624,14 +2741,12 @@ export declare interface NS extends Singularity {
* // NS1:
* var currentSecurity = getServerSecurityLevel("foodnstuff");
* currentSecurity = currentSecurity - weaken("foodnstuff");
* currentSecurity = currentSecurity - weaken("foodnstuff", { threads: 5 }); // Only use 5 threads to weaken
* ```
* @example
* ```ts
* // NS2:
* let currentSecurity = ns.getServerSecurityLevel("foodnstuff");
* currentSecurity -= await ns.weaken("foodnstuff");
* currentSecurity -= await ns.weaken("foodnstuff", { threads: 5 }); // Only use 5 threads to weaken
* ```
* @param host - Hostname of the target server to weaken.
* @param opts - Optional parameters for configuring function behavior.
@ -2710,9 +2825,10 @@ export declare interface NS extends Singularity {
* Returns the security increase that would occur if a hack with this many threads happened.
*
* @param threads - Amount of threads that will be used.
* @param hostname - Hostname of the target server. The number of threads is limited to the number needed to hack the servers maximum amount of money.
* @returns The security increase.
*/
hackAnalyzeSecurity(threads: number): number;
hackAnalyzeSecurity(threads: number, hostname?: string): number;
/**
* Get the chance of successfully hacking a server.
@ -2818,6 +2934,17 @@ export declare interface NS extends Singularity {
*/
print(...args: any[]): void;
/**
* Prints a formatted string to the scripts logs.
* @remarks
* RAM cost: 0 GB
*
* see: https://github.com/alexei/sprintf.js
* @param format - format of the message
* @param args - Value(s) to be printed.
*/
printf(format: string, ...args: any[]): void;
/**
* Prints one or more values or variables to the Terminal.
* @remarks
@ -3276,6 +3403,34 @@ export declare interface NS extends Singularity {
* @returns True if the script is successfully killed, and false otherwise.
*/
kill(script: number): boolean;
/**
* {@inheritDoc NS.(kill:1)}
* @example
* ```ts
* // NS1:
* //The following example will try to kill a script named foo.script on the foodnstuff server that was ran with no arguments:
* kill("foo.script", "foodnstuff");
*
* //The following will try to kill a script named foo.script on the current server that was ran with no arguments:
* kill("foo.script", getHostname());
*
* //The following will try to kill a script named foo.script on the current server that was ran with the arguments 1 and “foodnstuff”:
* kill("foo.script", getHostname(), 1, "foodnstuff");
* ```
* @example
* ```ts
* // NS2:
* //The following example will try to kill a script named foo.script on the foodnstuff server that was ran with no arguments:
* ns.kill("foo.script", "foodnstuff");
*
* //The following will try to kill a script named foo.script on the current server that was ran with no arguments:
* ns.kill("foo.script", getHostname());
*
* //The following will try to kill a script named foo.script on the current server that was ran with the arguments 1 and “foodnstuff”:
* ns.kill("foo.script", getHostname(), 1, "foodnstuff");
* ```
*/
kill(script: string, host: string, ...args: string[]): boolean;
/**
@ -3341,6 +3496,37 @@ export declare interface NS extends Singularity {
* @returns True if the script/literature file is successfully copied over and false otherwise. If the files argument is an array then this function will return true if at least one of the files in the array is successfully copied.
*/
scp(files: string | string[], destination: string): Promise<boolean>;
/**
* {@inheritDoc NS.(scp:1)}
* @example
* ```ts
* // NS1:
* //Copies foo.lit from the helios server to the home computer:
* scp("foo.lit", "helios", "home");
*
* //Tries to copy three files from rothman-uni to home computer:
* files = ["foo1.lit", "foo2.script", "foo3.script"];
* scp(files, "rothman-uni", "home");
* ```
* @example
* ```ts
* // NS2:
* //Copies foo.lit from the helios server to the home computer:
* await ns.scp("foo.lit", "helios", "home");
*
* //Tries to copy three files from rothman-uni to home computer:
* files = ["foo1.lit", "foo2.script", "foo3.script"];
* await ns.scp(files, "rothman-uni", "home");
* ```
* @example
* ```ts
* //ns2, copies files from home to a target server
* const server = ns.args[0];
* const files = ["hack.js","weaken.js","grow.js"];
* await ns.scp(files, "home", server);
* ```
*/
scp(files: string | string[], source: string, destination: string): Promise<boolean>;
/**
@ -3367,8 +3553,8 @@ export declare interface NS extends Singularity {
* @example
* ```ts
* // NS1:
* const scripts = ps("home");
* for (let i = 0; i < scripts.length; ++i) {
* var scripts = ps("home");
* for (var i = 0; i < scripts.length; ++i) {
* tprint(scripts[i].filename + ' ' + scripts[i].threads);
* tprint(scripts[i].args);
* }
@ -3377,8 +3563,8 @@ export declare interface NS extends Singularity {
* ```ts
* // NS2:
* const ps = ns.ps("home");
* for (script of ps) {
* ns.tprint(`${script.filename} ${ps[i].threads}`);
* for (let script of ps) {
* ns.tprint(`${script.filename} ${script.threads}`);
* ns.tprint(script.args);
* }
* ```
@ -3748,13 +3934,13 @@ export declare interface NS extends Singularity {
* @remarks
* RAM cost: 0.3 GB
*
* Running with no args returns curent script.
* Running with no args returns current script.
* If you use a PID as the first parameter, the hostname and args parameters are unnecessary.
*
* @param filename - Optional. Filename or PID of the script.
* @param hostname - Optional. Name of host server the script is running on.
* @param args - Arguments to identify the script
* @returns info about a running script
* @returns The info about the running script if found, and null otherwise.
*/
getRunningScript(filename?: FilenameOrPID, hostname?: string, ...args: (string | number)[]): RunningScript;
@ -3905,7 +4091,7 @@ export declare interface NS extends Singularity {
* @param data - Data to write.
* @returns True if the data is successfully written to the port, and false otherwise.
*/
tryWritePort(port: number, data: string[] | number): Promise<boolean>;
tryWritePort(port: number, data: string | number): Promise<boolean>;
/**
* Read content of a file.
@ -4145,6 +4331,10 @@ export declare interface NS extends Singularity {
* @returns Amount of income the specified script generates while online.
*/
getScriptIncome(): [number, number];
/**
* {@inheritDoc NS.(getScriptIncome:1)}
*/
getScriptIncome(script: string, host: string, ...args: string[]): number;
/**
@ -4165,6 +4355,10 @@ export declare interface NS extends Singularity {
* @returns Amount of hacking experience the specified script generates while online.
*/
getScriptExpGain(): number;
/**
* {@inheritDoc NS.(getScriptExpGain:1)}
*/
getScriptExpGain(script: string, host: string, ...args: string[]): number;
/**
@ -4228,19 +4422,25 @@ export declare interface NS extends Singularity {
tFormat(milliseconds: number, milliPrecision?: boolean): string;
/**
* Prompt the player with a Yes/No modal.
* Prompt the player with an input modal.
* @remarks
* RAM cost: 0 GB
*
* Prompts the player with a dialog box with two options: Yes and No.
* This function will return true if the player click Yes and false if
* the player clicks No. The scripts execution is halted until the player
* selects one of the options.
* Prompts the player with a dialog box. If `options.type` is undefined or "boolean",
* the player is shown "Yes" and "No" prompts, which return true and false respectively.
* Passing a type of "text" will give the player a text field and a value of "select"
* will show a drop-down field. Choosing type "select" will require an array or object
* to be passed via the `options.choices` property.
* The scripts execution is halted until the player selects one of the options.
*
* @param txt - Text to appear in the prompt dialog box.
* @returns True if the player click Yes and false if the player clicks No.
* @param options - Options to modify the prompt the player is shown.
* @returns True if the player click Yes; false if the player clicks No; or the value entered by the player.
*/
prompt(txt: string): Promise<boolean>;
prompt(
txt: string,
options?: { type?: "boolean" | "text" | "select" | undefined; choices?: string[] },
): Promise<boolean | string>;
/**
* Open up a message box.
@ -4472,8 +4672,10 @@ export declare interface Office {
maxMor: number;
/** Name of all the employees */
employees: string[];
/** Positions of the employees */
/** Production of the employees */
employeeProd: EmployeeJobs;
/** Positions of the employees */
employeeJobs: EmployeeJobs;
}
/**
@ -4562,14 +4764,14 @@ export declare interface OfficeAPI {
/**
* Get the cost to unlock research
* @param divisionName - Name of the division
* @param cityName - Name of the city
* @param researchName - Name of the research
* @returns cost
*/
getResearchCost(divisionName: string, researchName: string): number;
/**
* Gets if you have unlocked a research
* @param divisionName - Name of the division
* @param cityName - Name of the city
* @param researchName - Name of the research
* @returns true is unlocked, false if not
*/
hasResearched(divisionName: string, researchName: string): boolean;
@ -4693,6 +4895,8 @@ export declare interface Player {
factions: string[];
tor: boolean;
hasCorporation: boolean;
inBladeburner: boolean;
entropy: number;
}
/**
@ -4710,7 +4914,7 @@ export declare interface PlayerSkills {
dexterity: number;
/** Agility level */
agility: number;
/** Chraisma level */
/** Charisma level */
charisma: number;
/** Intelligence level */
intelligence: number;
@ -4771,9 +4975,11 @@ export declare interface RunningScript {
logs: string[];
offlineExpGained: number;
offlineMoneyMade: number;
/** Offline running time of the script, in seconds **/
offlineRunningTime: number;
onlineExpGained: number;
onlineMoneyMade: number;
/** Online running time of the script, in seconds **/
onlineRunningTime: number;
pid: number;
ramUsage: number;
@ -4807,7 +5013,7 @@ export declare interface Server {
/** IP Address. Must be unique */
ip: string;
/** Flag indicating whether player is curently connected to this server */
/** Flag indicating whether player is currently connected to this server */
isConnectedTo: boolean;
/** RAM (GB) available on this server */
@ -4946,7 +5152,7 @@ export declare interface Singularity {
* purchasing a TOR router using this function is the same as if you were to
* manually purchase one.
*
* @returns True if actions is successful, false otherwise.
* @returns True if actions is successful or you already own TOR router, false otherwise.
*/
purchaseTor(): boolean;
@ -4983,7 +5189,7 @@ export declare interface Singularity {
*
*
* Returns a boolean indicating whether or not the player is currently performing an
* action. These actions include working for a company/faction, studying at a univeristy,
* action. These actions include working for a company/faction, studying at a university,
* working out at a gym, creating a program, committing a crime, or carrying out a Hacking Mission.
*
* @returns True if the player is currently performing an action, false otherwise.
@ -5002,9 +5208,10 @@ export declare interface Singularity {
* The actions that can be stopped with this function are:
*
* * Studying at a university
* * Working out at a gym
* * Working for a company/faction
* * Creating a program
* * Committing a Crime
* * Committing a crime
*
* This function will return true if the players action was ended.
* It will return false if the player was not performing an action when this function was called.
@ -5637,6 +5844,67 @@ export declare interface Singularity {
* @returns True if the focus was changed.
*/
setFocus(focus: boolean): boolean;
/**
* Get a list of programs offered on the dark web.
* @remarks
* RAM cost: 1 GB * 16/4/1
*
*
* This function allows the player to get a list of programs available for purchase
* on the dark web. Players MUST have purchased Tor to get the list of programs
* available. If Tor has not been purchased yet, this function will return an
* empty list.
*
* @example
* ```ts
* // NS1
* getDarkwebProgramsAvailable();
* // returns ['BruteSSH.exe', 'FTPCrack.exe'...etc]
* ```
* @example
* ```ts
* // NS2
* ns.getDarkwebProgramsAvailable();
* // returns ['BruteSSH.exe', 'FTPCrack.exe'...etc]
* ```
* @returns - a list of programs available for purchase on the dark web, or [] if Tor has not
* been purchased
*/
getDarkwebPrograms(): string[];
/**
* Check the price of an exploit on the dark web
* @remarks
* RAM cost: 0.5 GB * 16/4/1
*
*
* This function allows you to check the price of a darkweb exploit/program.
* You MUST have a TOR router in order to use this function. The price returned
* by this function is the same price you would see with buy -l from the terminal.
* Returns the cost of the program if it has not been purchased yet, 0 if it
* has already been purchased, or -1 if Tor has not been purchased (and thus
* the program/exploit is not available for purchase).
*
* If the program does not exist, an error is thrown.
*
*
* @example
* ```ts
* // NS1
* getDarkwebProgramCost("brutessh.exe");
* ```
* @example
* ```ts
* // NS2
* ns.getDarkwebProgramCost("brutessh.exe");
* ```
* @param programName - Name of program to check the price of
* @returns Price of the specified darkweb program
* (if not yet purchased), 0 if it has already been purchased, or -1 if Tor has not been
* purchased. Throws an error if the specified program/exploit does not exist
*/
getDarkwebProgramCost(programName: string): number;
}
/**
@ -5971,14 +6239,14 @@ export declare interface Stanek {
* RAM cost: 0.4 GB
* @returns The width of the gift.
*/
width(): number;
giftWidth(): number;
/**
* Stanek's Gift height.
* @remarks
* RAM cost: 0.4 GB
* @returns The height of the gift.
*/
height(): number;
giftHeight(): number;
/**
* Charge a fragment, increasing its power.
@ -5988,7 +6256,7 @@ export declare interface Stanek {
* @param rootY - rootY Root Y against which to align the top left of the fragment.
* @returns Promise that lasts until the charge action is over.
*/
charge(rootX: number, rootY: number): Promise<void>;
chargeFragment(rootX: number, rootY: number): Promise<void>;
/**
* List possible fragments.
@ -6013,7 +6281,7 @@ export declare interface Stanek {
* @remarks
* RAM cost: 0 GB
*/
clear(): void;
clearGift(): void;
/**
* Check if fragment can be placed at specified location.
@ -6026,7 +6294,7 @@ export declare interface Stanek {
* @param fragmentId - fragmentId ID of the fragment to place.
* @returns true if the fragment can be placed at that position. false otherwise.
*/
canPlace(rootX: number, rootY: number, rotation: number, fragmentId: number): boolean;
canPlaceFragment(rootX: number, rootY: number, rotation: number, fragmentId: number): boolean;
/**
* Place fragment on Stanek's Gift.
* @remarks
@ -6038,7 +6306,7 @@ export declare interface Stanek {
* @param fragmentId - ID of the fragment to place.
* @returns true if the fragment can be placed at that position. false otherwise.
*/
place(rootX: number, rootY: number, rotation: number, fragmentId: number): boolean;
placeFragment(rootX: number, rootY: number, rotation: number, fragmentId: number): boolean;
/**
* Get placed fragment at location.
* @remarks
@ -6048,7 +6316,7 @@ export declare interface Stanek {
* @param rootY - Y against which to align the top left of the fragment.
* @returns The fragment at [rootX, rootY], if any.
*/
get(rootX: number, rootY: number): ActiveFragment | undefined;
getFragment(rootX: number, rootY: number): ActiveFragment | undefined;
/**
* Remove fragment at location.
@ -6059,7 +6327,7 @@ export declare interface Stanek {
* @param rootY - Y against which to align the top left of the fragment.
* @returns The fragment at [rootX, rootY], if any.
*/
remove(rootX: number, rootY: number): boolean;
removeFragment(rootX: number, rootY: number): boolean;
}
/**
@ -6448,6 +6716,20 @@ export declare interface TIX {
* @returns True if you successfully purchased it or if you already have access, false otherwise.
*/
purchase4SMarketDataTixApi(): boolean;
/**
* Purchase WSE Account.
* @remarks RAM cost: 2.5 GB
* @returns True if you successfully purchased it or if you already have access, false otherwise.
*/
purchaseWseAccount(): boolean;
/**
* Purchase TIX API Access
* @remarks RAM cost: 2.5 GB
* @returns True if you successfully purchased it or if you already have access, false otherwise.
*/
purchaseTixApi(): boolean;
}
/**
@ -6627,6 +6909,14 @@ export declare interface WarehouseAPI {
* @param enabled - smart supply enabled
*/
setSmartSupply(divisionName: string, cityName: string, enabled: boolean): void;
/**
* Set whether smart supply uses leftovers before buying
* @param divisionName - Name of the division
* @param cityName - Name of the city
* @param materialName - Name of the material
* @param enabled - smart supply use leftovers enabled
*/
setSmartSupplyUseLeftovers(divisionName: string, cityName: string, materialName: string, enabled: boolean): void;
/**
* Set material buy data
* @param divisionName - Name of the division
@ -6635,6 +6925,14 @@ export declare interface WarehouseAPI {
* @param amt - Amount of material to buy
*/
buyMaterial(divisionName: string, cityName: string, materialName: string, amt: number): void;
/**
* Set material to bulk buy
* @param divisionName - Name of the division
* @param cityName - Name of the city
* @param materialName - Name of the material
* @param amt - Amount of material to buy
*/
bulkPurchase(divisionName: string, cityName: string, materialName: string, amt: number): void;
/**
* Get warehouse data
* @param divisionName - Name of the division

@ -1,2 +0,0 @@
!function(n){function t(t){for(var e,i,f=t[0],c=t[1],l=t[2],a=0,s=[];a<f.length;a++)i=f[a],Object.prototype.hasOwnProperty.call(r,i)&&r[i]&&s.push(r[i][0]),r[i]=0;for(e in c)Object.prototype.hasOwnProperty.call(c,e)&&(n[e]=c[e]);for(p&&p(t);s.length;)s.shift()();return u.push.apply(u,l||[]),o()}function o(){for(var n,t=0;t<u.length;t++){for(var o=u[t],e=!0,f=1;f<o.length;f++){var c=o[f];0!==r[c]&&(e=!1)}e&&(u.splice(t--,1),n=i(i.s=o[0]))}return n}var e={},r={2:0},u=[];function i(t){if(e[t])return e[t].exports;var o=e[t]={i:t,l:!1,exports:{}};return n[t].call(o.exports,o,o.exports,i),o.l=!0,o.exports}i.m=n,i.c=e,i.d=function(n,t,o){i.o(n,t)||Object.defineProperty(n,t,{enumerable:!0,get:o})},i.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},i.t=function(n,t){if(1&t&&(n=i(n)),8&t)return n;if(4&t&&"object"==typeof n&&n&&n.__esModule)return n;var o=Object.create(null);if(i.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:n}),2&t&&"string"!=typeof n)for(var e in n)i.d(o,e,function(t){return n[t]}.bind(null,e));return o},i.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return i.d(t,"a",t),t},i.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},i.p="";var f=window.webpackJsonp=window.webpackJsonp||[],c=f.push.bind(f);f.push=t,f=f.slice();for(var l=0;l<f.length;l++)t(f[l]);var p=c;u.push([1281,0]),o()}({1281:function(n,t,o){"use strict";o.r(t);o(1282),o(1284),o(1286),o(1288),o(1290),o(1292),o(1294),o(1296),o(1298),o(1300),o(1302),o(1304),o(1306),o(1308),o(1310),o(1312),o(1314),o(1316),o(1318),o(1320),o(1322),o(1324),o(1326),o(1328),o(1330),o(1332),o(1334),o(1336),o(1338),o(1340)},1284:function(n,t,o){},1286:function(n,t,o){},1288:function(n,t,o){},1290:function(n,t,o){},1292:function(n,t,o){},1294:function(n,t,o){},1296:function(n,t,o){},1298:function(n,t,o){},1300:function(n,t,o){},1302:function(n,t,o){},1304:function(n,t,o){},1306:function(n,t,o){},1308:function(n,t,o){},1310:function(n,t,o){},1312:function(n,t,o){},1314:function(n,t,o){},1316:function(n,t,o){},1318:function(n,t,o){},1320:function(n,t,o){},1322:function(n,t,o){},1324:function(n,t,o){},1326:function(n,t,o){},1328:function(n,t,o){},1330:function(n,t,o){},1332:function(n,t,o){},1334:function(n,t,o){},1336:function(n,t,o){},1338:function(n,t,o){},1340:function(n,t,o){}});
//# sourceMappingURL=engineStyle.bundle.js.map

6070
dist/engineStyle.css vendored

File diff suppressed because it is too large Load Diff

101
dist/vendor.bundle.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

301
dist/vendor.css vendored

@ -1,301 +0,0 @@
/*! normalize.css v8.0.0 | MIT License | github.com/necolas/normalize.css */
/* Document
========================================================================== */
/**
* 1. Correct the line height in all browsers.
* 2. Prevent adjustments of font size after orientation changes in iOS.
*/
html {
line-height: 1.15;
/* 1 */
-webkit-text-size-adjust: 100%;
/* 2 */ }
/* Sections
========================================================================== */
/**
* Remove the margin in all browsers.
*/
body {
margin: 0; }
/**
* Correct the font size and margin on `h1` elements within `section` and
* `article` contexts in Chrome, Firefox, and Safari.
*/
h1 {
font-size: 2em;
margin: 0.67em 0; }
/* Grouping content
========================================================================== */
/**
* 1. Add the correct box sizing in Firefox.
* 2. Show the overflow in Edge and IE.
*/
hr {
box-sizing: content-box;
/* 1 */
height: 0;
/* 1 */
overflow: visible;
/* 2 */ }
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
pre {
font-family: monospace, monospace;
/* 1 */
font-size: 1em;
/* 2 */ }
/* Text-level semantics
========================================================================== */
/**
* Remove the gray background on active links in IE 10.
*/
a {
background-color: transparent; }
/**
* 1. Remove the bottom border in Chrome 57-
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
*/
abbr[title] {
border-bottom: none;
/* 1 */
text-decoration: underline;
/* 2 */
text-decoration: underline dotted;
/* 2 */ }
/**
* Add the correct font weight in Chrome, Edge, and Safari.
*/
b,
strong {
font-weight: bolder; }
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
samp {
font-family: monospace, monospace;
/* 1 */
font-size: 1em;
/* 2 */ }
/**
* Add the correct font size in all browsers.
*/
small {
font-size: 80%; }
/**
* Prevent `sub` and `sup` elements from affecting the line height in
* all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline; }
sub {
bottom: -0.25em; }
sup {
top: -0.5em; }
/* Embedded content
========================================================================== */
/**
* Remove the border on images inside links in IE 10.
*/
img {
border-style: none; }
/* Forms
========================================================================== */
/**
* 1. Change the font styles in all browsers.
* 2. Remove the margin in Firefox and Safari.
*/
button,
input,
optgroup,
select,
textarea {
font-family: inherit;
/* 1 */
font-size: 100%;
/* 1 */
line-height: 1.15;
/* 1 */
margin: 0;
/* 2 */ }
/**
* Show the overflow in IE.
* 1. Show the overflow in Edge.
*/
button,
input {
/* 1 */
overflow: visible; }
/**
* Remove the inheritance of text transform in Edge, Firefox, and IE.
* 1. Remove the inheritance of text transform in Firefox.
*/
button,
select {
/* 1 */
text-transform: none; }
/**
* Correct the inability to style clickable types in iOS and Safari.
*/
button,
[type="button"],
[type="reset"],
[type="submit"] {
-webkit-appearance: button; }
/**
* Remove the inner border and padding in Firefox.
*/
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0; }
/**
* Restore the focus styles unset by the previous rule.
*/
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
outline: 1px dotted ButtonText; }
/**
* Correct the padding in Firefox.
*/
fieldset {
padding: 0.35em 0.75em 0.625em; }
/**
* 1. Correct the text wrapping in Edge and IE.
* 2. Correct the color inheritance from `fieldset` elements in IE.
* 3. Remove the padding so developers are not caught out when they zero out
* `fieldset` elements in all browsers.
*/
legend {
box-sizing: border-box;
/* 1 */
color: inherit;
/* 2 */
display: table;
/* 1 */
max-width: 100%;
/* 1 */
padding: 0;
/* 3 */
white-space: normal;
/* 1 */ }
/**
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
*/
progress {
vertical-align: baseline; }
/**
* Remove the default vertical scrollbar in IE 10+.
*/
textarea {
overflow: auto; }
/**
* 1. Add the correct box sizing in IE 10.
* 2. Remove the padding in IE 10.
*/
[type="checkbox"],
[type="radio"] {
box-sizing: border-box;
/* 1 */
padding: 0;
/* 2 */ }
/**
* Correct the cursor style of increment and decrement buttons in Chrome.
*/
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto; }
/**
* 1. Correct the odd appearance in Chrome and Safari.
* 2. Correct the outline style in Safari.
*/
[type="search"] {
-webkit-appearance: textfield;
/* 1 */
outline-offset: -2px;
/* 2 */ }
/**
* Remove the inner padding in Chrome and Safari on macOS.
*/
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none; }
/**
* 1. Correct the inability to style clickable types in iOS and Safari.
* 2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button;
/* 1 */
font: inherit;
/* 2 */ }
/* Interactive
========================================================================== */
/*
* Add the correct display in Edge, IE 10+, and Firefox.
*/
details {
display: block; }
/*
* Add the correct display in all browsers.
*/
summary {
display: list-item; }
/* Misc
========================================================================== */
/**
* Add the correct display in IE 10+.
*/
template {
display: none; }
/**
* Add the correct display in IE 10.
*/
[hidden] {
display: none; }
/*# sourceMappingURL=vendor.css.map*/

@ -25,8 +25,8 @@ I need equations that test many different aspect of "math culture", it can be ch
All variable purchasing will be scriptable.
All equation must have:
- several variables that can be upgraded, at least 1 variable must be strategic in it's upgrading (upgrading too much can cause drop in performance)
- Some sort of math twist that requires some thinking, like (-2)^c1 alters between positive and negative.

@ -115,7 +115,6 @@ Fork and clone the repo
- 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
@ -131,7 +130,6 @@ Inside the root of the repo run
After that you can open any browser and navigate to `localhost:8000` and play the game.
Saving a file will reload the game automatically.
### How to build the electron app
Tested on Node v16.13.1 (LTS) on Windows

@ -23,10 +23,11 @@ Yes, just export the save file from the options menu & import it in the other pl
## 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.
- 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.
---
@ -51,11 +52,13 @@ You can navigate to the game files by right-clicking the game in your library an
## 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).
@ -68,17 +71,17 @@ When launching the game, you will be prompted with three options. If the standar
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`
- 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`
- on Linux: `~/.config/bitburner/config.json`
- on macOS: `~/Library/Application\ Support/bitburner/config.json`
- on Windows: `%USERPROFILE%\AppData\Roaming\bitburner\config.json`
---

@ -12,4 +12,5 @@ must be unlocked.
Source-Files <advancedgameplay/sourcefiles>
Intelligence <advancedgameplay/intelligence>
Sleeves <advancedgameplay/sleeves>
Grafting <advancedgameplay/grafting>
Hacking algorithms <advancedgameplay/hackingalgorithms>

@ -0,0 +1,18 @@
.. _gameplay_grafting:
Grafting
========
Grafting is an experimental process through which you can obtain the benefits of
Augmentations, without needing to reboot your body.
Grafting can be done at VitaLife in New Tokyo, where you'll find a shady researcher with
questionable connections. From there, you can spend a sum of money to begin grafting
Augmentations. This will take some time. When done, the Augmentation will be applied to
your character without needing to install.
Be warned, some who have tested grafting have reported an unidentified malware. Dubbed
"Entropy", this virus seems to grow in potency as more Augmentations are grafted,
causing unpredictable affects to the victim.
Note that when crafting an Augmentation, cancelling will **not** save your progress,
and the money spent will **not** be returned.

@ -6,10 +6,8 @@ Intelligence is a :ref:`stat <gameplay_stats>` that is unlocked by having
:ref:`Source-File 5 <gameplay_sourcefiles>` (i.e. Destroying BitNode-5).
Intelligence is unique because it is permanent and persistent. It never gets reset
back to 1. However, gaining Intelligence experience is extremely slow. The methods
of gaining Intelligence exp is also hidden. You won't know when you gain
experience and how much. It is a stat that gradually builds up as you continue
to play the game.
back to 1. However, gaining Intelligence experience is extremely slow. It is a stat
that gradually builds up as you continue to play the game.
Intelligence will boost your production for many actions in the game, including:
@ -18,3 +16,4 @@ Intelligence will boost your production for many actions in the game, including:
* Crime success rate
* Bladeburner
* Reputation gain for companies & factions
* Augmentation grafting speed

@ -91,19 +91,3 @@ and above, and is only available after defeating BitNode-10 at least once.
Memory is a persistent stat, meaning it never gets reset back to 1.
The maximum possible value for a sleeve's memory is 100.
Re-sleeving
^^^^^^^^^^^
Re-sleeving is the process of digitizing and transferring your consciousness into a
new human body, or "sleeve". When you re-sleeve into a new body, your stat experience
and Augmentations get replaced with those of the new body.
In order to re-sleeve, you must purchase new bodies. This can be done at VitaLife in
New Tokyo. Once you purchase a body to re-sleeve into, the effects will take
place immediately.
Note that resleeving **REMOVES** all of your currently-installed Augmentations,
and replaces them with the ones provided by the purchased sleeve. However,
Augmentations that are purchased but not installed will **not** be removed. If you have purchased
an Augmentation and then re-sleeve into a body which already has that Augmentation,
it will be removed since you cannot have duplicate Augmentations.

@ -53,6 +53,7 @@ List of all Source-Files
+-------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|| BitNode-10: Digital Carbon || * Each level of this grants a Duplicate Sleeve. |
|| || * Allows the player to access the `Sleeve API <https://github.com/danielyxie/bitburner/blob/dev/markdown/bitburner.sleeve.md>`_ in other BitNodes. |
|| || * Grants the player access to the VitaLife secret laboratory in other BitNodes. Also grants access to the Grafting API. |
+-------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|| BitNode-11: The Big Crash || * Company favor increases both the player's salary and reputation gain at that |
|| || company by 1% per favor (rather than just the reputation gain). |

@ -2,7 +2,7 @@
Augmentations
=============
Advances in science and medicine have lead to powerful new technologies
Advances in science and medicine have led to powerful new technologies
that allow people to augment themselves beyond normal human capabilities.
There are many different types of Augmentations, ranging from cybernetic
to genetic to biological. Acquiring these Augmentations enhances the

@ -93,9 +93,15 @@ The list contains the name of (i.e. the value returned by
| Subarray with Maximum Sum | | Given an array of integers, find the contiguous subarray (containing |
| | | at least one number) which has the largest sum and return that sum. |
+------------------------------------+------------------------------------------------------------------------------------------+
| Total Ways to Sum | | Given a number, how many different ways can that number be written as |
| Total Ways to Sum | | Given a number, how many different distinct ways can that number be written as |
| | | a sum of at least two positive integers? |
+------------------------------------+------------------------------------------------------------------------------------------+
| Total Ways to Sum II | | You are given an array with two elements. The first element is an integer n. |
| | | The second element is an array of numbers representing the set of available integers. |
| | | How many different distinct ways can that number n be written as |
| | | a sum of integers contained in the given set? |
| | | You may use each integer in the set zero or more times. |
+------------------------------------+------------------------------------------------------------------------------------------+
| Spiralize Matrix | | Given an array of array of numbers representing a 2D matrix, return the |
| | | elements of that matrix in clockwise spiral order. |
| | | |
@ -115,6 +121,16 @@ The list contains the name of (i.e. the value returned by
| | | Assuming you are initially positioned at the start of the array, determine |
| | | whether you are able to reach the last index of the array. |
+------------------------------------+------------------------------------------------------------------------------------------+
| Array Jumping Game II | | You are given an array of integers where each element represents the |
| | | maximum possible jump distance from that position. For example, if you |
| | | are at position i and your maximum jump length is n, then you can jump |
| | | to any position from i to i+n. |
| | | |
| | | Assuming you are initially positioned at the start of the array, determine |
| | | the minimum number of jumps to reach the end of the array. |
| | | |
| | | If it's impossible to reach the end, then the answer should be 0. |
+------------------------------------+------------------------------------------------------------------------------------------+
| Merge Overlapping Intervals | | Given an array of intervals, merge all overlapping intervals. An interval |
| | | is an array with two numbers, where the first number is always less than |
| | | the second (e.g. [1, 5]). |
@ -196,6 +212,23 @@ The list contains the name of (i.e. the value returned by
| | | |
| | | Determine how many unique paths there are from start to finish. |
+------------------------------------+------------------------------------------------------------------------------------------+
| Shortest Path in a Grid | | You are given a 2D array of numbers (array of array of numbers) representing |
| | | a grid. The 2D array contains 1's and 0's, where 1 represents an obstacle and |
| | | 0 represents a free space. |
| | | |
| | | Assume you are initially positioned in top-left corner of that grid and that you |
| | | are trying to reach the bottom-right corner. In each step, you may move to the up, |
| | | down, left or right. Furthermore, you cannot move onto spaces which have obstacles. |
| | | |
| | | Determine if paths exist from start to destination, and find the shortest one. |
| | | |
| | | Examples: |
| | | [[0,1,0,0,0], |
| | | [0,0,0,1,0]] -> "DRRURRD" |
| | | [[0,1], |
| | | [1,0]] -> "" |
| | | |
+------------------------------------+------------------------------------------------------------------------------------------+
| Sanitize Parentheses in Expression | | Given a string with parentheses and letters, remove the minimum number of invalid |
| | | parentheses in order to validate the string. If there are multiple minimal ways |
| | | to validate the string, provide all of the possible results. |
@ -215,6 +248,7 @@ The list contains the name of (i.e. the value returned by
| | | The answer should be provided as an array of strings containing the valid expressions. |
| | | |
| | | NOTE: Numbers in an expression cannot have leading 0's |
| | | NOTE: The order of evaluation expects script operator precedence |
| | | |
| | | Examples: |
| | | Input: digits = "123", target = 6 |

@ -7,6 +7,16 @@ these companies, you can apply for jobs.
Working a job lets you earn money, experience, and reputation with that company.
While working for a company, you can click "Do something else simultaneously" to be able
to do things while you continue to work in the background. There is a 20% penalty to the
related gains. Clicking the "Focus" button under the overview will return you to the
current work.
Reputation is required to apply for a promotion. This reputation is not counted towards
your career until the shift ends, either due to the time spent or clicking the
"Stop Working" button. For most jobs there is a penalty of 50% of the reputation gained
if you stop your shift early.
Information about all Companies
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TODO

@ -107,3 +107,14 @@ starting security, rounded to the nearest integer. To be more precise::
This means that a server's security level will not fall below this
value if you are trying to weaken() it.
Backdoors
^^^^^^^^^
Servers that can be hacked can also have backdoors installed. These backdoors
will provide you with a benefit; the services may be cheaper, penalties may
be reduced or there may be other results. Honeypots exist and will let factions
know when you have succeeded at backdooring their system. Once you have a
backdoor installed, you can connect to that server directly.
When you visit a location in the city and see that the name is partially scrambled,
this indicates that you have backdoored the server related to the location.

@ -21,23 +21,19 @@ can be used to check how much RAM a server has.
Identifying Servers
^^^^^^^^^^^^^^^^^^^
A server is identified by two properties: its IP address and its hostname.
An IP address is a 32-bit number represented in dot-decimal notation.
For example, "56.1.5.0" and "86.5.1.0" might be two IP addresses
you see in the game. A hostname is a label assigned to a server.
A server is identified by its hostname.
A hostname is a label assigned to a server.
A hostname will usually give you a general idea of what the server
is. For example, the company Nova Medical might have a server with
the hostname "nova-med".
Hostnames and IP addresses are unique. This means that if one
server has the IP address "1.1.1.1" and the hostname
"some-server", then no other server in the game can have that
IP address or that hostname.
Hostnames are unique. This means that if one
server has the the hostname "some-server", then no other server
in the game can have that that hostname.
There are many :ref:`Netscript Functions <netscriptfunctions>`
and :ref:`terminal` commands in the game
that will require you to target a specific server. This is done using
either the IP address or the hostname of the server.
that will require you to target a specific server by hostname.
Player-owned Servers
^^^^^^^^^^^^^^^^^^^^

@ -239,7 +239,7 @@ connect
$ connect [hostname/ip]
Connect to a remote server. The hostname or IP address of the remote server must
Connect to a remote server. The hostname of the remote server must
be given as the argument to this command. Note that only servers that are immediately
adjacent to the current server in the network can be connected to. To see which
servers can be connected to, use the 'scan' command.
@ -335,7 +335,7 @@ Then to kill this script the same arguments would have to be used::
$ kill foo.script 50e3 sigma-cosmetics
If you are killing the script using its PID, then the PID argument must be numeric.
If you are killing the script using its PID, then the PID argument must be numeric.
killall
^^^^^^^
@ -347,7 +347,7 @@ Kills all scripts on the current server.
ls
^^
$ ls [dir] [| grep pattern]
$ ls [dir] [--grep pattern]
Prints files and directories on the current server to the Terminal screen.
@ -358,19 +358,21 @@ followed by the files (also in alphabetical order).
The :code:`dir` optional parameter allows you to specify the directory for which to display
files.
The :code:`| grep pattern` optional parameter allows you to only display files and directories
The :code:`--grep pattern` optional parameter allows you to only display files and directories
with a certain pattern in their names.
The :code:`-l` optional parameter allows you to force each item onto a single line.
Examples::
// List files/directories with the '.script' extension in the current directory
$ ls | grep .script
$ ls -l --grep .script
// List files/directories with the '.js' extension in the root directory
$ ls / | grep .js
$ ls / -l --grep .js
// List files/directories with the word 'purchase' in the name, in the :code:`scripts` directory
$ ls scripts | grep purchase
$ ls scripts -l --grep purchase
lscpu
@ -542,28 +544,6 @@ Then in order to check its logs with 'tail' the same arguments must be used::
$ tail foo.script 10 50000
theme
^^^^^
$ theme [preset] | [#background #text #highlight]
Change the color of the game's user interface
This command can be called with a preset theme. Currently, the supported presets are:
* default
* muted
* solarized
However, you can also specify your own color scheme using hex values.
To do so, you must specify three hex color values for the background
color, the text color, and the highlight color. These hex values must
be preceded by a pound sign (#) and must be either 3 or 6 digits. Example::
$ theme #ffffff #385 #235012
A color picker such as Google's can be used to get your desired hex color values
top
^^^

@ -3,6 +3,299 @@
Changelog
=========
v1.6.3 - 2022-04-01 Few stanek fixes
------------------------------------
Stanek Gift
* Has a minimum size of 2x3
* Active Fragment property 'avgCharge' renamed to 'highestCharge'
* Formula for fragment effect updated to make 561% more sense.
Now you can charge to your heart content.
* Logs for the 'chargeFragment' function updated.
Misc.
* Nerf noodle bar.
v1.6.0 - 2022-03-29 Grafting
----------------------------
** Vitalife secret lab **
* A new mechanic called Augmentation Grafting has been added. Resleeving has been removed.
* Credit to @nickofolas for his incredible work.
** Stanek **
* BREAKING: Many functions in the stanek API were renamed in order to avoid name collision with things like Map.prototype.get
** UI **
* Major update to Sleeve, Gang UI, and Create Program (@nickofolas)
* re-add pre tags to support slash n in prompt (@jacktose)
* Tabelize linked output of 'ls' (@Master-Guy)
* Add the ability to filter open scripts (@phyzical)
* Add minHeight to editor tabs (@nickofolas)
* Properly expand gang equipment cards to fill entire screen (@nickofolas)
* Add shortcut to Faction augmentations page from FactionsRoot (@nickofolas)
* Fix extra space on editor tabs (@nickofolas)
* Present offline message as list (@DSteve595)
* add box showing remaining augments per faction (@jjayeon)
* Add tab switching support to vim mode (@JParisFerrer)
* Show current task on gang management screen (@zeddrak)
* Fix for ui of gang members current task when set via api (@phyzical)
* Don't hide irrelevant materials if their stock is not empty and hide irrelevant divisions from Export (@SagePtr)
* Fix regex to enable alpha transparency hex codes (8 digits) (@surdaft)
** API **
* Added dark web functions to ns api
* BREAKING: purchaseTor() should returns true if player already has Tor. (@DavidGrinberg, @waffleattack)
* Implement getBonusTime in Corporation API (@t-wolfeadam)
* Added functions to purchase TIX and WSI (@incubusnb)
* purchaseSleeveAug checks shock value (@incubusnb)
* Fix bug with hacknet api
* Fix spendHashes bug
* Added 0 cost of asleep() (@Master-Guy)
* Fix some misleading corporation errors (@TheRealMaxion)
* expose the inBladeburner on the player object (@phyzical)
* added ram charge for stanek width and height (@phyzical)
* Fix sufficient player money check to buy back shares. (@ChrissiQ)
* Fix Static Ram Circumventing for some NS functions (@CrafterKolyan)
* added CorporationSoftCap to NetscriptDefinitions (@phyzical)
* Added definition of autocomplete() 'data' argument. (@tigercat2000)
* Adding support for text/select options in Prompt command (@PhilipArmstead)
* Added the ability to exportGame via api (@phyzical)
** Arcade **
* Added an arcade to New Tokyo where you can play a 4 year old version of bitburner.
** Misc. **
* Add a warning triggered while auto-saves are off. (@MartinFournier)
* Log info for field analysis now displays actual rank gained. (@ApamNapat)
* Removed BladeburnerSkillCost from skill point cost description. (@ApamNapat)
* Fix handling for UpArrow in bladeburner console. (@dowinter)
* Add GitHub action to check PRs for generated files. (@MartinFournier)
* Cap Staneks gift at 25x25 to prevent crashes. (@waffleattack)
* Remove old & unused files from repository. (@MartinFournier)
* Factions on the factions screens are sorted by story progress / type. (@phyzical)
* Fix log manager not picking up new runs of scripts. (@phyzical)
* Added prettier to cicd.
* UI improvements (@phyzical)
* Documentation / Typos (@nanogyth, @Master-Guy, @incubusnb, @ApamNapat, @phyzical, @SagePtr)
* Give player code a copy of Division.upgrades instead of the live object (@Ornedan)
* Fix bug with small town achievement.
* Fix bug with purchaseSleeveAug (@phyzical)
* Check before unlocking corp upgrade (@gianfun)
* General codebase improvements. (@phyzical, @Master-Guy, @ApamNapat)
* Waiting on promises in NS1 no longer freezes the script. (@Master-Guy)
* Fix bug with missing ramcost for tFormat (@TheMas3212)
* Fix crash with new prompt
* Quick fix to prevent division by 0 in terminal (@Master-Guy)
* removed ip references (@phyzical, @Master-Guy)
* Terminal now supports 'ls -l'
* Fix negative number formatting (@Master-Guy)
* Fix unique ip generation (@InDieTasten)
* remove terminal command theme from docs (@phyzical)
* Fix 'Augmentations Left' with gang factions (@nickofolas)
* Attempt to fix 'bladeburner.process()' early routing issue (@MartinFournier)
* work in progress augment fix (@phyzical)
* Fixes missing space in Smart Supply (@TheRealMaxion)
* Change license to Apache 2 with Commons Clause
* updated regex sanitization (@mbrannen)
* Sleeve fix for when faction isnt found (@phyzical)
* Fix editor "close" naming (@phyzical)
* Fix bug with sleeves where some factions would be listed as workable. (@phyzical)
* Fix research tree of product industries post-prestige (@pd)
* Added a check for exisiting industry type before expanding (@phyzical)
* fix hackAnalyzeThreads returning infinity (@chrisrabe)
* Make growthAnalyze more accurate (@dwRchyngqxs)
* Add 'Zoom -> Reset Zoom' command to Steam (@smolgumball)
* Add hasOwnProperty check to GetServer (@SagePtr)
* Speed up employee productivity calculation (@pd)
* Field Work and Security Work benefit from 'share' (@SagePtr)
* Nerf noodle bar.
v1.5.0 - Steam Cloud integration
--------------------------------
** Steam Cloud Saving **
* Added support for steam cloud saving (@MartinFournier)
** UI **
* background now matches game primary color (@nickofolas)
* page title contains version (@MartinFourier)
* Major text editor improvements (@nickofolas)
* Display bonus time on sleeve page (@MartinFourier)
* Several UI improvements (@nickofolas, @smolgumball, @DrCuriosity, @phyzical)
* Fix aug display in alpha (@Dominik Winter)
* Fix display of corporation product equation (@SagePtr)
* Make Bitverse more accessible (@ChrissiQ)
* Make corporation warehouse more accessible (@ChrissiQ)
* Make tab style more consistent (@nickofolas)
** Netscript **
* Fix bug with async.
* Add 'printf' ns function (@Ninetailed)
* Remove blob caching.
* Fix formulas access check (@Ornedan)
* Fix bug in exp calculation (@qcorradi)
* Fix NaN comparison (@qcorradi)
* Fix travelToCity with bad argument (@SlyCedix)
* Fix bug where augs could not be purchased via sing (@reacocard)
* Fix rounding error in donateToFaction (@Risenafis)
* Fix bug with weakenAnalyze (@rhobes)
* Prevent exploit with atExit (@Ornedan)
* Double 'share' power
** Corporations **
* Fix bugs with corp API (@pigalot)
* Add smart supply func to corp API (@pd)
** Misc. **
* The file API now allows GET and DELETE (@lordducky)
* Force achievement calculation on BN completion (@SagePtr)
* Cleanup in repository (@MartinFourier)
* Several improvements to the electron version (@MartinFourier)
* Fix bug with casino roulette (@jamie-mac)
* Terminal history persists in savefile (@MartinFourier)
* Fix tests (@jamie-mac)
* Fix crash with electron windows tracker (@smolgumball)
* Fix BN6/7 passive reputation gain (@BrianLDev)
* Fix Sleeve not resetting on install (@waffleattack)
* Sort joined factions (@jjayeon)
* Update documentation / typo (@lethern, @Meowdoleon, @JohnnyUrosevic, @JosephDavidTalbot,
@pd, @lethern, @lordducky, @zeddrak, @fearnlj01, @reasonablytall, @MatthewTh0,
@SagePtr, @manniL, @Jedimaster4559, @loganville, @Arrow2thekn33, @wdpk, @fwolfst,
@fschoenfeldt, @Waladil, @AdamTReineke, @citrusmunch, @factubsio, @ashtongreen,
@ChrissiQ, @DJ-Laser, @waffleattack, @ApamNapat, @CrafterKolyan, @DSteve595)
* Nerf noodle bar.
v1.4.0 - 2022-01-18 Sharing is caring
-------------------------------------
** Computer sharing **
* A new mechanic has been added, it's is invoked by calling the new function 'share'.
This mechanic helps you farm reputation faster.
** gang **
* Installing augs means losing a little bit of ascension multipliers.
** Misc. **
* Prevent gang API from performing actions for the type of gang they are not. (@TheMas3212)
* Fix donation to gang faction. (@TheMas3212)
* Fix gang check crashing the game. (@TheMas3212)
* Make time compression more robust.
* Fix bug with scp.
* Add zoom to steam version. (@MartinFourier)
* Fix donateToFaction accepts donation of NaN. (@woody-lam-cwl)
* Show correct hash capacity gain on cache level upgrade tooltip. (@woody-lam-cwl)
* Fix tests (@woody-lam-cwl)
* Fix cache tooltip (@woody-lam-cwl)
* Added script to prettify save file for debugging (@MartinFourier)
* Update documentation / typos (@theit8514, @thadguidry, @tigercat2000, @SlyCedix, @Spacejoker, @KenJohansson,
@Ornedan, @JustAnOkapi, @nickofolas, @philarmstead, @TheMas3212, @dcragusa, @XxKingsxX-Pinu,
@paiv, @smolgumball, @zeddrak, @stinky-lizard, @nickofolas, @Feodoric, @daanflore,
@markusariliu, @mstruebing, @erplsf, @waffleattack, @Dexalt142, @AIT-OLPE, @deathly809, @BuckAMayzing,
@MartinFourier, @pigalot, @lethern)
* Fix BN3+ achievement (@SagePtr)
* Fix reputation carry over bug (@TheMas3212)
* Add button to exit infiltrations (@TheMas3212)
* Add dev menu achievement check (@TheMas3212)
* Add 'host' config for electron server (@MartinFourier)
* Suppress save toast only works for autosave (@MartinFourier)
* Fix some achievements not triggering with 'backdoor' (@SagePtr)
* Update Neuroflux Governor description.
* Fix bug with electron server.
* Fix bug with corporation employee assignment function (@Ornedan)
* Add detailed information to terminal 'mem' command (@MartinFourier)
* Add savestamp to savefile (@MartinFourier)
* Dev menu can apply export bonus (@MartinFourier)
* Icarus message no longer applies on top of itself (@Feodoric)
* purchase augment via API can no longer buy Neuroflux when it shouldn't (@Feodoric)
* Syntax highlighter should be smarter (@neuralsim)
* Fix some miscalculation when calculating money stolen (@zeddrak)
* Fix max cache achievement working with 0 cache (@MartinFourier)
* Add achievements in the game, not just steam (@MartinFourier)
* Overflow hash converts to money automatically (@MartinFourier)
* Make mathjax load locally (@MartinFourier)
* Make favor calculation more efficient (@kittycat2002)
* Fix some scripts crashing the game on startup (@MartinFourier)
* Toasts will appear above tail window (@MartinFourier)
* Fix issue that can cause terminal actions to start on one server and end on another (@MartinFourier)
* Fix 'fileExists' not correctly matching file names (@TheMas3212)
* Refactor some code to be more efficient (@TheMas3212)
* Fix exp gain for terminal grow and weaken (@nickofolas)
* Refactor script death code to reject waiting promises instead of resolving (@Ornedan)
* HP recalculates on defense exp gain (@TheMas3212)
* Fix log for ascendMember (@TheMas3212)
* Netscript ports clear on reset (@TheMas3212)
* Fix bug related to company (@TheMas3212)
* Fix bug where corporation handbook would not be correctly added (@TheMas3212)
* Servers in hash upgrades are sorted alpha (@MartinFourier)
* Fix very old save not properly migrating augmentation renamed in 0.56 (@MartinFourier)
* Add font height and line height in theme settings (@MartinFourier)
* Fix crash when quitting job (@MartinFourier)
* Added save file validation system (@TheMas3212)
* React and ReactDOM are now global objects (@pigalot)
* 'nano' supports globs (@smolgumball)
* Character overview can be dragged (@MartinFourier)
* Job page updates in real time (@nickofolas)
* Company favor gain uses the same calculation as faction, this is just performance
the value didn't change (@nickofolas)
* ns2 files work with more import options (@theit8514)
* Allow autocomplete for partial executables (@nickofolas)
* Add support for contract completion (@nickofolas)
* 'ls' link are clickable (@smolgumball)
* Prevent steam from opening external LOCAL files (@MartinFourier)
* Fix a bug with autocomplete (@Feodoric)
* Optimise achievement checks (@Feodoric)
* Hacknet server achievements grant associated hacknet node achievement (@Feodoric)
* Fix display bug with hacknet (@Feodoric)
* 'analyze' now says if the server is backdoored (@deathly809)
* Add option to exclude running script from save (@MartinFourier)
* Game now catches more errors and redirects to recovery page (@MartinFourier)
* Fix bug with autocomplete (@nickofolas)
* Add tooltip to unfocus work (@nickofolas)
* Add detailst overview (@MartinFourier)
* Fix focus bug (@deathly809)
* Fix some NaN handling (@deathly809)
* Added 'mv' ns function (@deathly809)
* Add focus argument to some singularity functions (@nickofolas)
* Fix some functions not disabling log correctly (@deathly809)
* General UI improvements (@nickofolas)
* Handle steamworks errors gravefully (@MartinFourier)
* Fix some react component not unmounting correctly (@MartinFourier)
* 'help' autocompletes (@nickofolas)
* No longer push all achievements to steam (@Ornedan)
* Recovery page has more information (@MartinFourier)
* Added 'getGameInfo' ns function (@MartinFourier)
* SF3.3 unlocks all corp API (@pigalot)
* Major improvements to corp API (@pigalot)
* Prevent seed money outside BN3 (@pigalot)
* Fix bug where using keyboard shortcuts would crash if the feature is not available (@MartinFourier)\
* Sidebar remains opened/closed on save (@MartinFourier)
* Added tooltip to sidebar when closed (@MartinFourier)
* Fix bug where Formulas.exe is not available when starting BN5 (@TheMas3212)
* Fix CI (@tvanderpol)
* Change shortcuts to match sidebar (@MartinFourier)
* Format gang respect (@attrib)
* Add modal to text editor with ram details (@nickofolas)
* Fix several bugs with singularity focus (@nickofolas)
* Nerf noodle bar.
v1.3.0 - 2022-01-04 Cleaning up
-------------------------------

@ -64,9 +64,9 @@ documentation_title = '{0} Documentation'.format(project)
# built documents.
#
# The short X.Y version.
version = '1.3'
version = '1.6'
# The full version, including alpha/beta/rc tags.
release = '1.3.0'
release = '1.6.3'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.

@ -117,7 +117,7 @@ Source-File
:Max Level: 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 will reduce RAM costs.
Difficulty:
Depending on what Source-Files you have unlocked before attempting this BitNode,

File diff suppressed because one or more lines are too long

@ -6,18 +6,18 @@ async function enableAchievementsInterval(window) {
// If the Steam API could not be initialized on game start, we'll abort this.
if (global.greenworksError) return;
// This is backward but the game fills in an array called `document.achievements` and we retrieve it from
// 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();
log.silly(`All Steam achievements ${JSON.stringify(steamAchievements)}`);
const playerAchieved = (await Promise.all(steamAchievements.map(checkSteamAchievement))).filter(name => !!name);
const playerAchieved = (await Promise.all(steamAchievements.map(checkSteamAchievement))).filter((name) => !!name);
log.debug(`Player has Steam achievements ${JSON.stringify(playerAchieved)}`);
const intervalID = setInterval(async () => {
try {
const playerAchievements = await window.webContents.executeJavaScript("document.achievements");
for (const ach of playerAchievements) {
if (!steamAchievements.includes(ach)) continue; // Don't try activating achievements that don't exist Steam-side
if (playerAchieved.includes(ach)) continue; // Don't spam achievements that have already been recorded
if (playerAchieved.includes(ach)) continue; // Don't spam achievements that have already been recorded
log.info(`Granting Steam achievement ${ach}`);
greenworks.activateAchievement(ach, () => undefined);
playerAchieved.push(ach);
@ -26,7 +26,7 @@ async function enableAchievementsInterval(window) {
log.error(error);
// The interval probably did not get cleared after a window kill
log.warn('Clearing achievements timer');
log.warn("Clearing achievements timer");
clearInterval(intervalID);
return;
}
@ -36,10 +36,14 @@ async function enableAchievementsInterval(window) {
function checkSteamAchievement(name) {
return new Promise((resolve) => {
greenworks.getAchievement(name, playerHas => resolve(playerHas ? name : ""), err => {
log.warn(`Failed to get Steam achievement ${name} status: ${err}`);
resolve("");
});
greenworks.getAchievement(
name,
(playerHas) => resolve(playerHas ? name : ""),
(err) => {
log.warn(`Failed to get Steam achievement ${name} status: ${err}`);
resolve("");
},
);
});
}
@ -50,5 +54,6 @@ function disableAchievementsInterval(window) {
}
module.exports = {
enableAchievementsInterval, disableAchievementsInterval
}
enableAchievementsInterval,
disableAchievementsInterval,
};

@ -12,25 +12,27 @@ async function initialize(win) {
window = win;
server = http.createServer(async function (req, res) {
let body = "";
res.setHeader('Content-Type', 'application/json');
res.setHeader("Content-Type", "application/json");
req.on("data", (chunk) => {
body += chunk.toString(); // convert Buffer to string
});
req.on("end", async () => {
const providedToken = req.headers?.authorization?.replace('Bearer ', '') ?? '';
const providedToken = req.headers?.authorization?.replace("Bearer ", "") ?? "";
const isValid = providedToken === getAuthenticationToken();
if (isValid) {
log.debug('Valid authentication token');
log.debug("Valid authentication token");
} else {
log.log('Invalid authentication token');
log.log("Invalid authentication token");
res.writeHead(401);
res.end(JSON.stringify({
success: false,
msg: 'Invalid authentication token'
}));
res.end(
JSON.stringify({
success: false,
msg: "Invalid authentication token",
}),
);
return;
}
@ -40,16 +42,18 @@ async function initialize(win) {
} catch (error) {
log.warn(`Invalid body data`);
res.writeHead(400);
res.end(JSON.stringify({
success: false,
msg: 'Invalid body data'
}));
res.end(
JSON.stringify({
success: false,
msg: "Invalid body data",
}),
);
return;
}
let result;
switch(req.method) {
switch (req.method) {
// Request files
case "GET":
result = await window.webContents.executeJavaScript(`document.getFiles()`);
@ -62,16 +66,18 @@ async function initialize(win) {
if (!data) {
log.warn(`Invalid script update request - No data`);
res.writeHead(400);
res.end(JSON.stringify({
success: false,
msg: 'Invalid script update request - No data'
}));
res.end(
JSON.stringify({
success: false,
msg: "Invalid script update request - No data",
}),
);
return;
}
result = await window.webContents.executeJavaScript(`document.saveFile("${data.filename}", "${data.code}")`);
break;
// Delete files
case "DELETE":
result = await window.webContents.executeJavaScript(`document.deleteFile("${data.filename}")`);
@ -84,19 +90,20 @@ async function initialize(win) {
log.warn(`Api Server Error`, result.msg);
}
res.end(JSON.stringify({
success: result.res,
msg: result.msg,
data: result.data
}));
res.end(
JSON.stringify({
success: result.res,
msg: result.msg,
data: result.data,
}),
);
});
});
const autostart = config.get('autostart', false);
const autostart = config.get("autostart", false);
if (autostart) {
try {
await enable()
await enable();
} catch (error) {
return Promise.reject(error);
}
@ -105,15 +112,14 @@ async function initialize(win) {
return Promise.resolve();
}
function enable() {
if (isListening()) {
log.warn('API server already listening');
log.warn("API server already listening");
return Promise.resolve();
}
const port = config.get('port', 9990);
const host = config.get('host', '127.0.0.1');
const port = config.get("port", 9990);
const host = config.get("host", "127.0.0.1");
log.log(`Starting http server on port ${port} - listening on ${host}`);
// https://stackoverflow.com/a/62289870
@ -125,13 +131,10 @@ function enable() {
resolve();
}
});
server.once('error', (err) => {
server.once("error", (err) => {
if (!startFinished) {
startFinished = true;
console.log(
'There was an error starting the server in the error listener:',
err
);
console.log("There was an error starting the server in the error listener:", err);
reject(err);
}
});
@ -140,11 +143,11 @@ function enable() {
function disable() {
if (!isListening()) {
log.warn('API server not listening');
log.warn("API server not listening");
return Promise.resolve();
}
log.log('Stopping http server');
log.log("Stopping http server");
return server.close();
}
@ -162,31 +165,35 @@ function isListening() {
function toggleAutostart() {
const newValue = !isAutostart();
config.set('autostart', newValue);
config.set("autostart", newValue);
log.log(`New autostart value is '${newValue}'`);
}
function isAutostart() {
return config.get('autostart');
return config.get("autostart");
}
function getAuthenticationToken() {
const token = config.get('token');
const token = config.get("token");
if (token) return token;
const newToken = generateToken();
config.set('token', newToken);
config.set("token", newToken);
return newToken;
}
function generateToken() {
const buffer = crypto.randomBytes(48);
return buffer.toString('base64')
return buffer.toString("base64");
}
module.exports = {
initialize,
enable, disable, toggleServer,
toggleAutostart, isAutostart,
getAuthenticationToken, isListening,
}
enable,
disable,
toggleServer,
toggleAutostart,
isAutostart,
getAuthenticationToken,
isListening,
};

@ -1,9 +1,8 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta charset="utf-8" />
<title>Bitburner</title>
<link rel="stylesheet" href="main.css" />
<style>
body {
background-color: black;

@ -1,9 +1,8 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta charset="utf-8" />
<title>Bitburner</title>
<link rel="stylesheet" href="main.css" />
<style>
body {
background-color: black;

@ -15,19 +15,20 @@ const debug = process.argv.includes("--debug");
async function createWindow(killall) {
const setStopProcessHandler = global.app_handlers.stopProcess;
app.setAppUserModelId("Bitburner");
let icon;
if (process.platform == 'linux') {
icon = path.join(__dirname, 'icon.png');
if (process.platform == "linux") {
icon = path.join(__dirname, "icon.png");
}
const tracker = windowTracker('main');
const tracker = windowTracker("main");
const window = new BrowserWindow({
icon,
show: false,
backgroundThrottling: false,
backgroundColor: "#000000",
title: 'Bitburner',
title: "Bitburner",
x: tracker.state.x,
y: tracker.state.y,
width: tracker.state.width,
@ -36,7 +37,7 @@ async function createWindow(killall) {
minHeight: 400,
webPreferences: {
nativeWindowOpen: true,
preload: path.join(__dirname, 'preload.js'),
preload: path.join(__dirname, "preload.js"),
},
});
@ -51,12 +52,12 @@ async function createWindow(killall) {
window.webContents.on("new-window", async function (e, url) {
// Let's make sure sure we have a proper url
let parsedUrl
let parsedUrl;
try {
parsedUrl = new URL(url);
} catch (_) {
// This is an invalid url, let's just do nothing
log.warn(`Invalid url found: ${url}`)
log.warn(`Invalid url found: ${url}`);
e.preventDefault();
return;
}
@ -73,11 +74,13 @@ async function createWindow(killall) {
if (!isChild) {
// If we're not relative to our app's path let's abort
log.warn(`Requested path ${filePath.dir}${path.sep}${filePath.base} is not relative to the app: ${appPath.dir}${path.sep}${appPath.base}`)
log.warn(
`Requested path ${filePath.dir}${path.sep}${filePath.base} is not relative to the app: ${appPath.dir}${path.sep}${appPath.base}`,
);
e.preventDefault();
} else if (!fileExists) {
// If the file does not exist let's abort
log.warn(`Requested path ${filePath.dir}${path.sep}${filePath.base} does not exist`)
log.warn(`Requested path ${filePath.dir}${path.sep}${filePath.base} does not exist`);
e.preventDefault();
}
@ -89,7 +92,7 @@ async function createWindow(killall) {
let urlToOpen = parsedUrl.toString();
if (parsedUrl.search) {
log.log(`Cannot open a path with parameters: ${parsedUrl.search}`);
urlToOpen = urlToOpen.replace(parsedUrl.search, '');
urlToOpen = urlToOpen.replace(parsedUrl.search, "");
// It would be possible to launch an URL with parameter using this, but it would mess up the process again...
// const escapedUri = parsedUrl.href.replace('&', '^&');
// cp.spawn("cmd.exe", ["/c", "start", escapedUri], { detached: true, stdio: "ignore" });

@ -3,83 +3,91 @@
// found in the LICENSE file.
// The source code can be found in https://github.com/greenheartgames/greenworks
var fs = require('fs');
var fs = require("fs");
var greenworks;
if (process.platform == 'darwin') {
if (process.arch == 'x64')
greenworks = require('./lib/greenworks-osx64');
else if (process.arch == 'ia32')
greenworks = require('./lib/greenworks-osx32');
} else if (process.platform == 'win32') {
if (process.arch == 'x64')
greenworks = require('./lib/greenworks-win64');
else if (process.arch == 'ia32')
greenworks = require('./lib/greenworks-win32');
} else if (process.platform == 'linux') {
if (process.arch == 'x64')
greenworks = require('./lib/greenworks-linux64');
else if (process.arch == 'ia32')
greenworks = require('./lib/greenworks-linux32');
if (process.platform == "darwin") {
if (process.arch == "x64") greenworks = require("./lib/greenworks-osx64");
else if (process.arch == "ia32") greenworks = require("./lib/greenworks-osx32");
} else if (process.platform == "win32") {
if (process.arch == "x64") greenworks = require("./lib/greenworks-win64");
else if (process.arch == "ia32") greenworks = require("./lib/greenworks-win32");
} else if (process.platform == "linux") {
if (process.arch == "x64") greenworks = require("./lib/greenworks-linux64");
else if (process.arch == "ia32") greenworks = require("./lib/greenworks-linux32");
}
function error_process(err, error_callback) {
if (err && error_callback)
error_callback(err);
if (err && error_callback) error_callback(err);
}
greenworks.ugcGetItems = function(options, ugc_matching_type, ugc_query_type,
success_callback, error_callback) {
if (typeof options !== 'object') {
greenworks.ugcGetItems = function (options, ugc_matching_type, ugc_query_type, success_callback, error_callback) {
if (typeof options !== "object") {
error_callback = success_callback;
success_callback = ugc_query_type;
ugc_query_type = ugc_matching_type;
ugc_matching_type = options;
options = {
'app_id': greenworks.getAppId(),
'page_num': 1
}
app_id: greenworks.getAppId(),
page_num: 1,
};
}
greenworks._ugcGetItems(options, ugc_matching_type, ugc_query_type,
success_callback, error_callback);
}
greenworks._ugcGetItems(options, ugc_matching_type, ugc_query_type, success_callback, error_callback);
};
greenworks.ugcGetUserItems = function(options, ugc_matching_type,
ugc_list_sort_order, ugc_list, success_callback, error_callback) {
if (typeof options !== 'object') {
greenworks.ugcGetUserItems = function (
options,
ugc_matching_type,
ugc_list_sort_order,
ugc_list,
success_callback,
error_callback,
) {
if (typeof options !== "object") {
error_callback = success_callback;
success_callback = ugc_list;
ugc_list = ugc_list_sort_order;
ugc_list_sort_order = ugc_matching_type;
ugc_matching_type = options;
options = {
'app_id': greenworks.getAppId(),
'page_num': 1
}
app_id: greenworks.getAppId(),
page_num: 1,
};
}
greenworks._ugcGetUserItems(options, ugc_matching_type, ugc_list_sort_order,
ugc_list, success_callback, error_callback);
}
greenworks._ugcGetUserItems(
options,
ugc_matching_type,
ugc_list_sort_order,
ugc_list,
success_callback,
error_callback,
);
};
greenworks.ugcSynchronizeItems = function (options, sync_dir, success_callback,
error_callback) {
if (typeof options !== 'object') {
greenworks.ugcSynchronizeItems = function (options, sync_dir, success_callback, error_callback) {
if (typeof options !== "object") {
error_callback = success_callback;
success_callback = sync_dir;
sync_dir = options;
options = {
'app_id': greenworks.getAppId(),
'page_num': 1
}
app_id: greenworks.getAppId(),
page_num: 1,
};
}
greenworks._ugcSynchronizeItems(options, sync_dir, success_callback,
error_callback);
}
greenworks._ugcSynchronizeItems(options, sync_dir, success_callback, error_callback);
};
greenworks.publishWorkshopFile = function(options, file_path, image_path, title,
description, success_callback, error_callback) {
if (typeof options !== 'object') {
greenworks.publishWorkshopFile = function (
options,
file_path,
image_path,
title,
description,
success_callback,
error_callback,
) {
if (typeof options !== "object") {
error_callback = success_callback;
success_callback = description;
description = title;
@ -87,18 +95,24 @@ greenworks.publishWorkshopFile = function(options, file_path, image_path, title,
image_path = file_path;
file_path = options;
options = {
'app_id': greenworks.getAppId(),
'tags': []
}
app_id: greenworks.getAppId(),
tags: [],
};
}
greenworks._publishWorkshopFile(options, file_path, image_path, title,
description, success_callback, error_callback);
}
greenworks._publishWorkshopFile(options, file_path, image_path, title, description, success_callback, error_callback);
};
greenworks.updatePublishedWorkshopFile = function(options,
published_file_handle, file_path, image_path, title, description,
success_callback, error_callback) {
if (typeof options !== 'object') {
greenworks.updatePublishedWorkshopFile = function (
options,
published_file_handle,
file_path,
image_path,
title,
description,
success_callback,
error_callback,
) {
if (typeof options !== "object") {
error_callback = success_callback;
success_callback = description;
description = title;
@ -107,104 +121,166 @@ greenworks.updatePublishedWorkshopFile = function(options,
file_path = published_file_handle;
published_file_handle = options;
options = {
'tags': [] // No tags are set
}
tags: [], // No tags are set
};
}
greenworks._updatePublishedWorkshopFile(options, published_file_handle,
file_path, image_path, title, description, success_callback,
error_callback);
}
greenworks._updatePublishedWorkshopFile(
options,
published_file_handle,
file_path,
image_path,
title,
description,
success_callback,
error_callback,
);
};
// An utility function for publish related APIs.
// It processes remains steps after saving files to Steam Cloud.
function file_share_process(file_name, image_name, next_process_func,
error_callback, progress_callback) {
if (progress_callback)
progress_callback("Completed on saving files on Steam Cloud.");
greenworks.fileShare(file_name, function() {
greenworks.fileShare(image_name, function() {
next_process_func();
}, function(err) { error_process(err, error_callback); });
}, function(err) { error_process(err, error_callback); });
function file_share_process(file_name, image_name, next_process_func, error_callback, progress_callback) {
if (progress_callback) progress_callback("Completed on saving files on Steam Cloud.");
greenworks.fileShare(
file_name,
function () {
greenworks.fileShare(
image_name,
function () {
next_process_func();
},
function (err) {
error_process(err, error_callback);
},
);
},
function (err) {
error_process(err, error_callback);
},
);
}
// Publishing user generated content(ugc) to Steam contains following steps:
// 1. Save file and image to Steam Cloud.
// 2. Share the file and image.
// 3. publish the file to workshop.
greenworks.ugcPublish = function(file_name, title, description, image_name,
success_callback, error_callback, progress_callback) {
var publish_file_process = function() {
if (progress_callback)
progress_callback("Completed on sharing files.");
greenworks.publishWorkshopFile(file_name, image_name, title, description,
function(publish_file_id) { success_callback(publish_file_id); },
function(err) { error_process(err, error_callback); });
greenworks.ugcPublish = function (
file_name,
title,
description,
image_name,
success_callback,
error_callback,
progress_callback,
) {
var publish_file_process = function () {
if (progress_callback) progress_callback("Completed on sharing files.");
greenworks.publishWorkshopFile(
file_name,
image_name,
title,
description,
function (publish_file_id) {
success_callback(publish_file_id);
},
function (err) {
error_process(err, error_callback);
},
);
};
greenworks.saveFilesToCloud([file_name, image_name], function() {
file_share_process(file_name, image_name, publish_file_process,
error_callback, progress_callback);
}, function(err) { error_process(err, error_callback); });
}
greenworks.saveFilesToCloud(
[file_name, image_name],
function () {
file_share_process(file_name, image_name, publish_file_process, error_callback, progress_callback);
},
function (err) {
error_process(err, error_callback);
},
);
};
// Update publish ugc steps:
// 1. Save new file and image to Steam Cloud.
// 2. Share file and images.
// 3. Update published file.
greenworks.ugcPublishUpdate = function(published_file_id, file_name, title,
description, image_name, success_callback, error_callback,
progress_callback) {
var update_published_file_process = function() {
if (progress_callback)
progress_callback("Completed on sharing files.");
greenworks.updatePublishedWorkshopFile(published_file_id,
file_name, image_name, title, description,
function() { success_callback(); },
function(err) { error_process(err, error_callback); });
greenworks.ugcPublishUpdate = function (
published_file_id,
file_name,
title,
description,
image_name,
success_callback,
error_callback,
progress_callback,
) {
var update_published_file_process = function () {
if (progress_callback) progress_callback("Completed on sharing files.");
greenworks.updatePublishedWorkshopFile(
published_file_id,
file_name,
image_name,
title,
description,
function () {
success_callback();
},
function (err) {
error_process(err, error_callback);
},
);
};
greenworks.saveFilesToCloud([file_name, image_name], function() {
file_share_process(file_name, image_name, update_published_file_process,
error_callback, progress_callback);
}, function(err) { error_process(err, error_callback); });
}
greenworks.saveFilesToCloud(
[file_name, image_name],
function () {
file_share_process(file_name, image_name, update_published_file_process, error_callback, progress_callback);
},
function (err) {
error_process(err, error_callback);
},
);
};
// Greenworks Utils APIs implmentation.
greenworks.Utils.move = function(source_dir, target_dir, success_callback,
error_callback) {
fs.rename(source_dir, target_dir, function(err) {
greenworks.Utils.move = function (source_dir, target_dir, success_callback, error_callback) {
fs.rename(source_dir, target_dir, function (err) {
if (err) {
if (error_callback) error_callback(err);
return;
}
if (success_callback)
success_callback();
if (success_callback) success_callback();
});
}
};
greenworks.init = function() {
greenworks.init = function () {
if (this.initAPI()) return true;
if (!this.isSteamRunning())
throw new Error("Steam initialization failed. Steam is not running.");
if (!this.isSteamRunning()) throw new Error("Steam initialization failed. Steam is not running.");
var appId;
try {
appId = fs.readFileSync('steam_appid.txt', 'utf8');
appId = fs.readFileSync("steam_appid.txt", "utf8");
} catch (e) {
throw new Error("Steam initialization failed. Steam is running," +
"but steam_appid.txt is missing. Expected to find it in: " +
require('path').resolve('steam_appid.txt'));
throw new Error(
"Steam initialization failed. Steam is running," +
"but steam_appid.txt is missing. Expected to find it in: " +
require("path").resolve("steam_appid.txt"),
);
}
if (!/^\d+ *\r?\n?$/.test(appId)) {
throw new Error("Steam initialization failed. " +
"steam_appid.txt appears to be invalid; " +
"it should contain a numeric ID: " + appId);
throw new Error(
"Steam initialization failed. " +
"steam_appid.txt appears to be invalid; " +
"it should contain a numeric ID: " +
appId,
);
}
throw new Error("Steam initialization failed, but Steam is running, " +
"and steam_appid.txt is present and valid." +
"Maybe that's not really YOUR app ID? " + appId.trim());
}
throw new Error(
"Steam initialization failed, but Steam is running, " +
"and steam_appid.txt is present and valid." +
"Maybe that's not really YOUR app ID? " +
appId.trim(),
);
};
var EventEmitter = require('events').EventEmitter;
var EventEmitter = require("events").EventEmitter;
greenworks.__proto__ = EventEmitter.prototype;
EventEmitter.call(greenworks);
@ -212,6 +288,6 @@ greenworks._steam_events.on = function () {
greenworks.emit.apply(greenworks, arguments);
};
process.versions['greenworks'] = greenworks._version;
process.versions["greenworks"] = greenworks._version;
module.exports = greenworks;

@ -18,7 +18,7 @@ log.transports.console.level = config.get("console-log-level", "debug");
log.catchErrors();
log.info(`Started app: ${JSON.stringify(process.argv)}`);
process.on('uncaughtException', function () {
process.on("uncaughtException", function () {
// The exception will already have been logged by electron-log
process.exit(1);
});
@ -67,42 +67,43 @@ function setStopProcessHandler(app, window, enabled) {
// 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']
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);
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")
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');
log.warn("Forcefully crashing the renderer process");
window.webContents.forcefullyCrashRenderer();
}
log.debug('Destroying the window');
log.debug("Destroying the window");
window.destroy();
}, 200);
}
};
const clearWindowHandler = () => {
window = null;
};
const stopProcessHandler = () => {
log.info('Quitting the app...');
log.info("Quitting the app...");
app.isQuiting = true;
app.quit();
process.exit(0);
@ -121,12 +122,12 @@ function setStopProcessHandler(app, window, enabled) {
const restoreNewest = config.get("onload-restore-newest", true);
if (restoreNewest && !isRestoreDisabled) {
try {
await storage.restoreIfNewerExists(window)
await storage.restoreIfNewerExists(window);
} catch (error) {
log.error("Could not restore newer file", error);
}
}
}
};
const receivedDisableRestoreHandler = async (event, arg) => {
if (!window) {
@ -140,7 +141,7 @@ function setStopProcessHandler(app, window, enabled) {
isRestoreDisabled = false;
log.debug("Re-enabling auto-restore");
}, arg.duration);
}
};
const receivedGameSavedHandler = async (event, arg) => {
if (!window) {
@ -149,7 +150,7 @@ function setStopProcessHandler(app, window, enabled) {
}
const { save, ...other } = arg;
log.silly("Received game saved info", {...other, save: `${save.length} bytes`});
log.silly("Received game saved info", { ...other, save: `${save.length} bytes` });
if (storage.isAutosaveEnabled()) {
saveToDisk(save, arg.fileName);
@ -159,43 +160,51 @@ function setStopProcessHandler(app, window, enabled) {
const playtime = window.gameInfo.player.playtime;
log.silly(window.gameInfo);
if (playtime > minimumPlaytime) {
saveToCloud(save);
saveToCloud(save);
} else {
log.debug(`Auto-save to cloud disabled for save game under ${minimumPlaytime}ms (${playtime}ms)`);
}
}
}
};
const saveToCloud = debounce(async (save) => {
log.debug("Saving to Steam Cloud ...")
try {
const playerId = window.gameInfo.player.identifier;
await storage.pushGameSaveToSteamCloud(save, playerId);
log.silly("Saved Game to Steam Cloud");
} catch (error) {
log.error(error);
utils.writeToast(window, "Could not save to Steam Cloud.", "error", 5000);
}
}, config.get("cloud-save-min-time", 1000 * 60 * 15), { leading: true });
const saveToCloud = debounce(
async (save) => {
log.debug("Saving to Steam Cloud ...");
try {
const playerId = window.gameInfo.player.identifier;
await storage.pushGameSaveToSteamCloud(save, playerId);
log.silly("Saved Game to Steam Cloud");
} catch (error) {
log.error(error);
utils.writeToast(window, "Could not save to Steam Cloud.", "error", 5000);
}
},
config.get("cloud-save-min-time", 1000 * 60 * 15),
{ leading: true },
);
const saveToDisk = debounce(async (save, fileName) => {
log.debug("Saving to Disk ...")
try {
const file = await storage.saveGameToDisk(window, { save, fileName });
log.silly(`Saved Game to '${file.replaceAll('\\', '\\\\')}'`);
} catch (error) {
log.error(error);
utils.writeToast(window, "Could not save to disk", "error", 5000);
}
}, config.get("disk-save-min-time", 1000 * 60 * 5), { leading: true });
const saveToDisk = debounce(
async (save, fileName) => {
log.debug("Saving to Disk ...");
try {
const file = await storage.saveGameToDisk(window, { save, fileName });
log.silly(`Saved Game to '${file.replaceAll("\\", "\\\\")}'`);
} catch (error) {
log.error(error);
utils.writeToast(window, "Could not save to disk", "error", 5000);
}
},
config.get("disk-save-min-time", 1000 * 60 * 5),
{ leading: true },
);
if (enabled) {
log.debug("Adding closing handlers");
ipcMain.on("push-game-ready", receivedGameReadyHandler);
ipcMain.on("push-game-saved", receivedGameSavedHandler);
ipcMain.on("push-disable-restore", receivedDisableRestoreHandler)
ipcMain.on("push-disable-restore", receivedDisableRestoreHandler);
window.on("closed", clearWindowHandler);
window.on("close", closingWindowHandler)
window.on("close", closingWindowHandler);
app.on("window-all-closed", stopProcessHandler);
} else {
log.debug("Removing closing handlers");
@ -213,7 +222,7 @@ async function startWindow(noScript) {
global.app_handlers = {
stopProcess: setStopProcessHandler,
createWindow: startWindow,
}
};
app.whenReady().then(async () => {
log.info("Application is ready!");
@ -231,7 +240,8 @@ app.whenReady().then(async () => {
title: "Bitburner",
message: "Could not connect to Steam",
detail: `${global.greenworksError}\n\nYou won't be able to receive achievements until this is resolved and you restart the game.`,
type: 'warning', buttons: ['OK']
type: "warning",
buttons: ["OK"],
});
}
}

@ -37,7 +37,7 @@ function getMenu(window) {
log.error(error);
utils.writeToast(window, "Could not load last save from disk", "error", 5000);
}
}
},
},
{
label: "Load From File",
@ -51,9 +51,7 @@ function getMenu(window) {
{ name: "Game Saves", extensions: ["json", "json.gz", "txt"] },
{ name: "All", extensions: ["*"] },
],
properties: [
"openFile", "dontAddToRecent",
]
properties: ["openFile", "dontAddToRecent"],
});
if (result.canceled) return;
const file = result.filePaths[0];
@ -65,7 +63,7 @@ function getMenu(window) {
log.error(error);
utils.writeToast(window, "Could not load save from disk", "error", 5000);
}
}
},
},
{
label: "Load From Steam Cloud",
@ -78,7 +76,7 @@ function getMenu(window) {
log.error(error);
utils.writeToast(window, "Could not load from Steam Cloud", "error", 5000);
}
}
},
},
{
type: "separator",
@ -89,8 +87,7 @@ function getMenu(window) {
checked: storage.isSaveCompressionEnabled(),
click: (menuItem) => {
storage.setSaveCompressionConfig(menuItem.checked);
utils.writeToast(window,
`${menuItem.checked ? "Enabled" : "Disabled"} Save Compression`, "info", 5000);
utils.writeToast(window, `${menuItem.checked ? "Enabled" : "Disabled"} Save Compression`, "info", 5000);
refreshMenu(window);
},
},
@ -100,8 +97,7 @@ function getMenu(window) {
checked: storage.isAutosaveEnabled(),
click: (menuItem) => {
storage.setAutosaveConfig(menuItem.checked);
utils.writeToast(window,
`${menuItem.checked ? "Enabled" : "Disabled"} Auto-Save to Disk`, "info", 5000);
utils.writeToast(window, `${menuItem.checked ? "Enabled" : "Disabled"} Auto-Save to Disk`, "info", 5000);
refreshMenu(window);
},
},
@ -112,8 +108,12 @@ function getMenu(window) {
checked: storage.isCloudEnabled(),
click: (menuItem) => {
storage.setCloudEnabledConfig(menuItem.checked);
utils.writeToast(window,
`${menuItem.checked ? "Enabled" : "Disabled"} Auto-Save to Steam Cloud`, "info", 5000);
utils.writeToast(
window,
`${menuItem.checked ? "Enabled" : "Disabled"} Auto-Save to Steam Cloud`,
"info",
5000,
);
refreshMenu(window);
},
},
@ -123,8 +123,12 @@ function getMenu(window) {
checked: config.get("onload-restore-newest", true),
click: (menuItem) => {
config.set("onload-restore-newest", menuItem.checked);
utils.writeToast(window,
`${menuItem.checked ? "Enabled" : "Disabled"} Restore Newest on Load`, "info", 5000);
utils.writeToast(
window,
`${menuItem.checked ? "Enabled" : "Disabled"} Restore Newest on Load`,
"info",
5000,
);
refreshMenu(window);
},
},
@ -153,7 +157,7 @@ function getMenu(window) {
label: "Open Data Directory",
click: () => shell.openPath(app.getPath("userData")),
},
]
],
},
{
type: "separator",
@ -162,7 +166,7 @@ function getMenu(window) {
label: "Quit",
click: () => app.quit(),
},
]
],
},
{
label: "Edit",
@ -210,29 +214,29 @@ function getMenu(window) {
label: "API Server",
submenu: [
{
label: api.isListening() ? 'Disable Server' : 'Enable Server',
click: (async () => {
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);
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");
utils.writeToast(window, "Error Toggling Server", "error");
}
refreshMenu(window);
})
},
},
{
label: api.isAutostart() ? 'Disable Autostart' : 'Enable Autostart',
click: (async () => {
label: api.isAutostart() ? "Disable Autostart" : "Enable Autostart",
click: async () => {
api.toggleAutostart();
if (api.isAutostart()) {
utils.writeToast(window, "Enabled API Server Autostart", "success");
@ -240,42 +244,45 @@ function getMenu(window) {
utils.writeToast(window, "Disabled API Server Autostart", "success");
}
refreshMenu(window);
})
},
},
{
label: 'Copy Auth Token',
click: (async () => {
label: "Copy Auth Token",
click: async () => {
const token = api.getAuthenticationToken();
log.log('Wrote authentication token to clipboard');
log.log("Wrote authentication token to clipboard");
clipboard.writeText(token);
utils.writeToast(window, "Copied Authentication Token to Clipboard", "info");
})
},
},
{
type: 'separator',
type: "separator",
},
{
label: 'Information',
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)'],
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');
}
});
}
}
]
})
.then(({ response }) => {
if (response === 1) {
utils.openExternal("https://github.com/bitburner-official/bitburner-vscode");
}
});
},
},
],
},
{
label: "Zoom",
@ -291,7 +298,7 @@ function getMenu(window) {
utils.setZoomFactor(window, newZoom);
refreshMenu(window);
} else {
log.log('Max zoom out')
log.log("Max zoom out");
utils.writeToast(window, "Cannot zoom in anymore", "warning");
}
},
@ -307,11 +314,21 @@ function getMenu(window) {
utils.setZoomFactor(window, newZoom);
refreshMenu(window);
} else {
log.log('Max zoom in')
log.log("Max zoom in");
utils.writeToast(window, "Cannot zoom out anymore", "warning");
}
},
},
{
label: "Reset Zoom",
enabled: utils.getZoomFactor() !== 1,
accelerator: "CommandOrControl+num0",
click: () => {
utils.setZoomFactor(window, 1);
refreshMenu(window);
log.log("Reset zoom");
},
},
],
},
{
@ -330,8 +347,8 @@ function getMenu(window) {
} catch (error) {
log.error(error);
}
}
}
},
},
],
},
]);
@ -342,5 +359,6 @@ function refreshMenu(window) {
}
module.exports = {
getMenu, refreshMenu,
}
getMenu,
refreshMenu,
};

@ -1,38 +1,36 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const { ipcRenderer, contextBridge } = require('electron')
const { ipcRenderer, contextBridge } = require("electron");
const log = require("electron-log");
contextBridge.exposeInMainWorld(
"electronBridge", {
send: (channel, data) => {
log.log("Send on channel " + channel)
// whitelist channels
let validChannels = [
"get-save-data-response",
"get-save-info-response",
"push-game-saved",
"push-game-ready",
"push-import-result",
"push-disable-restore",
];
if (validChannels.includes(channel)) {
ipcRenderer.send(channel, data);
}
},
receive: (channel, func) => {
log.log("Receive on channel " + channel)
let validChannels = [
"get-save-data-request",
"get-save-info-request",
"push-save-request",
"trigger-save",
"trigger-game-export",
"trigger-scripts-export",
];
if (validChannels.includes(channel)) {
// Deliberately strip event as it includes `sender`
ipcRenderer.on(channel, (event, ...args) => func(...args));
}
contextBridge.exposeInMainWorld("electronBridge", {
send: (channel, data) => {
log.log("Send on channel " + channel);
// whitelist channels
let validChannels = [
"get-save-data-response",
"get-save-info-response",
"push-game-saved",
"push-game-ready",
"push-import-result",
"push-disable-restore",
];
if (validChannels.includes(channel)) {
ipcRenderer.send(channel, data);
}
}
);
},
receive: (channel, func) => {
log.log("Receive on channel " + channel);
let validChannels = [
"get-save-data-request",
"get-save-info-request",
"push-save-request",
"trigger-save",
"trigger-game-export",
"trigger-scripts-export",
];
if (validChannels.includes(channel)) {
// Deliberately strip event as it includes `sender`
ipcRenderer.on(channel, (event, ...args) => func(...args));
}
},
});

@ -16,9 +16,9 @@ const config = new Config();
// https://stackoverflow.com/a/69418940
const dirSize = async (directory) => {
const files = await fs.readdir(directory);
const stats = files.map(file => fs.stat(path.join(directory, file)));
const stats = files.map((file) => fs.stat(path.join(directory, file)));
return (await Promise.all(stats)).reduce((accumulator, { size }) => accumulator + size, 0);
}
};
const getDirFileStats = async (directory) => {
const files = await fs.readdir(directory);
@ -26,30 +26,31 @@ const getDirFileStats = async (directory) => {
const file = path.join(directory, f);
return fs.stat(file).then((stat) => ({ file, stat }));
});
const data = (await Promise.all(stats));
const data = await Promise.all(stats);
return data;
};
const getNewestFile = async (directory) => {
const data = await getDirFileStats(directory)
const data = await getDirFileStats(directory);
return data.sort((a, b) => b.stat.mtime.getTime() - a.stat.mtime.getTime())[0];
};
const getAllSaves = async (window) => {
const rootDirectory = await getSaveFolder(window, true);
const data = await fs.readdir(rootDirectory, { withFileTypes: true});
const savesPromises = data.filter((e) => e.isDirectory()).
map((dir) => path.join(rootDirectory, dir.name)).
map((dir) => getDirFileStats(dir));
const data = await fs.readdir(rootDirectory, { withFileTypes: true });
const savesPromises = data
.filter((e) => e.isDirectory())
.map((dir) => path.join(rootDirectory, dir.name))
.map((dir) => getDirFileStats(dir));
const saves = await Promise.all(savesPromises);
const flat = flatten(saves);
return flat;
}
};
async function prepareSaveFolders(window) {
const rootFolder = await getSaveFolder(window, true);
const currentFolder = await getSaveFolder(window);
const backupsFolder = path.join(rootFolder, "/_backups")
const backupsFolder = path.join(rootFolder, "/_backups");
await prepareFolders(rootFolder, currentFolder, backupsFolder);
}
@ -60,7 +61,7 @@ async function prepareFolders(...folders) {
// eslint-disable-next-line no-await-in-loop
await fs.stat(folder);
} catch (error) {
if (error.code === 'ENOENT') {
if (error.code === "ENOENT") {
log.warn(`'${folder}' not found, creating it...`);
// eslint-disable-next-line no-await-in-loop
await fs.mkdir(folder);
@ -125,14 +126,14 @@ function isCloudEnabled() {
function saveCloudFile(name, content) {
return new Promise((resolve, reject) => {
greenworks.saveTextToFile(name, content, resolve, reject);
})
});
}
function getFirstCloudFile() {
const nbFiles = greenworks.getFileCount();
if (nbFiles === 0) throw new Error('No files in cloud');
if (nbFiles === 0) throw new Error("No files in cloud");
const file = greenworks.getFileNameAndSize(0);
log.silly(`Found ${nbFiles} files.`)
log.silly(`Found ${nbFiles} files.`);
log.silly(`First File: ${file.name} (${file.size} bytes)`);
return file.name;
}
@ -153,7 +154,7 @@ function deleteCloudFile() {
async function getSteamCloudQuota() {
return new Promise((resolve, reject) => {
greenworks.getCloudQuota(resolve, reject)
greenworks.getCloudQuota(resolve, reject);
});
}
@ -166,9 +167,9 @@ async function backupSteamDataToDisk(currentPlayerId) {
if (previousPlayerId !== currentPlayerId) {
const backupSave = await getSteamCloudSaveString();
const backupFile = path.join(app.getPath("userData"), "/saves/_backups", `${previousPlayerId}.json.gz`);
const buffer = Buffer.from(backupSave, 'base64').toString('utf8');
const buffer = Buffer.from(backupSave, "base64").toString("utf8");
saveContent = await gzip(buffer);
await fs.writeFile(backupFile, saveContent, 'utf8');
await fs.writeFile(backupFile, saveContent, "utf8");
log.debug(`Saved backup game to '${backupFile}`);
}
}
@ -219,7 +220,9 @@ async function saveGameToDisk(window, saveData) {
const remainingSpaceBytes = maxFolderSizeBytes - saveFolderSizeBytes;
log.debug(`Folder Usage: ${saveFolderSizeBytes} bytes`);
log.debug(`Folder Capacity: ${maxFolderSizeBytes} bytes`);
log.debug(`Remaining: ${remainingSpaceBytes} bytes (${(saveFolderSizeBytes / maxFolderSizeBytes * 100).toFixed(2)}% used)`)
log.debug(
`Remaining: ${remainingSpaceBytes} bytes (${((saveFolderSizeBytes / maxFolderSizeBytes) * 100).toFixed(2)}% used)`,
);
const shouldCompress = isSaveCompressionEnabled();
const fileName = saveData.fileName;
const file = path.join(currentFolder, fileName + (shouldCompress ? ".gz" : ""));
@ -227,10 +230,10 @@ async function saveGameToDisk(window, saveData) {
let saveContent = saveData.save;
if (shouldCompress) {
// Let's decode the base64 string so GZIP is more efficient.
const buffer = Buffer.from(saveContent, 'base64').toString('utf8');
const buffer = Buffer.from(saveContent, "base64").toString("utf8");
saveContent = await gzip(buffer);
}
await fs.writeFile(file, saveContent, 'utf8');
await fs.writeFile(file, saveContent, "utf8");
log.debug(`Saved Game to '${file}'`);
log.debug(`Save Size: ${saveContent.length} bytes`);
} catch (error) {
@ -240,7 +243,8 @@ async function saveGameToDisk(window, saveData) {
const fileStats = await getDirFileStats(currentFolder);
const oldestFiles = fileStats
.sort((a, b) => a.stat.mtime.getTime() - b.stat.mtime.getTime())
.map(f => f.file).filter(f => f !== file);
.map((f) => f.file)
.filter((f) => f !== file);
while (saveFolderSizeBytes > maxFolderSizeBytes && oldestFiles.length > 0) {
const fileToRemove = oldestFiles.shift();
@ -255,7 +259,12 @@ async function saveGameToDisk(window, saveData) {
// eslint-disable-next-line no-await-in-loop
saveFolderSizeBytes = await getFolderSizeInBytes(currentFolder);
log.debug(`Save Folder: ${saveFolderSizeBytes} bytes`);
log.debug(`Remaining: ${maxFolderSizeBytes - saveFolderSizeBytes} bytes (${(saveFolderSizeBytes / maxFolderSizeBytes * 100).toFixed(2)}% used)`)
log.debug(
`Remaining: ${maxFolderSizeBytes - saveFolderSizeBytes} bytes (${(
(saveFolderSizeBytes / maxFolderSizeBytes) *
100
).toFixed(2)}% used)`,
);
}
return file;
@ -271,13 +280,13 @@ async function loadLastFromDisk(window) {
async function loadFileFromDisk(path) {
const buffer = await fs.readFile(path);
let content;
if (path.endsWith('.gz')) {
if (path.endsWith(".gz")) {
const uncompressedBuffer = await gunzip(buffer);
content = uncompressedBuffer.toString('base64');
content = uncompressedBuffer.toString("base64");
log.debug(`Uncompressed file content (new size: ${content.length} bytes)`);
} else {
content = buffer.toString('utf8');
log.debug(`Loaded file with ${content.length} bytes`)
content = buffer.toString("utf8");
log.debug(`Loaded file with ${content.length} bytes`);
}
return content;
}
@ -293,10 +302,10 @@ function getSaveInformation(window, save) {
function getCurrentSave(window) {
return new Promise((resolve) => {
ipcMain.once('get-save-data-response', (event, data) => {
ipcMain.once("get-save-data-response", (event, data) => {
resolve(data);
});
window.webContents.send('get-save-data-request');
window.webContents.send("get-save-data-request");
});
}
@ -322,13 +331,12 @@ async function restoreIfNewerExists(window) {
}
try {
const saves = (await getAllSaves()).
sort((a, b) => b.stat.mtime.getTime() - a.stat.mtime.getTime());
const saves = (await getAllSaves()).sort((a, b) => b.stat.mtime.getTime() - a.stat.mtime.getTime());
if (saves.length > 0) {
disk.save = await loadFileFromDisk(saves[0].file);
disk.data = await getSaveInformation(window, disk.save);
}
} catch(error) {
} catch (error) {
log.error("Could not retrieve disk file");
log.debug(error);
}
@ -337,23 +345,20 @@ async function restoreIfNewerExists(window) {
let bestMatch;
if (!steam.data && !disk.data) {
log.info("No data to import");
} else {
} else if (!steam.data) {
// We'll just compare using the lastSave field for now.
if (!steam.data) {
log.debug('Best potential save match: Disk');
bestMatch = disk;
} else if (!disk.data) {
log.debug('Best potential save match: Steam Cloud');
bestMatch = steam;
} else if ((steam.data.lastSave >= disk.data.lastSave)
|| (steam.data.playtime + lowPlaytime > disk.data.playtime)) {
// We want to prioritze steam data if the playtime is very close
log.debug('Best potential save match: Steam Cloud');
bestMatch = steam;
} else {
log.debug('Best potential save match: disk');
bestMatch = disk;
}
log.debug("Best potential save match: Disk");
bestMatch = disk;
} else if (!disk.data) {
log.debug("Best potential save match: Steam Cloud");
bestMatch = steam;
} else if (steam.data.lastSave >= disk.data.lastSave || steam.data.playtime + lowPlaytime > disk.data.playtime) {
// We want to prioritze steam data if the playtime is very close
log.debug("Best potential save match: Steam Cloud");
bestMatch = steam;
} else {
log.debug("Best potential save match: disk");
bestMatch = disk;
}
if (bestMatch) {
if (bestMatch.data.lastSave > currentData.lastSave + 5000) {
@ -362,7 +367,7 @@ async function restoreIfNewerExists(window) {
log.silly(bestMatch.data);
await pushSaveGameForImport(window, bestMatch.save, true);
return true;
} else if(bestMatch.data.playtime > currentData.playtime && currentData.playtime < lowPlaytime) {
} else if (bestMatch.data.playtime > currentData.playtime && currentData.playtime < lowPlaytime) {
log.info("Found older save, but with more playtime, and current less than 15 mins played");
log.silly(bestMatch.data);
await pushSaveGameForImport(window, bestMatch.save, true);
@ -375,12 +380,24 @@ async function restoreIfNewerExists(window) {
}
module.exports = {
getCurrentSave, getSaveInformation,
restoreIfNewerExists, pushSaveGameForImport,
pushGameSaveToSteamCloud, getSteamCloudSaveString, getSteamCloudQuota, deleteCloudFile,
saveGameToDisk, loadLastFromDisk, loadFileFromDisk,
getSaveFolder, prepareSaveFolders, getAllSaves,
isCloudEnabled, setCloudEnabledConfig,
isAutosaveEnabled, setAutosaveConfig,
isSaveCompressionEnabled, setSaveCompressionConfig,
};
getCurrentSave,
getSaveInformation,
restoreIfNewerExists,
pushSaveGameForImport,
pushGameSaveToSteamCloud,
getSteamCloudSaveString,
getSteamCloudQuota,
deleteCloudFile,
saveGameToDisk,
loadLastFromDisk,
loadFileFromDisk,
getSaveFolder,
prepareSaveFolders,
getAllSaves,
isCloudEnabled,
setCloudEnabledConfig,
isAutosaveEnabled,
setAutosaveConfig,
isSaveCompressionEnabled,
setSaveCompressionConfig,
};

@ -9,61 +9,61 @@ const Config = require("electron-config");
const config = new Config();
function reloadAndKill(window, killScripts) {
const setStopProcessHandler = global.app_handlers.stopProcess
const setStopProcessHandler = global.app_handlers.stopProcess;
const createWindowHandler = global.app_handlers.createWindow;
log.info('Reloading & Killing all scripts...');
log.info("Reloading & Killing all scripts...");
setStopProcessHandler(app, window, false);
achievements.disableAchievementsInterval(window);
api.disable();
window.webContents.forcefullyCrashRenderer();
window.on('closed', () => {
window.on("closed", () => {
// Wait for window to be closed before opening the new one to prevent race conditions
log.debug('Opening new window');
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);
}
});
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);
window.on("unresponsive", window.unresponsiveHandler);
}
function detachUnresponsiveAppHandler(window) {
window.off('unresponsive', window.unresponsiveHandler);
window.off("unresponsive", window.unresponsiveHandler);
}
function showErrorBox(title, error) {
dialog.showErrorBox(
title,
`${error.name}\n\n${error.message}`
);
dialog.showErrorBox(title, `${error.name}\n\n${error.message}`);
}
function exportSaveFromIndexedDb() {
@ -71,15 +71,15 @@ function exportSaveFromIndexedDb() {
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');
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 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';
a.download = "save.json";
document.body.appendChild(a);
a.click();
setTimeout(function () {
@ -87,24 +87,21 @@ function exportSaveFromIndexedDb() {
window.URL.revokeObjectURL(url);
resolve();
}, 0);
}
}
};
};
});
}
async function exportSave(window) {
await window.webContents
.executeJavaScript(`${exportSaveFromIndexedDb.toString()}; exportSaveFromIndexedDb();`, true);
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)
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)
await window.webContents.executeJavaScript(`window.appNotifier.toast("${message}", "${type}", ${duration});`, true);
}
function openExternal(url) {
@ -113,7 +110,7 @@ function openExternal(url) {
}
function getZoomFactor() {
const configZoom = config.get('zoom', 1);
const configZoom = config.get("zoom", 1);
return configZoom;
}
@ -121,14 +118,20 @@ function setZoomFactor(window, zoom = null) {
if (zoom === null) {
zoom = 1;
} else {
config.set('zoom', zoom);
config.set("zoom", zoom);
}
window.webContents.setZoomFactor(zoom);
}
module.exports = {
reloadAndKill, showErrorBox, exportSave,
attachUnresponsiveAppHandler, detachUnresponsiveAppHandler,
openExternal, writeTerminal, writeToast,
getZoomFactor, setZoomFactor,
}
reloadAndKill,
showErrorBox,
exportSave,
attachUnresponsiveAppHandler,
detachUnresponsiveAppHandler,
openExternal,
writeTerminal,
writeToast,
getZoomFactor,
setZoomFactor,
};

@ -29,6 +29,11 @@ const windowTracker = (windowName) => {
};
const saveState = debounce(() => {
if (!window || window.isDestroyed()) {
log.silly(`Saving window state failed because window is not available`);
return;
}
if (!windowState.isMaximized) {
windowState = window.getBounds();
}
@ -41,7 +46,7 @@ const windowTracker = (windowName) => {
const track = (win) => {
window = win;
['resize', 'move', 'close'].forEach((event) => {
["resize", "move", "close"].forEach((event) => {
win.on(event, saveState);
});
};

@ -73,5 +73,5 @@
<link rel="shortcut icon" href="favicon.ico"></head>
<body>
<div id="root"/>
<script type="text/javascript" src="dist/vendor.bundle.js"></script><script type="text/javascript" src="dist/main.bundle.js"></script></body>
<script type="text/javascript" src="dist/vendor.bundle.js"></script><script type="text/javascript" src="main.bundle.js"></script></body>
</html>

@ -4,12 +4,11 @@ module.exports = {
transform: {
"^.+\\.(js|jsx|ts|tsx)$": "babel-jest",
},
testPathIgnorePatterns: [
'.cypress', 'node_modules', 'dist',
],
testPathIgnorePatterns: [".cypress", "node_modules", "dist"],
testEnvironment: "jsdom",
moduleNameMapper: {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/test/__mocks__/fileMock.js",
"\\.(css|less)$": "<rootDir>/test/__mocks__/styleMock.js"
}
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$":
"<rootDir>/test/__mocks__/fileMock.js",
"\\.(css|less)$": "<rootDir>/test/__mocks__/styleMock.js",
},
};

1
letter_to_fandom.com Normal file

@ -0,0 +1 @@
I want the wiki here https://bitburner.fandom.com/wiki/Bitburner_Wiki taken down please.

@ -1,85 +1,88 @@
LIMITED USE SOFTWARE LICENSE AGREEMENT
“Commons Clause” License Condition v1.0
This Limited Use Software License Agreement (the "Agreement") is a legal agreement between you, the end-user, and Daniel Y Xie,
the creator of the software, hereafter referred to as the Creator.
The Software is provided to you by the Licensor under the License, as defined below, subject to the following condition.
By downloading or purchasing the software material, which includes source code (the "Source Code"), artwork data, music and software
tools (collectively, the "Software"), you are agreeing to be bound by the terms of this Agreement. If you do not agree to the terms
of this Agreement, promptly destroy the Software you may have downloaded or copied.
Without limiting other conditions in the License, the grant of rights under the License will not include, and the License does not grant to you, the right to Sell the Software.
SOFTWARE LICENSE
For purposes of the foregoing, “Sell” means practicing any or all of the rights granted to you under the License to provide to third parties, for a fee or other consideration (including without limitation fees for hosting or consulting/ support services related to the Software), a product or service whose value derives, entirely or substantially, from the functionality of the Software. Any license notice or attribution required by the License must also include this Commons Clause License Condition notice.
1. Grant of License. The Creator grants to you the right to use the Software. You have no ownership or proprietary rights in or to
the Software, or the Trademark. For purposes of this section, "use" means loading the Software into RAM, as well as installation
on a hard disk or other storage device. The Software, together with any archive copy thereof, shall be destroyed when no longer
used in accordance with this Agreement, or when the right to use the Software is terminated. You agree that the Software will not
be shipped, transferred or exported into any country in violation of the U.S. Export Administration Act (or any other law governing
such matters) and that you will not utilize, in any other manner, the Software in violation of any applicable law.
Software: Bitburner
2. Permitted Uses.
License: Apache 2.0 with Commons Clause
You may copy and distribute literal (i.e., verbatim) or modified copies of the Software's source code.
You must meet all of the following conditions with respect to any work that you distribute or publish that in whole or in part
contains or is derived from the Software or any part thereof:
Licensor: Daniel Y Xie
(a) The distributed Software may not be used in any way for commercial gain and must not violate any of the restrictions
set forth in Section 3.
(b) If you have modified the Software, you must cause the modified Software to carry prominent notices stating that
you have modified the Software's files. Modifications must not alter or remove any copyright notices in the Software.
(c) The distributed Software must include either a written copy of this License, or a prominent written indication that
the Software is covered by this License and written instructions for printing and/or displaying the copy of the License
on the distribution medium
(d) When modifications to the Software are released under this license, a non-exclusive royalty-free right is granted to
the initial developer of the Software to distribute your modification in future versions of the Software provided
such versions remain available under these terms in addition to any other license(s) of the initial developer.
(d) You may not impose any further restrictions on the recipient's exercise of the rights granted herein.
-------------------------------------------------------------------
For educational purposes only, you, the end-user, may use portions of the Source Code, such as particular
routines, to develop your own software, but may not duplicate the Source Code. The limited
right referenced in the preceding sentence is hereinafter referred to as "Educational Use." By so exercising the Educational
Use right you shall not obtain any ownership, copyright, proprietary or other interest in or to the Source Code, or any portion
of the Source Code. You may dispose of your own software in your sole discretion. When exercising the Educational Use right,
you may not use or exploit the Software, or any portion of the Software, which includes the Source Code, for commercial gain.
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
3. Prohibited Uses: Under no circumstances shall you, the end-user, be permitted, allowed or authorized to commercially
exploit the Software or any work that in whole or in part contains or is derived from the Software or any part thereof.
Neither you nor anyone at your direction shall do any of the following acts with regard to the Software,
or any portion thereof:
Definitions.
Rent;
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
Sell;
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
Lease;
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
Offer on a pay-per-play basis;
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
Distribute for money or any other consideration; or
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
In any other manner and through any medium whatsoever commercially exploit or use for any commercial purpose.
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
4. Copyright. The Software and all copyrights related thereto (including all characters and other images generated by the
Software or depicted in the Software) are owned by the Creator and is protected by United States copyright laws and international treaty
provisions. The Creator shall retain exclusive ownership and copyright in and to the Software and all portions of the Software and you
shall have no ownership or other proprietary interest in such materials. You must treat the Software like any other copyrighted
material. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License.
You may not otherwise reproduce, copy or disclose to others, in whole or in any part, the Software. You may not copy the
written materials accompanying the Software. You agree to use your best efforts to see that any user of the Software licensed
hereunder complies with this Agreement.
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
5. NO WARRANTIES. The Creator DISCLAIMS ALL WARRANTIES, BOTH EXPRESS IMPLIED, INCLUDING BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE WITH RESPECT TO THE SOFTWARE. THIS LIMITED WARRANTY GIVES YOU SPECIFIC
LEGAL RIGHTS. YOU MAY HAVE OTHER RIGHTS WHICH VARY FROM JURISDICTION TO JURISDICTION. the Creator DOES NOT WARRANT THAT THE OPERATION
OF THE SOFTWARE WILL BE UNINTERRUPTED, ERROR FREE OR MEET YOUR SPECIFIC REQUIREMENTS. THE WARRANTY SET FORTH ABOVE IS IN LIEU
OF ALL OTHER EXPRESS WARRANTIES WHETHER ORAL OR WRITTEN. THE AGENTS, EMPLOYEES, DISTRIBUTORS, AND DEALERS OF THE CREATOR ARE NOT AUTHORIZED
TO MAKE MODIFICATIONS TO THIS WARRANTY, OR ADDITIONAL WARRANTIES ON BEHALF OF THE CREATOR.
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
Exclusive Remedies. The Software is being offered to you free of any charge. You agree that you have no remedy against the creator,
its affiliates, contractors, suppliers, and agents for loss or damage caused by any defect or failure in the Software regardless
of the form of action, whether in contract, tort, includinegligence, strict liability or otherwise, with regard to the Software.
This Agreement shall be construed in accordance with and governed by the laws of the State of Texas. Copyright and other
proprietary matters will be governed by United States laws and international treaties. IN ANY CASE, THE CREATOR SHALL NOT BE LIABLE
FOR LOSS OF DATA, LOSS OF PROFITS, LOST SAVINGS, SPECIAL, INCIDENTAL, CONSEQUENTIAL, INDIRECT OR OTHER SIMILAR DAMAGES ARISING
FROM BREACH OF WARRANTY, BREACH OF CONTRACT, NEGLIGENCE, OR OTHER LEGAL THEORY EVEN IF THE CREATOR OR ITS AGENT HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. Some jurisdictions do not allow the exclusion or limitation of
incidental or consequential damages, so the above limitation or exclusion may not apply to you.
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
(a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2022 Daniel Y Xie
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

20
main.bundle.js Normal file

File diff suppressed because one or more lines are too long

1
main.bundle.js.map Normal file

File diff suppressed because one or more lines are too long

7461
main.css

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

@ -4,7 +4,7 @@
## AugmentationStats.agility\_exp\_mult property
Multipler to agility experience gain rate
Multiplier to agility experience gain rate
<b>Signature:</b>

@ -4,7 +4,7 @@
## AugmentationStats.agility\_mult property
Multipler to agility skill
Multiplier to agility skill
<b>Signature:</b>

@ -4,7 +4,7 @@
## AugmentationStats.bladeburner\_analysis\_mult property
Multipler to effectiveness in Bladeburner Field Analysis
Multiplier to effectiveness in Bladeburner Field Analysis
<b>Signature:</b>

@ -4,7 +4,7 @@
## AugmentationStats.bladeburner\_max\_stamina\_mult property
Multipler to Bladeburner max stamina
Multiplier to Bladeburner max stamina
<b>Signature:</b>

@ -4,7 +4,7 @@
## AugmentationStats.bladeburner\_stamina\_gain\_mult property
Multipler to Bladeburner stamina gain rate
Multiplier to Bladeburner stamina gain rate
<b>Signature:</b>

@ -4,7 +4,7 @@
## AugmentationStats.bladeburner\_success\_chance\_mult property
Multipler to success chance in Bladeburner contracts/operations
Multiplier to success chance in Bladeburner contracts/operations
<b>Signature:</b>

@ -4,7 +4,7 @@
## AugmentationStats.charisma\_exp\_mult property
Multipler to charisma experience gain rate
Multiplier to charisma experience gain rate
<b>Signature:</b>

@ -4,7 +4,7 @@
## AugmentationStats.charisma\_mult property
Multipler to charisma skill
Multiplier to charisma skill
<b>Signature:</b>

@ -4,7 +4,7 @@
## AugmentationStats.company\_rep\_mult property
Multipler to amount of reputation gained when working
Multiplier to amount of reputation gained when working
<b>Signature:</b>

@ -4,7 +4,7 @@
## AugmentationStats.crime\_money\_mult property
Multipler to amount of money gained from crimes
Multiplier to amount of money gained from crimes
<b>Signature:</b>

@ -4,7 +4,7 @@
## AugmentationStats.crime\_success\_mult property
Multipler to crime success rate
Multiplier to crime success rate
<b>Signature:</b>

@ -4,7 +4,7 @@
## AugmentationStats.defense\_exp\_mult property
Multipler to defense experience gain rate
Multiplier to defense experience gain rate
<b>Signature:</b>

@ -4,7 +4,7 @@
## AugmentationStats.defense\_mult property
Multipler to defense skill
Multiplier to defense skill
<b>Signature:</b>

@ -4,7 +4,7 @@
## AugmentationStats.dexterity\_exp\_mult property
Multipler to dexterity experience gain rate
Multiplier to dexterity experience gain rate
<b>Signature:</b>

@ -4,7 +4,7 @@
## AugmentationStats.dexterity\_mult property
Multipler to dexterity skill
Multiplier to dexterity skill
<b>Signature:</b>

@ -4,7 +4,7 @@
## AugmentationStats.faction\_rep\_mult property
Multipler to amount of reputation gained when working
Multiplier to amount of reputation gained when working
<b>Signature:</b>

@ -4,7 +4,7 @@
## AugmentationStats.hacking\_chance\_mult property
Multipler to chance of successfully performing a hack
Multiplier to chance of successfully performing a hack
<b>Signature:</b>

@ -4,7 +4,7 @@
## AugmentationStats.hacking\_exp\_mult property
Multipler to hacking experience gain rate
Multiplier to hacking experience gain rate
<b>Signature:</b>

@ -4,7 +4,7 @@
## AugmentationStats.hacking\_grow\_mult property
Multipler to amount of money injected into servers using grow
Multiplier to amount of money injected into servers using grow
<b>Signature:</b>

@ -4,7 +4,7 @@
## AugmentationStats.hacking\_money\_mult property
Multipler to amount of money the player gains from hacking
Multiplier to amount of money the player gains from hacking
<b>Signature:</b>

@ -4,7 +4,7 @@
## AugmentationStats.hacking\_mult property
Multipler to hacking skill
Multiplier to hacking skill
<b>Signature:</b>

@ -4,7 +4,7 @@
## AugmentationStats.hacking\_speed\_mult property
Multipler to hacking speed
Multiplier to hacking speed
<b>Signature:</b>

@ -4,7 +4,7 @@
## AugmentationStats.hacknet\_node\_core\_cost\_mult property
Multipler to cost of core for a Hacknet Node
Multiplier to cost of core for a Hacknet Node
<b>Signature:</b>

@ -4,7 +4,7 @@
## AugmentationStats.hacknet\_node\_level\_cost\_mult property
Multipler to cost of leveling up a Hacknet Node
Multiplier to cost of leveling up a Hacknet Node
<b>Signature:</b>

@ -4,7 +4,7 @@
## AugmentationStats.hacknet\_node\_money\_mult property
Multipler to amount of money produced by Hacknet Nodes
Multiplier to amount of money produced by Hacknet Nodes
<b>Signature:</b>

@ -4,7 +4,7 @@
## AugmentationStats.hacknet\_node\_purchase\_cost\_mult property
Multipler to cost of purchasing a Hacknet Node
Multiplier to cost of purchasing a Hacknet Node
<b>Signature:</b>

@ -4,7 +4,7 @@
## AugmentationStats.hacknet\_node\_ram\_cost\_mult property
Multipler to cost of ram for a Hacknet Node
Multiplier to cost of ram for a Hacknet Node
<b>Signature:</b>

@ -16,34 +16,34 @@ export interface AugmentationStats
| Property | Type | Description |
| --- | --- | --- |
| [agility\_exp\_mult?](./bitburner.augmentationstats.agility_exp_mult.md) | number | <i>(Optional)</i> Multipler to agility experience gain rate |
| [agility\_mult?](./bitburner.augmentationstats.agility_mult.md) | number | <i>(Optional)</i> Multipler to agility skill |
| [bladeburner\_analysis\_mult?](./bitburner.augmentationstats.bladeburner_analysis_mult.md) | number | <i>(Optional)</i> Multipler to effectiveness in Bladeburner Field Analysis |
| [bladeburner\_max\_stamina\_mult?](./bitburner.augmentationstats.bladeburner_max_stamina_mult.md) | number | <i>(Optional)</i> Multipler to Bladeburner max stamina |
| [bladeburner\_stamina\_gain\_mult?](./bitburner.augmentationstats.bladeburner_stamina_gain_mult.md) | number | <i>(Optional)</i> Multipler to Bladeburner stamina gain rate |
| [bladeburner\_success\_chance\_mult?](./bitburner.augmentationstats.bladeburner_success_chance_mult.md) | number | <i>(Optional)</i> Multipler to success chance in Bladeburner contracts/operations |
| [charisma\_exp\_mult?](./bitburner.augmentationstats.charisma_exp_mult.md) | number | <i>(Optional)</i> Multipler to charisma experience gain rate |
| [charisma\_mult?](./bitburner.augmentationstats.charisma_mult.md) | number | <i>(Optional)</i> Multipler to charisma skill |
| [company\_rep\_mult?](./bitburner.augmentationstats.company_rep_mult.md) | number | <i>(Optional)</i> Multipler to amount of reputation gained when working |
| [crime\_money\_mult?](./bitburner.augmentationstats.crime_money_mult.md) | number | <i>(Optional)</i> Multipler to amount of money gained from crimes |
| [crime\_success\_mult?](./bitburner.augmentationstats.crime_success_mult.md) | number | <i>(Optional)</i> Multipler to crime success rate |
| [defense\_exp\_mult?](./bitburner.augmentationstats.defense_exp_mult.md) | number | <i>(Optional)</i> Multipler to defense experience gain rate |
| [defense\_mult?](./bitburner.augmentationstats.defense_mult.md) | number | <i>(Optional)</i> Multipler to defense skill |
| [dexterity\_exp\_mult?](./bitburner.augmentationstats.dexterity_exp_mult.md) | number | <i>(Optional)</i> Multipler to dexterity experience gain rate |
| [dexterity\_mult?](./bitburner.augmentationstats.dexterity_mult.md) | number | <i>(Optional)</i> Multipler to dexterity skill |
| [faction\_rep\_mult?](./bitburner.augmentationstats.faction_rep_mult.md) | number | <i>(Optional)</i> Multipler to amount of reputation gained when working |
| [hacking\_chance\_mult?](./bitburner.augmentationstats.hacking_chance_mult.md) | number | <i>(Optional)</i> Multipler to chance of successfully performing a hack |
| [hacking\_exp\_mult?](./bitburner.augmentationstats.hacking_exp_mult.md) | number | <i>(Optional)</i> Multipler to hacking experience gain rate |
| [hacking\_grow\_mult?](./bitburner.augmentationstats.hacking_grow_mult.md) | number | <i>(Optional)</i> Multipler to amount of money injected into servers using grow |
| [hacking\_money\_mult?](./bitburner.augmentationstats.hacking_money_mult.md) | number | <i>(Optional)</i> Multipler to amount of money the player gains from hacking |
| [hacking\_mult?](./bitburner.augmentationstats.hacking_mult.md) | number | <i>(Optional)</i> Multipler to hacking skill |
| [hacking\_speed\_mult?](./bitburner.augmentationstats.hacking_speed_mult.md) | number | <i>(Optional)</i> Multipler to hacking speed |
| [hacknet\_node\_core\_cost\_mult?](./bitburner.augmentationstats.hacknet_node_core_cost_mult.md) | number | <i>(Optional)</i> Multipler to cost of core for a Hacknet Node |
| [hacknet\_node\_level\_cost\_mult?](./bitburner.augmentationstats.hacknet_node_level_cost_mult.md) | number | <i>(Optional)</i> Multipler to cost of leveling up a Hacknet Node |
| [hacknet\_node\_money\_mult?](./bitburner.augmentationstats.hacknet_node_money_mult.md) | number | <i>(Optional)</i> Multipler to amount of money produced by Hacknet Nodes |
| [hacknet\_node\_purchase\_cost\_mult?](./bitburner.augmentationstats.hacknet_node_purchase_cost_mult.md) | number | <i>(Optional)</i> Multipler to cost of purchasing a Hacknet Node |
| [hacknet\_node\_ram\_cost\_mult?](./bitburner.augmentationstats.hacknet_node_ram_cost_mult.md) | number | <i>(Optional)</i> Multipler to cost of ram for a Hacknet Node |
| [strength\_exp\_mult?](./bitburner.augmentationstats.strength_exp_mult.md) | number | <i>(Optional)</i> Multipler to strength experience gain rate |
| [strength\_mult?](./bitburner.augmentationstats.strength_mult.md) | number | <i>(Optional)</i> Multipler to strength skill |
| [work\_money\_mult?](./bitburner.augmentationstats.work_money_mult.md) | number | <i>(Optional)</i> Multipler to amount of money gained from working |
| [agility\_exp\_mult?](./bitburner.augmentationstats.agility_exp_mult.md) | number | <i>(Optional)</i> Multiplier to agility experience gain rate |
| [agility\_mult?](./bitburner.augmentationstats.agility_mult.md) | number | <i>(Optional)</i> Multiplier to agility skill |
| [bladeburner\_analysis\_mult?](./bitburner.augmentationstats.bladeburner_analysis_mult.md) | number | <i>(Optional)</i> Multiplier to effectiveness in Bladeburner Field Analysis |
| [bladeburner\_max\_stamina\_mult?](./bitburner.augmentationstats.bladeburner_max_stamina_mult.md) | number | <i>(Optional)</i> Multiplier to Bladeburner max stamina |
| [bladeburner\_stamina\_gain\_mult?](./bitburner.augmentationstats.bladeburner_stamina_gain_mult.md) | number | <i>(Optional)</i> Multiplier to Bladeburner stamina gain rate |
| [bladeburner\_success\_chance\_mult?](./bitburner.augmentationstats.bladeburner_success_chance_mult.md) | number | <i>(Optional)</i> Multiplier to success chance in Bladeburner contracts/operations |
| [charisma\_exp\_mult?](./bitburner.augmentationstats.charisma_exp_mult.md) | number | <i>(Optional)</i> Multiplier to charisma experience gain rate |
| [charisma\_mult?](./bitburner.augmentationstats.charisma_mult.md) | number | <i>(Optional)</i> Multiplier to charisma skill |
| [company\_rep\_mult?](./bitburner.augmentationstats.company_rep_mult.md) | number | <i>(Optional)</i> Multiplier to amount of reputation gained when working |
| [crime\_money\_mult?](./bitburner.augmentationstats.crime_money_mult.md) | number | <i>(Optional)</i> Multiplier to amount of money gained from crimes |
| [crime\_success\_mult?](./bitburner.augmentationstats.crime_success_mult.md) | number | <i>(Optional)</i> Multiplier to crime success rate |
| [defense\_exp\_mult?](./bitburner.augmentationstats.defense_exp_mult.md) | number | <i>(Optional)</i> Multiplier to defense experience gain rate |
| [defense\_mult?](./bitburner.augmentationstats.defense_mult.md) | number | <i>(Optional)</i> Multiplier to defense skill |
| [dexterity\_exp\_mult?](./bitburner.augmentationstats.dexterity_exp_mult.md) | number | <i>(Optional)</i> Multiplier to dexterity experience gain rate |
| [dexterity\_mult?](./bitburner.augmentationstats.dexterity_mult.md) | number | <i>(Optional)</i> Multiplier to dexterity skill |
| [faction\_rep\_mult?](./bitburner.augmentationstats.faction_rep_mult.md) | number | <i>(Optional)</i> Multiplier to amount of reputation gained when working |
| [hacking\_chance\_mult?](./bitburner.augmentationstats.hacking_chance_mult.md) | number | <i>(Optional)</i> Multiplier to chance of successfully performing a hack |
| [hacking\_exp\_mult?](./bitburner.augmentationstats.hacking_exp_mult.md) | number | <i>(Optional)</i> Multiplier to hacking experience gain rate |
| [hacking\_grow\_mult?](./bitburner.augmentationstats.hacking_grow_mult.md) | number | <i>(Optional)</i> Multiplier to amount of money injected into servers using grow |
| [hacking\_money\_mult?](./bitburner.augmentationstats.hacking_money_mult.md) | number | <i>(Optional)</i> Multiplier to amount of money the player gains from hacking |
| [hacking\_mult?](./bitburner.augmentationstats.hacking_mult.md) | number | <i>(Optional)</i> Multiplier to hacking skill |
| [hacking\_speed\_mult?](./bitburner.augmentationstats.hacking_speed_mult.md) | number | <i>(Optional)</i> Multiplier to hacking speed |
| [hacknet\_node\_core\_cost\_mult?](./bitburner.augmentationstats.hacknet_node_core_cost_mult.md) | number | <i>(Optional)</i> Multiplier to cost of core for a Hacknet Node |
| [hacknet\_node\_level\_cost\_mult?](./bitburner.augmentationstats.hacknet_node_level_cost_mult.md) | number | <i>(Optional)</i> Multiplier to cost of leveling up a Hacknet Node |
| [hacknet\_node\_money\_mult?](./bitburner.augmentationstats.hacknet_node_money_mult.md) | number | <i>(Optional)</i> Multiplier to amount of money produced by Hacknet Nodes |
| [hacknet\_node\_purchase\_cost\_mult?](./bitburner.augmentationstats.hacknet_node_purchase_cost_mult.md) | number | <i>(Optional)</i> Multiplier to cost of purchasing a Hacknet Node |
| [hacknet\_node\_ram\_cost\_mult?](./bitburner.augmentationstats.hacknet_node_ram_cost_mult.md) | number | <i>(Optional)</i> Multiplier to cost of ram for a Hacknet Node |
| [strength\_exp\_mult?](./bitburner.augmentationstats.strength_exp_mult.md) | number | <i>(Optional)</i> Multiplier to strength experience gain rate |
| [strength\_mult?](./bitburner.augmentationstats.strength_mult.md) | number | <i>(Optional)</i> Multiplier to strength skill |
| [work\_money\_mult?](./bitburner.augmentationstats.work_money_mult.md) | number | <i>(Optional)</i> Multiplier to amount of money gained from working |

@ -4,7 +4,7 @@
## AugmentationStats.strength\_exp\_mult property
Multipler to strength experience gain rate
Multiplier to strength experience gain rate
<b>Signature:</b>

@ -4,7 +4,7 @@
## AugmentationStats.strength\_mult property
Multipler to strength skill
Multiplier to strength skill
<b>Signature:</b>

@ -4,7 +4,7 @@
## AugmentationStats.work\_money\_mult property
Multipler to amount of money gained from working
Multiplier to amount of money gained from working
<b>Signature:</b>

@ -0,0 +1,22 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [AutocompleteData](./bitburner.autocompletedata.md) &gt; [flags](./bitburner.autocompletedata.flags.md)
## AutocompleteData.flags() method
<b>Signature:</b>
```typescript
flags(schema: [string, string | number | boolean | string[]][]): any;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| schema | \[string, string \| number \| boolean \| string\[\]\]\[\] | |
<b>Returns:</b>
any

@ -0,0 +1,28 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [AutocompleteData](./bitburner.autocompletedata.md)
## AutocompleteData interface
Used for autocompletion
<b>Signature:</b>
```typescript
interface AutocompleteData
```
## Properties
| Property | Type | Description |
| --- | --- | --- |
| [scripts](./bitburner.autocompletedata.scripts.md) | string\[\] | |
| [servers](./bitburner.autocompletedata.servers.md) | string\[\] | |
| [txts](./bitburner.autocompletedata.txts.md) | string\[\] | |
## Methods
| Method | Description |
| --- | --- |
| [flags(schema)](./bitburner.autocompletedata.flags.md) | |

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [AutocompleteData](./bitburner.autocompletedata.md) &gt; [scripts](./bitburner.autocompletedata.scripts.md)
## AutocompleteData.scripts property
<b>Signature:</b>
```typescript
scripts: string[];
```

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [AutocompleteData](./bitburner.autocompletedata.md) &gt; [servers](./bitburner.autocompletedata.servers.md)
## AutocompleteData.servers property
<b>Signature:</b>
```typescript
servers: string[];
```

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [AutocompleteData](./bitburner.autocompletedata.md) &gt; [txts](./bitburner.autocompletedata.txts.md)
## AutocompleteData.txts property
<b>Signature:</b>
```typescript
txts: string[];
```

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [BitNodeMultipliers](./bitburner.bitnodemultipliers.md) &gt; [CorporationSoftCap](./bitburner.bitnodemultipliers.corporationsoftcap.md)
## BitNodeMultipliers.CorporationSoftCap property
Influences the money gain from dividends of corporations created by the player.
<b>Signature:</b>
```typescript
CorporationSoftCap: number;
```

@ -26,6 +26,7 @@ export interface BitNodeMultipliers
| [CodingContractMoney](./bitburner.bitnodemultipliers.codingcontractmoney.md) | number | Influences the amount of money gained from completing Coding Contracts |
| [CompanyWorkExpGain](./bitburner.bitnodemultipliers.companyworkexpgain.md) | number | Influences the experience gained for each ability when the player completes working their job. |
| [CompanyWorkMoney](./bitburner.bitnodemultipliers.companyworkmoney.md) | number | Influences how much money the player earns when completing working their job. |
| [CorporationSoftCap](./bitburner.bitnodemultipliers.corporationsoftcap.md) | number | Influences the money gain from dividends of corporations created by the player. |
| [CorporationValuation](./bitburner.bitnodemultipliers.corporationvaluation.md) | number | Influences the valuation of corporations created by the player. |
| [CrimeExpGain](./bitburner.bitnodemultipliers.crimeexpgain.md) | number | Influences the base experience gained for each ability when the player commits a crime. |
| [CrimeMoney](./bitburner.bitnodemultipliers.crimemoney.md) | number | Influences the base money gained when the player commits a crime. |
@ -53,7 +54,7 @@ export interface BitNodeMultipliers
| [ScriptHackMoney](./bitburner.bitnodemultipliers.scripthackmoney.md) | number | Influences how much the money on a server can be reduced when a script performs a hack against it. |
| [ScriptHackMoneyGain](./bitburner.bitnodemultipliers.scripthackmoneygain.md) | number | Influences how much of the money stolen by a scripted hack will be added to the player's money. |
| [ServerGrowthRate](./bitburner.bitnodemultipliers.servergrowthrate.md) | number | Influences the growth percentage per cycle against a server. |
| [ServerMaxMoney](./bitburner.bitnodemultipliers.servermaxmoney.md) | number | Influences the maxmimum money that a server can grow to. |
| [ServerMaxMoney](./bitburner.bitnodemultipliers.servermaxmoney.md) | number | Influences the maximum money that a server can grow to. |
| [ServerStartingMoney](./bitburner.bitnodemultipliers.serverstartingmoney.md) | number | Influences the initial money that a server starts with. |
| [ServerStartingSecurity](./bitburner.bitnodemultipliers.serverstartingsecurity.md) | number | Influences the initial security level (hackDifficulty) of a server. |
| [ServerWeakenRate](./bitburner.bitnodemultipliers.serverweakenrate.md) | number | Influences the weaken amount per invocation against a server. |

@ -4,7 +4,7 @@
## BitNodeMultipliers.ServerMaxMoney property
Influences the maxmimum money that a server can grow to.
Influences the maximum money that a server can grow to.
<b>Signature:</b>

@ -4,7 +4,7 @@
## Bladeburner.getActionAutolevel() method
Get wether an action is set to autolevel.
Get whether an action is set to autolevel.
<b>Signature:</b>

@ -31,5 +31,5 @@ RAM cost: 4 GB
Returns the remaining count of the specified action.
Note that this is meant to be used for Contracts and Operations. This function will return Infinity for actions such as Training and Field Analysis. This function will return 1 for BlackOps not yet completed regardless of wether the player has the required rank to attempt the mission or not.
Note that this is meant to be used for Contracts and Operations. This function will return Infinity for actions such as Training and Field Analysis. This function will return 1 for BlackOps not yet completed regardless of whether the player has the required rank to attempt the mission or not.

@ -20,7 +20,7 @@ You have to be employed in the Bladeburner division and be in BitNode-7 or have
| Method | Description |
| --- | --- |
| [getActionAutolevel(type, name)](./bitburner.bladeburner.getactionautolevel.md) | Get wether an action is set to autolevel. |
| [getActionAutolevel(type, name)](./bitburner.bladeburner.getactionautolevel.md) | Get whether an action is set to autolevel. |
| [getActionCountRemaining(type, name)](./bitburner.bladeburner.getactioncountremaining.md) | Get action count remaining. |
| [getActionCurrentLevel(type, name)](./bitburner.bladeburner.getactioncurrentlevel.md) | Get the current level of an action. |
| [getActionEstimatedSuccessChance(type, name)](./bitburner.bladeburner.getactionestimatedsuccesschance.md) | Get estimate success chance of an action. |

@ -4,7 +4,7 @@
## CodingContract.attempt() method
Attemps a coding contract.
Attempts a coding contract.
<b>Signature:</b>

@ -16,7 +16,7 @@ export interface CodingContract
| Method | Description |
| --- | --- |
| [attempt(answer, filename, host, opts)](./bitburner.codingcontract.attempt.md) | Attemps a coding contract. |
| [attempt(answer, filename, host, opts)](./bitburner.codingcontract.attempt.md) | Attempts a coding contract. |
| [getContractType(filename, host)](./bitburner.codingcontract.getcontracttype.md) | Get the type of a coding contract. |
| [getData(filename, host)](./bitburner.codingcontract.getdata.md) | Get the input data. |
| [getDescription(filename, host)](./bitburner.codingcontract.getdescription.md) | Get the description. |

@ -0,0 +1,24 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [Corporation](./bitburner.corporation.md) &gt; [buyBackShares](./bitburner.corporation.buybackshares.md)
## Corporation.buyBackShares() method
Buyback Shares
<b>Signature:</b>
```typescript
buyBackShares(amount: number): void;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| amount | number | Amount of shares to buy back. |
<b>Returns:</b>
void

@ -0,0 +1,23 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [Corporation](./bitburner.corporation.md) &gt; [getBonusTime](./bitburner.corporation.getbonustime.md)
## Corporation.getBonusTime() method
Get bonus time.
“Bonus time” is accumulated when the game is offline or if the game is inactive in the browser.
“Bonus time” makes the game progress faster.
<b>Signature:</b>
```typescript
getBonusTime(): number;
```
<b>Returns:</b>
number
Bonus time for the Corporation mechanic in milliseconds.

@ -19,9 +19,11 @@ export interface Corporation extends WarehouseAPI, OfficeAPI
| --- | --- |
| [acceptInvestmentOffer()](./bitburner.corporation.acceptinvestmentoffer.md) | Accept investment based on you companies current valuation |
| [bribe(factionName, amountCash, amountShares)](./bitburner.corporation.bribe.md) | Bribe a faction |
| [buyBackShares(amount)](./bitburner.corporation.buybackshares.md) | Buyback Shares |
| [createCorporation(corporationName, selfFund)](./bitburner.corporation.createcorporation.md) | Create a Corporation |
| [expandCity(divisionName, cityName)](./bitburner.corporation.expandcity.md) | Expand to a new city |
| [expandIndustry(industryType, divisionName)](./bitburner.corporation.expandindustry.md) | Expand to a new industry |
| [getBonusTime()](./bitburner.corporation.getbonustime.md) | Get bonus time.<!-- -->“Bonus time” is accumulated when the game is offline or if the game is inactive in the browser.<!-- -->“Bonus time” makes the game progress faster. |
| [getCorporation()](./bitburner.corporation.getcorporation.md) | Get corporation data |
| [getDivision(divisionName)](./bitburner.corporation.getdivision.md) | Get division data |
| [getExpandCityCost()](./bitburner.corporation.getexpandcitycost.md) | Gets the cost to expand into a new city |
@ -34,5 +36,6 @@ export interface Corporation extends WarehouseAPI, OfficeAPI
| [hasUnlockUpgrade(upgradeName)](./bitburner.corporation.hasunlockupgrade.md) | Check if you have a one time unlockable upgrade |
| [issueDividends(percent)](./bitburner.corporation.issuedividends.md) | Issue dividends |
| [levelUpgrade(upgradeName)](./bitburner.corporation.levelupgrade.md) | Level an upgrade. |
| [sellShares(amount)](./bitburner.corporation.sellshares.md) | Sell Shares |
| [unlockUpgrade(upgradeName)](./bitburner.corporation.unlockupgrade.md) | Unlock an upgrade |

@ -0,0 +1,24 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [Corporation](./bitburner.corporation.md) &gt; [sellShares](./bitburner.corporation.sellshares.md)
## Corporation.sellShares() method
Sell Shares
<b>Signature:</b>
```typescript
sellShares(amount: number): void;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| amount | number | Amount of shares to sell. |
<b>Returns:</b>
void

Some files were not shown because too many files have changed in this diff Show More