Merge branch 'dev' of github.com:danielyxie/bitburner into dev

This commit is contained in:
Olivier Gagnon 2022-01-04 18:03:56 -05:00
commit c06087c634
15 changed files with 262 additions and 47 deletions

@ -84,7 +84,9 @@ changes are okay to contribute:
- Changes that directly affect the game's balance
- New gameplay mechanics
### How to setup fork properly
---
## How to setup fork properly
Fork and clone the repo
@ -106,7 +108,15 @@ Fork and clone the repo
# Makes sure you always start from `danielyxie/dev` to avoid merge conflicts.
```
### Running locally.
## Development Workflow Best Practices
- Work in a new branch forked from the `dev` branch to isolate your new code
- Keep code-changes on a branch as small as possible. This makes it easier for code review. Each branch should be its own independent feature.
- Regularly rebase your branch against `dev` to make sure you have the latest updates pulled.
- When merging, always merge your branch into `dev`. When releasing a new update, then merge `dev` into `master`
## Running locally.
Install
@ -168,9 +178,14 @@ the following rules:
## As a Documentor
To contribute to and view your changes to the BitBurner documentation, you will
To contribute to and view your changes to the BitBurner documentation on [Read The
Docs](http://bitburner.readthedocs.io/), you will
need to have Python installed, along with [Sphinx](http://www.sphinx-doc.org).
To make change to the [in-game documentation](./markdown/bitburner.md), you will need to modify the [TypeScript definitions](./src/ScriptEditor/NetscriptDefinitions.d.ts), not the markdown files.
We are using [API Extractor](https://api-extractor.com/pages/tsdoc/doc_comment_syntax/) (tsdoc hints) to generate the markdown doc. Make your changes to the TypeScript definitions and then run `npm run doc`.
Before submitting your code for a pull request, please try to follow these
rules:
@ -182,3 +197,14 @@ rules:
_danielyxie/bitburner_ and the base is _dev_.
- Do not check in any generated files under `doc\`. The documentation is built
automatically by ReadTheDocs.
## Deploying a new version
Update the following
- `src/Constants.ts` `Version` and `LatestUpdate`
- `package.json` `version`
- `doc/source/conf.py` `version` and `release`
- `doc/source/changelog.rst`
- post to discord
- post to reddit.com/r/Bitburner

87
FAQ.md Normal file

@ -0,0 +1,87 @@
# Frequently Asked Questions
## Can I donate to the project?
No, the project does not take donation.
If you still want to donate, go donate blood to your local blood bank or donate to the [Electronic Frontier Foundation](https://www.eff.org/) or [Médecins Sans Frontières](https://www.msf.org/)
---
## I need help / Where can I learn?
The best way to get help is to join the [official discord server](https://discord.gg/TFc3hKD). People of all skill levels will be able to give you hints and tips.
---
## Can I play the same save on browser & steam?
Yes, just export the save file from the options menu & import it in the other platform.
---
## Game is stuck after running scripts!
You may have created an infinite loop with no sleep. You'll have to restart the game by killing all scripts.
* On Browser: Stick `?noScript` at the end of the URL
* On Steam:
* In the menu, "Reloads" -> "Reload & Kill All Scripts".
* If this does not work, when launching the game, use the kill all script options.
---
## Steam: Where is the save game located?
To maintain compatibility with the web browser version, the save game is not stored as a file on your filesystem. It lives inside the localStorage of the WebKit instance. You may export the save (and should backup it!) in the option menu.
---
## Steam: Game won't stop / Game is shown as "Running"
Due to a limitation with the way Steam tracks the game, if you launch an external link (such as documentation), Steam may keep tracking the game as "Running" even after it is closed. You should simply have to close your web browser to fix this.
---
## Steam: How do I get to the game files? <a name="game-files"></a>
You can navigate to the game files by right-clicking the game in your library and then go into "Manage" -> "Browse Local Files". The game can be launched directly from that location, if you're having issues with Steam.
---
## Steam: Game won't launch
### **On Windows**
If the game is installed on a network drive, it will fail to start due to a [limitation in Chromium](https://github.com/electron/electron/issues/27356).
If you cannot move the game to another drive, you'll have to add the `--no-sandbox` launch option. In your Steam Library, Right click the game and hit "Properties". You'll see the launch option section in the "General" window.
### **On Linux**
The game is built natively, do not use Proton unless native does not work.
When launching the game, you will be prompted with three options. If the standard launch does not work, you may attempt the `--disable-seccomp-filter-sandbox` or `--no-sandbox` launch option. If this still does not work, the game should be able to start by launching it directly or through the terminal. See [How do I get to the game files?](#game-files).
---
## Steam: File locations
### Logs (using [electron-log](https://github.com/megahertz/electron-log#readme))
You may want access the logs to get information about crashes or such.
* on Linux: `~/.config/bitburner/logs/main.log`
* on macOS: `~/Library/Logs/bitburner/main.log`
* on Windows: `%USERPROFILE%\AppData\Roaming\bitburner\logs\main.log`
### Config (using [electron-store](https://github.com/sindresorhus/electron-store#readme))
Configuration file will be written to disk in the application data directory.
* on Linux: `~/.config/bitburner/config.json`
* on macOS: `~/Library/Application\ Support/bitburner/config.json`
* on Windows: `%USERPROFILE%\AppData\Roaming\bitburner\config.json`
---
## Steam: What is the API Server?
The API Server allows the official [Visual Studio Code Extension](https://github.com/bitburner-official/bitburner-vscode) to push script file from VSCode to your in-game home.

@ -1,16 +1,19 @@
# Bitburner
[![Build Status](https://github.com/danielyxie/bitburner/actions/workflows/ci.yml/badge.svg?branch=dev)](https://github.com/danielyxie/bitburner/actions/workflows/ci.yml)
Bitburner is a programming-based [incremental game](https://en.wikipedia.org/wiki/Incremental_game)
that revolves around hacking and cyberpunk themes.
The game can be played at https://danielyxie.github.io/bitburner.
The game can be played at https://danielyxie.github.io/bitburner or installed through [Steam](https://store.steampowered.com/app/1812820/Bitburner/).
See the [frequently asked questions](./FAQ.md) for more information . To discuss the game or get help, join the [official discord server](https://discord.gg/TFc3hKD)
# Documentation
The game's official documentation can be found on [Read The
Docs](http://bitburner.readthedocs.io/). Please note that this is still a
work-in-progress.
Docs](http://bitburner.readthedocs.io/). Please note that this is still a work-in-progress.
The documentation is created using [Sphinx](http://www.sphinx-doc.org).
The [in-game documentation](./markdown/bitburner.md) is generated from the [TypeScript definitions](./src/ScriptEditor/NetscriptDefinitions.d.ts).
Anyone is welcome to contribute to the documentation by editing the [source
files](/doc/source) and then making a pull request with your contributions.

@ -1,21 +0,0 @@
## Deploying a new version
Update the following
- `src/Constants.ts` `Version` and `LatestUpdate`
- `package.json` `version`
- `doc/source/conf.py` `version` and `release`
- `doc/source/changelog.rst`
- post to discord
- post to reddit.com/r/Bitburner
## Deploying `dev` to the Beta Branch
TODO
## Development Workflow Best Practices
- Work in a new branch forked from the `dev` branch to isolate your new code
- Keep code-changes on a branch as small as possible. This makes it easier for code review. Each branch should be its own independent feature.
- Regularly rebase your branch against `dev` to make sure you have the latest updates pulled.
- When merging, always merge your branch into `dev`. When releasing a new update, then merge `dev` into `master`

@ -16,6 +16,10 @@ cp main.css .package/main.css
cp dist/vendor.bundle.js .package/dist/vendor.bundle.js
cp main.bundle.js .package/main.bundle.js
# Source maps
cp dist/vendor.bundle.js.map .package/dist/vendor.bundle.js.map
cp main.bundle.js.map .package/main.bundle.js.map
# Install electron sub-dependencies
cd electron
npm install

@ -25,8 +25,8 @@ export const ConsoleHelpText: {
"automate [var] [val] [hi/low]",
"",
"A simple way to automate your Bladeburner actions. This console command can be used " +
"to automatically start an action when your stamina rises above a certain threshold, and " +
"automatically switch to another action when your stamina drops below another threshold.",
"to automatically start an action when your stamina rises above a certain threshold, and " +
"automatically switch to another action when your stamina drops below another threshold.",
" automate status - Check the current status of your automation and get a brief description of what it'll do",
" automate en - Enable the automation feature",
" automate dis - Disable the automation feature",
@ -39,9 +39,9 @@ export const ConsoleHelpText: {
" automate general 'Field Analysis' low",
"",
"Using the four console commands above will set the automation to perform Tracking contracts " +
"if your stamina is 100 or higher, and then switch to Field Analysis if your stamina drops below " +
"50. Note that when setting the action, the name of the action is CASE-SENSITIVE. It must " +
"exactly match whatever the name is in the UI.",
"if your stamina is 100 or higher, and then switch to Field Analysis if your stamina drops below " +
"50. Note that when setting the action, the name of the action is CASE-SENSITIVE. It must " +
"exactly match whatever the name is in the UI.",
],
clear: ["clear", "", "Clears the console"],
cls: ["cls", "", "Clears the console"],
@ -49,8 +49,8 @@ export const ConsoleHelpText: {
"help [command]",
"",
"Running 'help' with no arguments displays the general help text, which lists all console commands " +
"and a brief description of what they do. A command can be specified to get more specific help text " +
"about that particular command. For example:",
"and a brief description of what they do. A command can be specified to get more specific help text " +
"about that particular command. For example:",
"",
" help automate",
"",
@ -60,8 +60,8 @@ export const ConsoleHelpText: {
"log [en/dis] [type]",
"",
"Enable or disable logging. By default, the results of completing actions such as contracts/operations are logged " +
"in the console. There are also random events that are logged in the console as well. The five categories of " +
"things that get logged are:",
"in the console. There are also random events that are logged in the console as well. The five categories of " +
"things that get logged are:",
"",
"[general, contracts, ops, blackops, events]",
"",
@ -86,10 +86,11 @@ export const ConsoleHelpText: {
" skill list",
"",
"To display information about a specific skill, specify the name of the skill afterwards. " +
"Note that the name of the skill is case-sensitive. Enter it exactly as seen in the UI. If " +
"the name of the skill has whitespace, enclose the name of the skill in double quotation marks:",
"Note that the name of the skill is case-sensitive. Enter it exactly as seen in the UI. If " +
"the name of the skill has whitespace, enclose the name of the skill in double quotation marks:",
"",
" skill list Reaper<br>" + " skill list 'Digital Observer'",
" skill list Reaper",
" skill list 'Digital Observer'",
"",
"This console command can also be used to level up skills:",
"",
@ -99,9 +100,9 @@ export const ConsoleHelpText: {
"start [type] [name]",
"",
"Start an action. An action is specified by its type and its name. The " +
"name is case-sensitive. It must appear exactly as it does in the UI. If " +
"the name of the action has whitespace, enclose it in double quotation marks. " +
"Valid action types include:",
"name is case-sensitive. It must appear exactly as it does in the UI. If " +
"the name of the action has whitespace, enclose it in double quotation marks. " +
"Valid action types include:",
"",
"[general, contract, op, blackop]",
"",

@ -138,6 +138,7 @@ export function Console(props: IProps): React.ReactElement {
paddingBottom: '8px',
display: 'flex',
alignItems: 'stretch',
whiteSpace: 'pre-wrap',
}}>
<Box>
<Logs entries={[...props.bladeburner.consoleLogs]} />

@ -22,7 +22,8 @@ export function makeRuntimeRejectMsg(workerScript: WorkerScript, msg: string): s
}
for (const scriptUrl of workerScript.scriptRef.dependencies) {
msg = msg.replace(new RegExp(scriptUrl.url, "g"), scriptUrl.filename);
// Return just the original msg if it's nullish so that we don't get a workerscript error
msg = msg?.replace(new RegExp(scriptUrl.url, "g"), scriptUrl.filename) ?? msg;
}
return "|DELIMITER|" + server.hostname + "|DELIMITER|" + workerScript.name + "|DELIMITER|" + msg;

@ -1639,7 +1639,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
const cost = getPurchaseServerCost(ram);
if (cost === Infinity) {
workerScript.log("purchaseServer", () => `Invalid argument: ram='${ram}' must be power of 2`);
workerScript.log("purchaseServer", () => `Invalid argument: ram='${ram}' must be a positive power of 2`);
return "";
}

@ -1,6 +1,8 @@
export type WordWrapOptions = 'on' | 'off' | 'bounded' | 'wordWrapColumn';
export interface Options {
theme: string;
insertSpaces: boolean;
fontSize: number;
wordWrap: WordWrapOptions;
vim: boolean;
}

@ -1,5 +1,5 @@
import React, { useState } from "react";
import { Options } from "./Options";
import { Options, WordWrapOptions } from "./Options";
import { Modal } from "../../ui/React/Modal";
import Button from "@mui/material/Button";
@ -21,6 +21,7 @@ export function OptionsModal(props: IProps): React.ReactElement {
const [theme, setTheme] = useState(props.options.theme);
const [insertSpaces, setInsertSpaces] = useState(props.options.insertSpaces);
const [fontSize, setFontSize] = useState(props.options.fontSize);
const [wordWrap, setWordWrap] = useState(props.options.wordWrap);
const [vim, setVim] = useState(props.options.vim);
function save(): void {
@ -28,6 +29,7 @@ export function OptionsModal(props: IProps): React.ReactElement {
theme,
insertSpaces,
fontSize,
wordWrap,
vim,
});
props.onClose();
@ -50,6 +52,7 @@ export function OptionsModal(props: IProps): React.ReactElement {
<MenuItem value="vs-dark">dark</MenuItem>
<MenuItem value="light">light</MenuItem>
<MenuItem value="dracula">dracula</MenuItem>
<MenuItem value="one-dark">one-dark</MenuItem>
</Select>
</Box>
@ -58,6 +61,16 @@ export function OptionsModal(props: IProps): React.ReactElement {
<Switch onChange={(event) => setInsertSpaces(event.target.checked)} checked={insertSpaces} />
</Box>
<Box display="flex" flexDirection="row" alignItems="center">
<Typography>Word Wrap: </Typography>
<Select onChange={(event) => setWordWrap(event.target.value as WordWrapOptions)} value={wordWrap}>
<MenuItem value={"off"}>Off</MenuItem>
<MenuItem value={"on"}>On</MenuItem>
<MenuItem value={"bounded"}>Bounded</MenuItem>
<MenuItem value={"wordWrapColumn"}>Word Wrap Column</MenuItem>
</Select>
</Box>
<Box display="flex" flexDirection="row" alignItems="center">
<Typography>Enable vim mode: </Typography>
<Switch onChange={(event) => setVim(event.target.checked)} checked={vim} />

@ -117,6 +117,7 @@ export function Root(props: IProps): React.ReactElement {
theme: Settings.MonacoTheme,
insertSpaces: Settings.MonacoInsertSpaces,
fontSize: Settings.MonacoFontSize,
wordWrap: Settings.MonacoWordWrap,
vim: props.vim || Settings.MonacoVim,
});
@ -794,6 +795,7 @@ export function Root(props: IProps): React.ReactElement {
theme: Settings.MonacoTheme,
insertSpaces: Settings.MonacoInsertSpaces,
fontSize: Settings.MonacoFontSize,
wordWrap: Settings.MonacoWordWrap,
vim: Settings.MonacoVim,
}}
save={(options: Options) => {
@ -801,6 +803,7 @@ export function Root(props: IProps): React.ReactElement {
Settings.MonacoTheme = options.theme;
Settings.MonacoInsertSpaces = options.insertSpaces;
Settings.MonacoFontSize = options.fontSize;
Settings.MonacoWordWrap = options.wordWrap;
Settings.MonacoVim = options.vim;
}}
/>

@ -218,6 +218,7 @@ export async function loadThemes(monaco: { editor: any }): Promise<void> {
"editor.selectionHighlightBorder": "#073642",
},
});
monaco.editor.defineTheme("dracula", {
base: "vs-dark",
inherit: true,
@ -313,4 +314,94 @@ export async function loadThemes(monaco: { editor: any }): Promise<void> {
"editor.snippetFinalTabstopHighlightBorder": "#50FA7B",
},
});
monaco.editor.defineTheme("one-dark", {
base: "vs-dark",
inherit: true,
rules: [
{
token: "",
background: "333842",
foreground: "ABB2BF",
},
{
token: "comment",
foreground: "5C6370",
},
{
token: "string",
foreground: "98C379",
},
{
token: "number",
foreground: "D19A66",
},
{
token: "function",
foreground: "C678DD",
},
{
token: "keyword",
foreground: "C678DD",
},
{
token: "otherkeyvars",
foreground: "D19A66",
},
{
token: "otherkeywords",
foreground: "C678DD",
},
{
token: "ns",
foreground: "E06C75",
},
{
token: "netscriptfunction",
foreground: "61AFEF",
},
{
token: "type.identifier",
foreground: "E5C07B",
},
{
token: "delimiter",
foreground: "ABB2BF",
},
{
token: "this",
foreground: "E06C75",
},
],
colors: {
"editor.background": "#282C34",
"editor.foreground": "#ABB2BF",
"editor.lineHighlightBackground": "#99BBFF0A",
"editor.selectionBackground": "#3E4451",
"editor.findMatchHighlightBackground": "#528BFF3D",
"editorCursor.foreground": "#528BFF",
"editorHoverWidget.background": "#21252B",
"editorHoverWidget.border": "#181A1F",
"editorIndentGuide.background": "#ABB2BF26",
"editorIndentGuide.activeBackground": "#626772",
"editorLineNumber.foreground": "#636D83",
"editorLineNumber.activeForeground": "#ABB2BF",
"editorSuggestWidget.background": "#21252B",
"editorSuggestWidget.border": "#181A1F",
"editorSuggestWidget.selectedBackground": "#2C313A",
"editorWhitespace.foreground": "#ABB2BF26",
"editorWidget.background": "#21252B",
"editorWidget.border": "#3A3F4B",
"input.background": "#1B1D23",
"input.border": "#181A1F",
"peekView.border": "#528BFF",
"peekViewResult.background": "#21252B",
"peekViewResult.selectionBackground": "#2C313A",
"peekViewTitle.background": "#1B1D23",
"peekViewEditor.background": "#1B1D23",
"scrollbarSlider.background": "#4E566680",
"scrollbarSlider.activeBackground": "#747D9180",
"scrollbarSlider.hoverBackground": "#5A637580",
}
});
}

@ -20,7 +20,7 @@ import { isPowerOfTwo } from "../utils/helpers/isPowerOfTwo";
*/
export function getPurchaseServerCost(ram: number): number {
const sanitizedRam = Math.round(ram);
if (isNaN(sanitizedRam) || !isPowerOfTwo(sanitizedRam)) {
if (isNaN(sanitizedRam) || !isPowerOfTwo(sanitizedRam) || !(Math.sign(sanitizedRam) === 1)) {
return Infinity;
}

@ -1,6 +1,7 @@
import { ISelfInitializer, ISelfLoading } from "../types";
import { OwnedAugmentationsOrderSetting, PurchaseAugmentationsOrderSetting } from "./SettingEnums";
import { defaultTheme, ITheme } from "./Themes";
import { WordWrapOptions } from '../ScriptEditor/ui/Options';
/**
* Represents the default settings the player could customize.
@ -141,6 +142,8 @@ interface ISettings extends IDefaultSettings {
MonacoFontSize: number;
MonacoVim: boolean;
MonacoWordWrap: WordWrapOptions;
}
export const defaultSettings: IDefaultSettings = {
@ -203,6 +206,7 @@ export const Settings: ISettings & ISelfInitializer & ISelfLoading = {
MonacoInsertSpaces: false,
MonacoFontSize: 20,
MonacoVim: false,
MonacoWordWrap: 'off',
theme: { ...defaultTheme },
init() {