Merge pull request #1690 from danielyxie/dev

Few bugfix
This commit is contained in:
hydroflame 2021-11-11 17:00:57 -05:00 committed by GitHub
commit f635f233cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 141 additions and 136 deletions

42
dist/vendor.bundle.js vendored

File diff suppressed because one or more lines are too long

@ -82,7 +82,7 @@ List of Factions and their Requirements
| | | server | |
| | | | |
+ +----------------+-----------------------------------------+-------------------------------+
| | Bitrunners | * Install a backdoor on the run4theh111z| |
| | BitRunners | * Install a backdoor on the run4theh111z| |
| | | server | |
| | | | |
+---------------------+----------------+-----------------------------------------+-------------------------------+

@ -61,7 +61,7 @@ v1.0.0 - 2021-11-10 Breaking the API :( (blame hydroflame)
* Button colors can be edited.
* Added 2 new colors in the theme editor: background primary and background secondary.
* infiltration uses key instead of keycode so it should work better on non-american keyboards.
* nerf noodle bar.
* buff noodle bar.
v0.58.0 - 2021-10-27 Road to Steam (hydroflame & community)
-----------------------------------------------------------

@ -10,7 +10,7 @@ getPlayer() Netscript Function
Returns an object with the Player's stats. The object has the following properties::
{
hacking_skill: Current Hacking skill level
hacking: Current Hacking skill level
hp: Current health points
max_hp: Maximum health points
strength: Current Strength skill level

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

22
package-lock.json generated

@ -1,11 +1,11 @@
{
"name": "bitburner",
"version": "0.58.0",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"version": "0.58.0",
"version": "1.0.0",
"hasInstallScript": true,
"license": "SEE LICENSE IN license.txt",
"dependencies": {
@ -28,6 +28,7 @@
"arg": "^5.0.0",
"better-react-mathjax": "^1.0.3",
"clsx": "^1.1.1",
"date-fns": "^2.25.0",
"decimal.js": "7.2.3",
"escodegen": "^1.11.0",
"file-saver": "^1.3.8",
@ -6963,6 +6964,18 @@
"whatwg-url": "^7.0.0"
}
},
"node_modules/date-fns": {
"version": "2.25.0",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.25.0.tgz",
"integrity": "sha512-ovYRFnTrbGPD4nqaEqescPEv1mNwvt+UTqI3Ay9SzNtey9NZnYu6E2qCcBBgJ6/2VF1zGGygpyTDITqpQQ5e+w==",
"engines": {
"node": ">=0.11"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/date-fns"
}
},
"node_modules/date-now": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz",
@ -26992,6 +27005,11 @@
"whatwg-url": "^7.0.0"
}
},
"date-fns": {
"version": "2.25.0",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.25.0.tgz",
"integrity": "sha512-ovYRFnTrbGPD4nqaEqescPEv1mNwvt+UTqI3Ay9SzNtey9NZnYu6E2qCcBBgJ6/2VF1zGGygpyTDITqpQQ5e+w=="
},
"date-now": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz",

@ -29,6 +29,7 @@
"arg": "^5.0.0",
"better-react-mathjax": "^1.0.3",
"clsx": "^1.1.1",
"date-fns": "^2.25.0",
"decimal.js": "7.2.3",
"escodegen": "^1.11.0",
"file-saver": "^1.3.8",

@ -67,7 +67,7 @@ BitNodes["BitNode2"] = new BitNode(
<br />
<br />
Organized crime groups quickly filled the void of power left behind from the collapse of Western government in the
2050s. As society and civlization broke down, people quickly succumbed to the innate human impulse of evil and
2050s. As society and civilization broke down, people quickly succumbed to the innate human impulse of evil and
savagery. The organized crime factions quickly rose to the top of the modern world.
<br />
<br />

@ -224,7 +224,6 @@ export class Action implements IAction {
let high = real + diff;
const city = inst.getCurrentCity();
const r = city.pop / city.popEst;
console.log(`${est} ${real}`);
if (r < 1) low *= r;
else high *= r;
return [clamp(low), clamp(high)];

@ -38,7 +38,7 @@ function EffectText(props: IEffectTextProps): React.ReactElement {
return (
<Typography>
Issue ${numeralWrapper.format(newShares, "0.000a")} new shares for{" "}
Issue {numeralWrapper.format(newShares, "0.000a")} new shares for{" "}
{numeralWrapper.formatMoney(newShares * newSharePrice)}?
</Typography>
);

@ -42,5 +42,6 @@ export function ExploitName(exploit: string): string {
}
export function sanitizeExploits(exploits: Exploit[]): Exploit[] {
return exploits.filter((e: Exploit) => Object.keys(Exploit).includes(e));
exploits = exploits.filter((e: Exploit) => Object.keys(Exploit).includes(e));
return [...new Set(exploits)];
}

@ -1,9 +1,11 @@
import { Player } from "../Player";
import { sanitizeExploits } from "./Exploit";
export function applyExploit(): void {
if (Player.exploits && Player.exploits.length === 0) {
return;
}
Player.exploits = sanitizeExploits(Player.exploits);
const inc = Math.pow(1.001, Player.exploits.length);
const dec = Math.pow(0.999, Player.exploits.length);

@ -20,8 +20,6 @@ import { createRandomIp } from "../utils/IPAddress";
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver";
interface IConstructorParams {
adminRights?: boolean;
hostname: string;
@ -37,7 +35,7 @@ export class HacknetServer extends BaseServer implements IHacknetNode {
// Number of cores. Improves hash production
cores = 1;
// Number of hashes that can be stored by this Hacknet Server
hashCapacity = 0;
@ -53,6 +51,9 @@ export class HacknetServer extends BaseServer implements IHacknetNode {
// Total number of hashes earned by this server
totalHashesGenerated = 0;
// Flag indicating wehther this is a purchased server
purchasedByPlayer = true;
constructor(params: IConstructorParams = { hostname: "", ip: createRandomIp() }) {
super(params);
@ -95,7 +96,7 @@ export class HacknetServer extends BaseServer implements IHacknetNode {
upgradeCore(levels: number, prodMult: number): void {
this.cores = Math.min(HacknetServerConstants.MaxCores, Math.round(this.cores + levels));
this.updateHashRate(prodMult);
this.cpuCores=this.cores;
this.cpuCores = this.cores;
}
upgradeLevel(levels: number, prodMult: number): void {

@ -119,7 +119,6 @@ export function Game(props: IProps): React.ReactElement {
}
function Progress(): React.ReactElement {
console.log(results);
return (
<Typography variant="h4">
<span style={{ color: "gray" }}>{results.slice(0, results.length - 1)}</span>

@ -35,8 +35,6 @@ export const Literatures: IMap<Literature> = {};
"<u>Getting Started with Corporations</u><br>" +
"To get started, visit the City Hall in Sector-12 in order to create a Corporation. This requires " +
"$150b of your own money, but this $150b will get put into your Corporation's funds. " +
"After creating your Corporation, you will see it listed as one of the locations in the city. Click on " +
"your Corporation in order to manage it.<br><br>" +
"Your Corporation can have many different divisions, each in a different Industry. There are many different " +
"types of Industries, each with different properties. To create your first division, click the " +
"'Expand into new Industry' button at the top of the management UI. The Agriculture " +

@ -855,10 +855,7 @@ export function startFactionHackWork(this: IPlayer, router: IRouter, faction: Fa
this.resetWorkStatus(CONSTANTS.WorkTypeFaction, faction.name, CONSTANTS.FactionWorkHacking);
this.workHackExpGainRate = 0.15 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.workRepGainRate =
((this.hacking + this.intelligence) / CONSTANTS.MaxSkillLevel) *
this.faction_rep_mult *
this.getIntelligenceBonus(0.5);
this.workRepGainRate = getFactionFieldWorkRepGain(this, faction);
this.factionWorkType = CONSTANTS.FactionWorkHacking;
this.currentWorkFactionDescription = "carrying out hacking contracts";
@ -1695,9 +1692,7 @@ export function regenerateHp(this: IPlayer, amt: number): void {
export function hospitalize(this: IPlayer): number {
const cost = getHospitalizationCost(this);
if (Settings.SuppressHospitalizationPopup === false) {
SnackbarEvents.emit(`You've been Hospitalized for ${numeralWrapper.formatMoney(cost)}`, "warning");
}
SnackbarEvents.emit(`You've been Hospitalized for ${numeralWrapper.formatMoney(cost)}`, "warning");
this.loseMoney(cost, "hospitalization");
this.hp = this.max_hp;
@ -2631,6 +2626,7 @@ export function canAccessResleeving(this: IPlayer): boolean {
export function giveExploit(this: IPlayer, exploit: Exploit): void {
if (!this.exploits.includes(exploit)) {
this.exploits.push(exploit);
SnackbarEvents.emit("SF -1 acquired!", "success");
}
}

@ -8,7 +8,7 @@ import { IMap } from "../types";
import { Terminal } from "../Terminal";
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver";
import { getTimestamp } from "../utils/helpers/getTimestamp";
import { formatTime } from "../utils/helpers/formatTime";
export class RunningScript {
// Script arguments
@ -74,8 +74,8 @@ export class RunningScript {
}
let logEntry = txt;
if (Settings.EnableTimestamps) {
logEntry = "[" + getTimestamp() + "] " + logEntry;
if (Settings.TimestampsFormat) {
logEntry = "[" + formatTime(Settings.TimestampsFormat) + "] " + logEntry;
}
this.logs.push(logEntry);

@ -42,11 +42,11 @@ export function OptionsModal(props: IProps): React.ReactElement {
<Box display="flex" flexDirection="row" alignItems="center">
<Typography>Theme: </Typography>
<Select onChange={(event) => setTheme(event.target.value)} value={theme}>
<MenuItem value="vs-dark">dark</MenuItem>
<MenuItem value="light">light</MenuItem>
<MenuItem value="monokai">monokai</MenuItem>
<MenuItem value="solarized-dark">solarized-dark</MenuItem>
<MenuItem value="solarized-light">solarized-light</MenuItem>
<MenuItem value="vs-dark">dark</MenuItem>
<MenuItem value="light">light</MenuItem>
</Select>
</Box>

@ -64,7 +64,7 @@ export async function loadThemes(monaco: { editor: any }): Promise<void> {
},
});
monaco.editor.defineTheme("solarish-dark", {
monaco.editor.defineTheme("solarized-dark", {
base: "vs-dark",
inherit: true,
rules: [
@ -113,16 +113,16 @@ export async function loadThemes(monaco: { editor: any }): Promise<void> {
foreground: "268bd2",
},
{
token: "type.identifier.js",
foreground: "b58900",
token: "type.identifier.js",
foreground: "b58900",
},
{
token: "delimiter.square.js",
foreground: "0087ff",
token: "delimiter.square.js",
foreground: "0087ff",
},
{
token: "delimiter.bracket.js",
foreground: "0087ff",
token: "delimiter.bracket.js",
foreground: "0087ff",
},
{
token: "this",
@ -141,13 +141,13 @@ export async function loadThemes(monaco: { editor: any }): Promise<void> {
},
});
monaco.editor.defineTheme("solarish-light", {
monaco.editor.defineTheme("solarized-light", {
base: "vs",
inherit: true,
rules: [
{
foreground: "657b83",
background: "fdf6e3",
background: "fdf6e3",
token: "",
},
{
@ -191,16 +191,16 @@ export async function loadThemes(monaco: { editor: any }): Promise<void> {
foreground: "268bd2",
},
{
token: "type.identifier.js",
foreground: "b58900",
token: "type.identifier.js",
foreground: "b58900",
},
{
token: "delimiter.square.js",
foreground: "0087ff",
token: "delimiter.square.js",
foreground: "0087ff",
},
{
token: "delimiter.bracket.js",
foreground: "0087ff",
token: "delimiter.bracket.js",
foreground: "0087ff",
},
{
token: "this",

@ -94,6 +94,9 @@ export class BaseServer {
// Text files on this server
textFiles: TextFile[] = [];
// Flag indicating wehther this is a purchased server
purchasedByPlayer = false;
constructor(params: IConstructorParams = { hostname: "", ip: createRandomIp() }) {
this.ip = params.ip ? params.ip : createRandomIp();

@ -48,9 +48,6 @@ export class Server extends BaseServer {
// How many ports are currently opened on the server
openPortCount = 0;
// Flag indicating wehther this is a purchased server
purchasedByPlayer = false;
// Hacking level required to hack this server
requiredHackingSkill = 1;

@ -44,9 +44,9 @@ interface IDefaultSettings {
EnableBashHotkeys: boolean;
/**
* Enable timestamps
* Timestamps format
*/
EnableTimestamps: boolean;
TimestampsFormat: string;
/**
* Locale used for display numbers
@ -83,11 +83,6 @@ interface IDefaultSettings {
*/
SuppressFactionInvites: boolean;
/**
* Whether to show a popup message when player is hospitalized from taking too much damage
*/
SuppressHospitalizationPopup: boolean;
/**
* Whether the user should be shown a dialog box whenever they receive a new message file.
*/
@ -171,7 +166,7 @@ export const defaultSettings: IDefaultSettings = {
DisableHotkeys: false,
DisableTextEffects: false,
EnableBashHotkeys: false,
EnableTimestamps: false,
TimestampsFormat: "",
Locale: "en",
MaxLogCapacity: 50,
MaxPortCapacity: 50,
@ -179,7 +174,6 @@ export const defaultSettings: IDefaultSettings = {
SaveGameOnFileSave: true,
SuppressBuyAugmentationConfirmation: false,
SuppressFactionInvites: false,
SuppressHospitalizationPopup: false,
SuppressMessages: false,
SuppressTravelConfirmation: false,
SuppressBladeburnerPopup: false,
@ -231,7 +225,7 @@ export const Settings: ISettings & ISelfInitializer & ISelfLoading = {
DisableHotkeys: defaultSettings.DisableHotkeys,
DisableTextEffects: defaultSettings.DisableTextEffects,
EnableBashHotkeys: defaultSettings.EnableBashHotkeys,
EnableTimestamps: defaultSettings.EnableTimestamps,
TimestampsFormat: defaultSettings.TimestampsFormat,
Locale: "en",
MaxLogCapacity: defaultSettings.MaxLogCapacity,
MaxPortCapacity: defaultSettings.MaxPortCapacity,
@ -241,7 +235,6 @@ export const Settings: ISettings & ISelfInitializer & ISelfLoading = {
SaveGameOnFileSave: defaultSettings.SaveGameOnFileSave,
SuppressBuyAugmentationConfirmation: defaultSettings.SuppressBuyAugmentationConfirmation,
SuppressFactionInvites: defaultSettings.SuppressFactionInvites,
SuppressHospitalizationPopup: defaultSettings.SuppressHospitalizationPopup,
SuppressMessages: defaultSettings.SuppressMessages,
SuppressTravelConfirmation: defaultSettings.SuppressTravelConfirmation,
SuppressBladeburnerPopup: defaultSettings.SuppressBladeburnerPopup,
@ -289,5 +282,6 @@ export const Settings: ISettings & ISelfInitializer & ISelfLoading = {
Object.assign(Settings.theme, save.theme);
delete save.theme;
Object.assign(Settings, save);
console.log(Settings.TimestampsFormat);
},
};

@ -4,7 +4,7 @@ import { Script } from "../Script/Script";
import { IPlayer } from "../PersonObjects/IPlayer";
import { IRouter } from "../ui/Router";
import { Settings } from "../Settings/Settings";
import { getTimestamp } from "../utils/helpers/getTimestamp";
import { formatTime } from "../utils/helpers/formatTime";
export class Output {
text: string;
@ -13,7 +13,7 @@ export class Output {
text: string,
color: "inherit" | "initial" | "primary" | "secondary" | "error" | "textPrimary" | "textSecondary" | undefined,
) {
if (Settings.EnableTimestamps) text = "[" + getTimestamp() + "] " + text;
if (Settings.TimestampsFormat) text = "[" + formatTime(Settings.TimestampsFormat) + "] " + text;
this.text = text;
this.color = color;
}
@ -22,10 +22,10 @@ export class Output {
export class RawOutput {
raw: React.ReactNode;
constructor(node: React.ReactNode) {
if (Settings.EnableTimestamps)
if (Settings.TimestampsFormat)
node = (
<>
[{getTimestamp()}] {node}
[{formatTime(Settings.TimestampsFormat)}] {node}
</>
);
this.raw = node;
@ -36,7 +36,7 @@ export class Link {
hostname: string;
dashes: string;
constructor(dashes: string, hostname: string) {
if (Settings.EnableTimestamps) dashes = "[" + getTimestamp() + "] " + dashes;
if (Settings.TimestampsFormat) dashes = "[" + formatTime(Settings.TimestampsFormat) + "] " + dashes;
this.hostname = hostname;
this.dashes = dashes;
}

@ -27,7 +27,11 @@ export function download(
const file = new Blob([server.scripts[i].code], {
type: "text/plain",
});
zip.file(server.scripts[i].filename + ".js", file);
let name = server.scripts[i].filename;
if (name.startsWith("/")) {
name = name.slice(1);
}
zip.file(name + ".js", file);
}
}
if (fn === "*" || fn === "*.txt") {

@ -253,7 +253,7 @@ const Engine: {
let offlineReputation = 0;
const offlineHackingIncome = (Player.moneySourceA.hacking / Player.playtimeSinceLastAug) * timeOffline * 0.75;
Player.gainMoney(offlineHackingIncome, "hacknet");
Player.gainMoney(offlineHackingIncome, "hacking");
// Process offline progress
loadAllRunningScripts(); // This also takes care of offline production for those scripts
if (Player.isWorking) {

@ -7,6 +7,5 @@ export function dialogBoxCreate(txt: string | JSX.Element): void {
AlertEvents.emit(txt);
} else {
AlertEvents.emit(<span dangerouslySetInnerHTML={{ __html: txt }} />);
console.log('emit"');
}
}

@ -19,6 +19,7 @@ import List from "@mui/material/List";
import ListItem from "@mui/material/ListItem";
import Link from "@mui/material/Link";
import Tooltip from "@mui/material/Tooltip";
import TextField from "@mui/material/TextField";
import DownloadIcon from "@mui/icons-material/Download";
import UploadIcon from "@mui/icons-material/Upload";
@ -30,6 +31,7 @@ import { ThemeEditorModal } from "./ThemeEditorModal";
import { Settings } from "../../Settings/Settings";
import { save, deleteGame } from "../../db";
import { formatTime } from "../../utils/helpers/formatTime";
const useStyles = makeStyles((theme: Theme) =>
createStyles({
@ -66,9 +68,6 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
const [suppressBuyAugmentationConfirmation, setSuppressBuyAugmentationConfirmation] = useState(
Settings.SuppressBuyAugmentationConfirmation,
);
const [suppressHospitalizationPopup, setSuppressHospitalizationPopup] = useState(
Settings.SuppressHospitalizationPopup,
);
const [suppressBladeburnerPopup, setSuppressBladeburnerPopup] = useState(Settings.SuppressBladeburnerPopup);
@ -76,7 +75,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
const [disableASCIIArt, setDisableASCIIArt] = useState(Settings.DisableASCIIArt);
const [disableTextEffects, setDisableTextEffects] = useState(Settings.DisableTextEffects);
const [enableBashHotkeys, setEnableBashHotkeys] = useState(Settings.EnableBashHotkeys);
const [enableTimestamps, setEnableTimestamps] = useState(Settings.EnableTimestamps);
const [timestampFormat, setTimestampFormat] = useState(Settings.TimestampsFormat);
const [saveGameOnFileSave, setSaveGameOnFileSave] = useState(Settings.SaveGameOnFileSave);
const [locale, setLocale] = useState(Settings.Locale);
@ -129,11 +128,6 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
Settings.SuppressBuyAugmentationConfirmation = event.target.checked;
}
function handleSuppressHospitalizationPopupChange(event: React.ChangeEvent<HTMLInputElement>): void {
setSuppressHospitalizationPopup(event.target.checked);
Settings.SuppressHospitalizationPopup = event.target.checked;
}
function handleSuppressBladeburnerPopupChange(event: React.ChangeEvent<HTMLInputElement>): void {
setSuppressBladeburnerPopup(event.target.checked);
Settings.SuppressBladeburnerPopup = event.target.checked;
@ -162,9 +156,9 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
setEnableBashHotkeys(event.target.checked);
Settings.EnableBashHotkeys = event.target.checked;
}
function handleEnableTimestampsChange(event: React.ChangeEvent<HTMLInputElement>): void {
setEnableTimestamps(event.target.checked);
Settings.EnableTimestamps = event.target.checked;
function handleTimestampFormatChange(event: React.ChangeEvent<HTMLInputElement>): void {
setTimestampFormat(event.target.value);
Settings.TimestampsFormat = event.target.value;
}
function handleSaveGameOnFile(event: React.ChangeEvent<HTMLInputElement>): void {
setSaveGameOnFileSave(event.target.checked);
@ -326,7 +320,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
</Typography>
}
>
<Typography>Suppress messages</Typography>
<Typography>Suppress story messages</Typography>
</Tooltip>
}
/>
@ -388,25 +382,6 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
}
/>
</ListItem>
<ListItem>
<FormControlLabel
control={
<Switch checked={suppressHospitalizationPopup} onChange={handleSuppressHospitalizationPopupChange} />
}
label={
<Tooltip
title={
<Typography>
If this is set, a popup message will no longer be shown when you are hospitalized after taking
too much damage.
</Typography>
}
>
<Typography>Suppress hospitalization popup</Typography>
</Tooltip>
}
/>
</ListItem>
{!!props.player.bladeburner && (
<ListItem>
<FormControlLabel
@ -493,21 +468,28 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
/>
</ListItem>
<ListItem>
<FormControlLabel
control={<Switch checked={enableTimestamps} onChange={handleEnableTimestampsChange} />}
label={
<Tooltip
title={
<Typography>
Terminal commands and log entries will be timestamped. The timestamp will have the format: M/D
h:m
</Typography>
}
>
<Typography>Enable timestamps</Typography>
</Tooltip>
<Tooltip
title={
<Typography>
Terminal commands and log entries will be timestamped. See
https://date-fns.org/docs/Getting-Started/
</Typography>
}
/>
>
<span>
<TextField
InputProps={{
startAdornment: (
<Typography color={formatTime(timestampFormat) === "format error" ? "error" : "success"}>
Timestamp&nbsp;format:&nbsp;
</Typography>
),
}}
value={timestampFormat}
onChange={handleTimestampFormatChange}
/>
</span>
</Tooltip>
</ListItem>
<ListItem>

@ -0,0 +1,10 @@
import { format } from "date-fns";
export function formatTime(fmt: string): string {
try {
return format(new Date(), fmt);
} catch (err: any) {
console.error(err);
return "format error";
}
}

@ -7,6 +7,7 @@ export function getTimestamp(): string {
const stringWidth = -2;
const formattedHours: string = `0${d.getHours()}`.slice(stringWidth);
const formattedMinutes: string = `0${d.getMinutes()}`.slice(stringWidth);
const formattedSeconds: string = `0${d.getSeconds()}`.slice(stringWidth);
return `${d.getMonth() + 1}/${d.getDate()} ${formattedHours}:${formattedMinutes}`;
return `${d.getMonth() + 1}/${d.getDate()} ${formattedHours}:${formattedMinutes}:${formattedSeconds}`;
}