From 46862d30fdd710f4f3650c38a35862bb6be9839c Mon Sep 17 00:00:00 2001 From: Daniel Ferri Date: Sat, 8 May 2021 18:44:21 +0200 Subject: [PATCH 01/31] Recursive and multi-command alias --- src/Alias.ts | 37 ++++++++++++++++++++++--------------- src/Terminal.jsx | 12 +++++++----- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/src/Alias.ts b/src/Alias.ts index 91c5dd96d..39931ad00 100644 --- a/src/Alias.ts +++ b/src/Alias.ts @@ -51,14 +51,14 @@ function addAlias(name: string, value: string): void { if (name in GlobalAliases) { delete GlobalAliases[name]; } - Aliases[name] = value; + Aliases[name] = value.trim(); } function addGlobalAlias(name: string, value: string): void { if (name in Aliases){ delete Aliases[name]; } - GlobalAliases[name] = value; + GlobalAliases[name] = value.trim(); } function getAlias(name: string): string | null { @@ -97,22 +97,29 @@ export function removeAlias(name: string): boolean { export function substituteAliases(origCommand: string): string { const commandArray = origCommand.split(" "); if (commandArray.length > 0){ - // For the unalias command, dont substite - if (commandArray[0] === "unalias") { return commandArray.join(" "); } + // For the alias and unalias commands, dont substite + if (commandArray[0] === "unalias" || commandArray[0] === "alias") { return commandArray.join(" "); } - const alias = getAlias(commandArray[0]); - if (alias != null) { - commandArray[0] = alias; - } else { - const alias = getGlobalAlias(commandArray[0]); + let somethingSubstituted = true; + let depth = 0; + + while(somethingSubstituted && depth < 10){ + depth++; + somethingSubstituted = false + const alias = getAlias(commandArray[0])?.split(" "); if (alias != null) { - commandArray[0] = alias; + somethingSubstituted = true + commandArray.splice(0, 1, ...alias); + //commandArray[0] = alias; } - } - for (let i = 0; i < commandArray.length; ++i) { - const alias = getGlobalAlias(commandArray[i]); - if (alias != null) { - commandArray[i] = alias; + for (let i = 0; i < commandArray.length; ++i) { + const alias = getGlobalAlias(commandArray[i])?.split(" "); + if (alias != null) { + somethingSubstituted = true + commandArray.splice(i, 1, ...alias); + i += alias.length - 1; + //commandArray[i] = alias; + } } } } diff --git a/src/Terminal.jsx b/src/Terminal.jsx index 3c2a4a4aa..f394251ca 100644 --- a/src/Terminal.jsx +++ b/src/Terminal.jsx @@ -625,7 +625,12 @@ let Terminal = { Terminal.commandHistoryIndex = Terminal.commandHistory.length; // Split commands and execute sequentially - commands = commands.split(";"); + commands = commands + .match(/(?:'[^']*'|"[^"]*"|[^;"])*/g) + .map(substituteAliases) + .map(c => c.match(/(?:'[^']*'|"[^"]*"|[^;"])*/g)) + .flat(); + console.log(commands); for (let i = 0; i < commands.length; i++) { if(commands[i].match(/^\s*$/)) { continue; } // Don't run commands that only have whitespace Terminal.executeCommand(commands[i].trim()); @@ -727,9 +732,6 @@ let Terminal = { return; } - // Process any aliases - command = substituteAliases(command); - // Allow usage of ./ if (command.startsWith("./")) { command = "run " + command.slice(2); @@ -873,7 +875,7 @@ let Terminal = { if (commandArray.length === 3) { if (commandArray[1] === "-g") { if (parseAliasDeclaration(commandArray[2], true)) { - post(`Set global alias ${commandArray[1]}`); + post(`Set global alias ${commandArray[2]}`); return; } } From ac8565d8208fc0cdf4aa8dc2d8de41746aaad00a Mon Sep 17 00:00:00 2001 From: Martin Fournier Date: Sat, 8 May 2021 15:02:26 -0400 Subject: [PATCH 02/31] Add basic docker support for development Assuming docker engine is installed, it is now possible to run the dev server using 'docker-compose up --build' or run the production version using 'docker build -t bitburner . && docker run -it -p 8000:80 bitburner'. --- .dockerignore | 14 ++++++++++++++ Dockerfile | 35 +++++++++++++++++++++++++++++++++++ docker-compose.yml | 15 +++++++++++++++ package.json | 2 ++ webpack.config.js | 23 ++++++++++++++++++----- 5 files changed, 84 insertions(+), 5 deletions(-) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 docker-compose.yml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..37b062314 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,14 @@ +node_modules/ + +.git +.gitattributes +.gitignore +.editorconfig + +.dockerignore +Dockerfile +docker-compose.yml + +*.md +Quotes.txt +netscript_tests/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..91ad8064b --- /dev/null +++ b/Dockerfile @@ -0,0 +1,35 @@ +FROM node:15.14.0 AS base + +WORKDIR /app + +# Scripts used in the npm preinstall hook +COPY scripts/engines-check.js scripts/semver.js scripts/ + +# Adding our dependencies and install before adding the rest of the files +# This prevents reinstallation of npm packages for every subsequent code modification +ENV npm_config_update_notifier=false +COPY package.json package-lock.json ./ +RUN npm ci --loglevel=error --no-audit --no-fund && npm rebuild node-sass + +# Adding all the remaining source files +COPY . . + +# We need more than the default 512MB otherwise webpack will throw 'heap out of memory' exceptions +# https://nodejs.org/api/cli.html#cli_max_old_space_size_size_in_megabytes +ENV NODE_OPTIONS=--max-old-space-size=1536 + +FROM base AS dev +# This is the main development build using the file watcher if you mount volumes +USER node +EXPOSE 8000 +CMD npm run start:container + +FROM base AS prod-dist +# We'll simply build the production dist files here to later reuse in a simple webserver +RUN npm run build + +FROM nginx:1.20.0-alpine AS prod +WORKDIR /usr/share/nginx/html +COPY --from=prod-dist /app/dist ./dist +COPY --from=prod-dist /app/index.html /app/favicon.ico /app/license.txt ./ +EXPOSE 80 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..bb81ce54e --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,15 @@ +version: "3.4" +services: + web: + image: bitburner:dev + build: + context: . + dockerfile: Dockerfile + target: dev + ports: + - "8000:8000" + volumes: + - ./src:/app/src + - ./css:/app/css + - ./utils:/app/utils + - ./test:/app/test diff --git a/package.json b/package.json index c12e247c6..78ee4fbc3 100644 --- a/package.json +++ b/package.json @@ -113,6 +113,7 @@ }, "scripts": { "start:dev": "webpack-dev-server --progress --env.devServer --mode development", + "start:container": "webpack-dev-server --progress --env.devServer --mode development --env.runInContainer", "build": "webpack --mode production", "build:dev": "webpack --mode development", "build:test": "webpack --config webpack.config-test.js", @@ -121,6 +122,7 @@ "lint:style": "stylelint --fix ./css/*", "preinstall": "node ./scripts/engines-check.js", "test": "mochapack --webpack-config webpack.config-test.js -r jsdom-global/register ./test/index.js", + "test:container": "mochapack --webpack-config webpack.config-test.js --slow 2000 --timeout 10000 -r jsdom-global/register ./test/index.js", "watch": "webpack --watch --mode production", "watch:dev": "webpack --watch --mode development" }, diff --git a/webpack.config.js b/webpack.config.js index da342707b..2ef501949 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -5,6 +5,7 @@ var HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = (env, argv) => { const isDevServer = (env || {}).devServer === true; + const runInContainer = (env || {}).runInContainer === true; const isDevelopment = argv.mode === 'development'; const outputDirectory = isDevServer ? "dist-dev" : "dist"; const entries = {}; @@ -22,6 +23,22 @@ module.exports = (env, argv) => { entrypoints: true, } + const devServerSettings = { + port: 8000, + publicPath: `/`, + stats: statsConfig, + }; + + // By default, the webpack-dev-server is not exposed outside of localhost. + // When running in a container we need it accessible externally. + if (runInContainer) { + devServerSettings.disableHostCheck = true; + devServerSettings.host = '0.0.0.0'; + devServerSettings.watchOptions = { + poll: true, + } + } + return { plugins: [ new webpack.DefinePlugin({ @@ -131,11 +148,7 @@ module.exports = (env, argv) => { }, }, }, - devServer: { - port: 8000, - publicPath: `/`, - stats: statsConfig, - }, + devServer: devServerSettings, resolve: { extensions: [ ".tsx", From 0f2b7517b43fb2ab4c76eedcac9bef694540869d Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Mon, 10 May 2021 18:26:50 -0400 Subject: [PATCH 03/31] Added export bonus --- src/Augmentation/AugmentationHelpers.jsx | 8 +++++++- src/Augmentation/ui/Root.tsx | 24 +++++++++++++++++++++--- src/ExportBonus.tsx | 19 +++++++++++++++++++ src/SaveObject.jsx | 3 +++ 4 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 src/ExportBonus.tsx diff --git a/src/Augmentation/AugmentationHelpers.jsx b/src/Augmentation/AugmentationHelpers.jsx index 30cf40e00..21268f8e1 100644 --- a/src/Augmentation/AugmentationHelpers.jsx +++ b/src/Augmentation/AugmentationHelpers.jsx @@ -12,6 +12,7 @@ import { Player } from "../Player"; import { prestigeAugmentation } from "../Prestige"; import { saveObject } from "../SaveObject"; import { Page, routing } from "../ui/navigationTracking"; +import { onExport } from "../ExportBonus"; import { dialogBoxCreate } from "../../utils/DialogBox"; import { clearObject } from "../../utils/helpers/clearObject"; @@ -2077,9 +2078,14 @@ export function displayAugmentationsContent(contentEl) { if (!routing.isOn(Page.Augmentations)) { return; } if (!(contentEl instanceof HTMLElement)) { return; } + function backup() { + saveObject.exportGame(); + onExport(Player); + } + ReactDOM.render( , contentEl, diff --git a/src/Augmentation/ui/Root.tsx b/src/Augmentation/ui/Root.tsx index d9350836c..f5315ed24 100644 --- a/src/Augmentation/ui/Root.tsx +++ b/src/Augmentation/ui/Root.tsx @@ -10,6 +10,8 @@ import { PurchasedAugmentations } from "./PurchasedAugmentations"; import { Player } from "../../Player"; import { StdButton } from "../../ui/React/StdButton"; +import { LastExportBonus, canGetBonus } from "../../ExportBonus"; +import { convertTimeMsToTimeElapsedString } from "../../../utils/StringHelperFunctions"; type IProps = { exportGameFn: () => void; @@ -17,15 +19,31 @@ type IProps = { } type IState = { - + rerender: boolean; } export class AugmentationsRoot extends React.Component { constructor(props: IProps) { super(props); + this.state = { + rerender: false, + }; + this.export = this.export.bind(this); + } + + export() { + this.props.exportGameFn(); + this.setState({ + rerender: !this.state.rerender, + }); } render(): React.ReactNode { + function exportBonusStr(): string { + if(canGetBonus()) return "(+1 favor to all factions)"; + return ""; + } + return (

Purchased Augmentations

@@ -60,8 +78,8 @@ export class AugmentationsRoot extends React.Component { diff --git a/src/ExportBonus.tsx b/src/ExportBonus.tsx new file mode 100644 index 000000000..ed33b6d24 --- /dev/null +++ b/src/ExportBonus.tsx @@ -0,0 +1,19 @@ +import { Factions } from "./Faction/Factions"; +import { IPlayer } from "./PersonObjects/IPlayer"; + +export let LastExportBonus: number = 0; + +const bonusTimer = 24*60*60*1000; // 24h +export function canGetBonus(): boolean { + const now = (new Date()).getTime() + if(now - LastExportBonus > bonusTimer) return true; + return false; +} + +export function onExport(p: IPlayer): void { + if(!canGetBonus()) return; + for (const facName of p.factions) { + Factions[facName].favor++; + } + LastExportBonus = (new Date()).getTime(); +} \ No newline at end of file diff --git a/src/SaveObject.jsx b/src/SaveObject.jsx index 5ffbb156d..884d47d02 100755 --- a/src/SaveObject.jsx +++ b/src/SaveObject.jsx @@ -31,6 +31,7 @@ import { loadStockMarket, StockMarket } from "./StockMarket/StockMarket"; import { createStatusText } from "./ui/createStatusText"; import { setTimeoutRef } from "./utils/SetTimeoutRef"; +import { LastExportBonus } from "./ExportBonus"; import { dialogBoxCreate } from "../utils/DialogBox"; import { gameOptionsBoxClose } from "../utils/GameOptions"; @@ -66,6 +67,7 @@ function BitburnerSaveObject() { this.FconfSettingsSave = ""; this.VersionSave = ""; this.AllGangsSave = ""; + this.LastExportBonus = ""; } BitburnerSaveObject.prototype.getSaveString = function() { @@ -94,6 +96,7 @@ BitburnerSaveObject.prototype.getSaveString = function() { this.SettingsSave = JSON.stringify(Settings); this.FconfSettingsSave = JSON.stringify(FconfSettings); this.VersionSave = JSON.stringify(CONSTANTS.Version); + this.LastExportBonus = JSON.stringify(LastExportBonus); if (Player.inGang()) { this.AllGangsSave = JSON.stringify(AllGangs); } From 5af10c84068c0df30ce760d9e720b555dd6a8de0 Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Mon, 10 May 2021 20:11:03 -0400 Subject: [PATCH 04/31] Offline money gain is based off hacking exp / time since last aug instead --- src/DevMenu.jsx | 24 +++++++++++++ src/NetscriptWorker.js | 5 +-- src/Script/ScriptHelpers.js | 69 ++++++++----------------------------- src/engine.jsx | 48 +++++++++++++++++++++++--- 4 files changed, 83 insertions(+), 63 deletions(-) diff --git a/src/DevMenu.jsx b/src/DevMenu.jsx index fd19c44eb..cd0f3592f 100644 --- a/src/DevMenu.jsx +++ b/src/DevMenu.jsx @@ -15,6 +15,8 @@ import { GetServerByHostname } from "./Server/ServerHelpers"; import { hackWorldDaemon } from "./RedPill"; import { StockMarket } from "./StockMarket/StockMarket"; import { Stock } from "./StockMarket/Stock"; +import { Engine, indexedDb } from "./engine"; +import { saveObject } from "./SaveObject"; import { dialogBoxCreate } from "../utils/DialogBox"; import { createElement } from "../utils/uiHelpers/createElement"; @@ -641,6 +643,15 @@ class DevMenuComponent extends Component { } } + timeskip(time) { + return () => { + Player.lastUpdate -= time; + Engine._lastUpdate -= time; + saveObject.saveGame(indexedDb); + setTimeout(() => location.reload(), 1000); + }; + } + render() { let factions = []; for (const i in Factions) { @@ -1212,6 +1223,19 @@ class DevMenuComponent extends Component {
+
+
+
+

Offline time skip:

+
+
+ + + +
+
+
+ ); } diff --git a/src/NetscriptWorker.js b/src/NetscriptWorker.js index d721b7716..cd38ea37e 100644 --- a/src/NetscriptWorker.js +++ b/src/NetscriptWorker.js @@ -564,7 +564,6 @@ export function updateOnlineScriptTimes(numCycles = 1) { * into worker scripts so that they will start running */ export function loadAllRunningScripts() { - var total = 0; let skipScriptLoad = (window.location.href.toLowerCase().indexOf("?noscripts") !== -1); if (skipScriptLoad) { console.info("Skipping the load of any scripts during startup"); } for (const property in AllServers) { @@ -587,13 +586,11 @@ export function loadAllRunningScripts() { createAndAddWorkerScript(server.runningScripts[j], server); // Offline production - total += scriptCalculateOfflineProduction(server.runningScripts[j]); + scriptCalculateOfflineProduction(server.runningScripts[j]); } } } } - - return total; } /** diff --git a/src/Script/ScriptHelpers.js b/src/Script/ScriptHelpers.js index 10cbcf257..9d6fde7b1 100644 --- a/src/Script/ScriptHelpers.js +++ b/src/Script/ScriptHelpers.js @@ -311,90 +311,51 @@ function saveAndCloseScriptEditor() { export function scriptCalculateOfflineProduction(runningScriptObj) { //The Player object stores the last update time from when we were online - var thisUpdate = new Date().getTime(); - var lastUpdate = Player.lastUpdate; - var timePassed = (thisUpdate - lastUpdate) / 1000; //Seconds + const thisUpdate = new Date().getTime(); + const lastUpdate = Player.lastUpdate; + const timePassed = (thisUpdate - lastUpdate) / 1000; //Seconds //Calculate the "confidence" rating of the script's true production. This is based //entirely off of time. We will arbitrarily say that if a script has been running for //4 hours (14400 sec) then we are completely confident in its ability - var confidence = (runningScriptObj.onlineRunningTime) / 14400; + let confidence = (runningScriptObj.onlineRunningTime) / 14400; if (confidence >= 1) {confidence = 1;} //Data map: [MoneyStolen, NumTimesHacked, NumTimesGrown, NumTimesWeaken] // Grow - for (var ip in runningScriptObj.dataMap) { + for (const ip in runningScriptObj.dataMap) { if (runningScriptObj.dataMap.hasOwnProperty(ip)) { if (runningScriptObj.dataMap[ip][2] == 0 || runningScriptObj.dataMap[ip][2] == null) {continue;} - var serv = AllServers[ip]; + const serv = AllServers[ip]; if (serv == null) {continue;} - var timesGrown = Math.round(0.5 * runningScriptObj.dataMap[ip][2] / runningScriptObj.onlineRunningTime * timePassed); - runningScriptObj.log("Called grow() on " + serv.hostname + " " + timesGrown + " times while offline"); - var growth = processSingleServerGrowth(serv, timesGrown, Player); - runningScriptObj.log(serv.hostname + " grown by " + numeralWrapper.format(growth * 100 - 100, '0.000000%') + " from grow() calls made while offline"); - } - } - - // Money from hacking - var totalOfflineProduction = 0; - for (var ip in runningScriptObj.dataMap) { - if (runningScriptObj.dataMap.hasOwnProperty(ip)) { - if (runningScriptObj.dataMap[ip][0] == 0 || runningScriptObj.dataMap[ip][0] == null) {continue;} - var serv = AllServers[ip]; - if (serv == null) {continue;} - var production = 0.5 * runningScriptObj.dataMap[ip][0] / runningScriptObj.onlineRunningTime * timePassed; - production *= confidence; - if (production > serv.moneyAvailable) { - production = serv.moneyAvailable; - } - totalOfflineProduction += production; - Player.gainMoney(production); - Player.recordMoneySource(production, "hacking"); - runningScriptObj.log(runningScriptObj.filename + " generated $" + production + " while offline by hacking " + serv.hostname); - serv.moneyAvailable -= production; - if (serv.moneyAvailable < 0) {serv.moneyAvailable = 0;} - if (isNaN(serv.moneyAvailable)) {serv.moneyAvailable = 0;} + const timesGrown = Math.round(0.5 * runningScriptObj.dataMap[ip][2] / runningScriptObj.onlineRunningTime * timePassed); + runningScriptObj.log(`Called on ${serv.hostname} ${timesGrown} times while offline`); + const growth = processSingleServerGrowth(serv, timesGrown, Player); + runningScriptObj.log(`'${serv.hostname}' grown by ${numeralWrapper.format(growth * 100 - 100, '0.000000%')} while offline`); } } // Offline EXP gain // A script's offline production will always be at most half of its online production. - var expGain = 0.5 * (runningScriptObj.onlineExpGained / runningScriptObj.onlineRunningTime) * timePassed; - expGain *= confidence; - + const expGain = confidence * (runningScriptObj.onlineExpGained / runningScriptObj.onlineRunningTime) * timePassed; Player.gainHackingExp(expGain); // Update script stats - runningScriptObj.offlineMoneyMade += totalOfflineProduction; runningScriptObj.offlineRunningTime += timePassed; runningScriptObj.offlineExpGained += expGain; - // Fortify a server's security based on how many times it was hacked - for (var ip in runningScriptObj.dataMap) { - if (runningScriptObj.dataMap.hasOwnProperty(ip)) { - if (runningScriptObj.dataMap[ip][1] == 0 || runningScriptObj.dataMap[ip][1] == null) {continue;} - var serv = AllServers[ip]; - if (serv == null) {continue;} - var timesHacked = Math.round(0.5 * runningScriptObj.dataMap[ip][1] / runningScriptObj.onlineRunningTime * timePassed); - runningScriptObj.log("Hacked " + serv.hostname + " " + timesHacked + " times while offline"); - serv.fortify(CONSTANTS.ServerFortifyAmount * timesHacked); - } - } - // Weaken - for (var ip in runningScriptObj.dataMap) { + for (const ip in runningScriptObj.dataMap) { if (runningScriptObj.dataMap.hasOwnProperty(ip)) { if (runningScriptObj.dataMap[ip][3] == 0 || runningScriptObj.dataMap[ip][3] == null) {continue;} - var serv = AllServers[ip]; + const serv = AllServers[ip]; if (serv == null) {continue;} - var timesWeakened = Math.round(0.5 * runningScriptObj.dataMap[ip][3] / runningScriptObj.onlineRunningTime * timePassed); - runningScriptObj.log("Called weaken() on " + serv.hostname + " " + timesWeakened + " times while offline"); + const timesWeakened = Math.round(0.5 * runningScriptObj.dataMap[ip][3] / runningScriptObj.onlineRunningTime * timePassed); + runningScriptObj.log(`Called weaken() on ${serv.hostname} ${timesWeakened} times while offline`); serv.weaken(CONSTANTS.ServerWeakenAmount * timesWeakened); } } - - return totalOfflineProduction; } //Returns a RunningScript object matching the filename and arguments on the diff --git a/src/engine.jsx b/src/engine.jsx index bfd4d761f..540328fa3 100644 --- a/src/engine.jsx +++ b/src/engine.jsx @@ -32,6 +32,11 @@ import { processPassiveFactionRepGain, inviteToFaction, } from "./Faction/FactionHelpers"; +import { + getHackingWorkRepGain, + getFactionSecurityWorkRepGain, + getFactionFieldWorkRepGain, +} from "./PersonObjects/formulas/reputation"; import { FconfSettings } from "./Fconf/FconfSettings"; import { hasHacknetServers, @@ -91,6 +96,7 @@ import { Page, routing } from "./ui/navigationTracking"; import { setSettingsLabels } from "./ui/setSettingsLabels"; import { Money } from "./ui/React/Money"; import { Hashes } from "./ui/React/Hashes"; +import { Reputation } from "./ui/React/Reputation"; import { ActiveScriptsRoot } from "./ui/ActiveScripts/Root"; import { initializeMainMenuHeaders } from "./ui/MainMenu/Headers"; @@ -1079,11 +1085,15 @@ const Engine = { // Calculate the number of cycles have elapsed while offline Engine._lastUpdate = new Date().getTime(); - var lastUpdate = Player.lastUpdate; - var numCyclesOffline = Math.floor((Engine._lastUpdate - lastUpdate) / Engine._idleSpeed); + const lastUpdate = Player.lastUpdate; + const timeOffline = Engine._lastUpdate - lastUpdate; + const numCyclesOffline = Math.floor(timeOffline / Engine._idleSpeed); + let offlineReputation = 0 + const offlineHackingIncome = Player.moneySourceA.hacking/(Player.playtimeSinceLastAug)*timeOffline*0.75; + Player.gainMoney(offlineHackingIncome); // Process offline progress - var offlineProductionFromScripts = loadAllRunningScripts(); // This also takes care of offline production for those scripts + loadAllRunningScripts(); // This also takes care of offline production for those scripts if (Player.isWorking) { if (Player.workType == CONSTANTS.WorkTypeFaction) { Player.workForFaction(numCyclesOffline); @@ -1098,6 +1108,31 @@ const Engine = { } else { Player.work(numCyclesOffline); } + } else { + + for(let i = 0; i < Player.factions.length; i++) { + const facName = Player.factions[i]; + if (!Factions.hasOwnProperty(facName)) continue; + const faction = Factions[facName]; + if (!faction.isMember) continue; + // No rep for special factions. + const info = faction.getInfo(); + if(!info.offersWork()) continue; + // No rep for gangs. + if(Player.getGangName() === facName) continue; + + + const hRep = getHackingWorkRepGain(Player, faction); + const sRep = getFactionSecurityWorkRepGain(Player, faction); + const fRep = getFactionFieldWorkRepGain(Player, faction); + // can be infinite, doesn't matter. + const reputationRate = Math.max(hRep, sRep, fRep) / Player.factions.length; + + const rep = reputationRate * + (numCyclesOffline); + faction.playerReputation += rep + offlineReputation += rep; + } } // Hacknet Nodes offline progress @@ -1157,7 +1192,10 @@ const Engine = { removeLoadingScreen(); const timeOfflineString = convertTimeMsToTimeElapsedString(time); dialogBoxCreate(<> - Offline for {timeOfflineString}. While you were offline, your scripts generated {Money(offlineProductionFromScripts)} and your Hacknet Nodes generated {hacknetProdInfo}. + Offline for {timeOfflineString}. While you were offline, your scripts + generated {Money(offlineHackingIncome)}, your Hacknet Nodes + generated {hacknetProdInfo} and you + gained {Reputation(offlineReputation)} divided amongst your factions. ); // Close main menu accordions for loaded game var visibleMenuTabs = [terminal, createScript, activeScripts, stats, @@ -1599,4 +1637,4 @@ window.onload = function() { } }; -export {Engine}; +export {Engine, indexedDb}; From c95a9261547048a6bb33dc953fc64bdc6724bfb5 Mon Sep 17 00:00:00 2001 From: Daniel Ferri Date: Tue, 11 May 2021 15:19:07 +0200 Subject: [PATCH 05/31] Add overflow time of bladeburner updates to the next update --- src/Bladeburner.jsx | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/src/Bladeburner.jsx b/src/Bladeburner.jsx index 6893feaeb..824259577 100644 --- a/src/Bladeburner.jsx +++ b/src/Bladeburner.jsx @@ -158,6 +158,7 @@ function Bladeburner(params={}) { // These times are in seconds this.actionTimeToComplete = 0; // 0 or -1 is an infinite running action (like training) this.actionTimeCurrent = 0; + this.actionTimeOverflow = 0; // ActionIdentifier Object var idleActionType = ActionTypes["Idle"]; @@ -406,7 +407,8 @@ Bladeburner.prototype.process = function() { this.randomEventCounter -= seconds; if (this.randomEventCounter <= 0) { this.randomEvent(); - this.randomEventCounter = getRandomInt(240, 600); + // Add instead of setting because we might have gone over the required time for the event + this.randomEventCounter += getRandomInt(240, 600); } this.processAction(seconds); @@ -664,8 +666,12 @@ Bladeburner.prototype.processAction = function(seconds) { throw new Error("Bladeburner.action is not an ActionIdentifier Object"); } - this.actionTimeCurrent += seconds; + // If the previous action went past its completion time, add to the next action + // This is not added inmediatly in case the automation changes the action + this.actionTimeCurrent += seconds + this.actionTimeOverflow; + this.actionTimeOverflow = 0; if (this.actionTimeCurrent >= this.actionTimeToComplete) { + this.actionTimeOverflow = this.actionTimeCurrent - this.actionTimeToComplete; return this.completeAction(); } } @@ -1889,17 +1895,18 @@ Bladeburner.prototype.updateActionAndSkillsContent = function() { Bladeburner.prototype.updateGeneralActionsUIElement = function(el, action) { removeChildrenFromElement(el); var isActive = el.classList.contains(ActiveActionCssClass); + var computedActionTimeCurrent = Math.min(this.actionTimeCurrent+this.actionTimeOverflow,this.actionTimeToComplete); el.appendChild(createElement("h2", { // Header innerText:isActive ? action.name + " (IN PROGRESS - " + - formatNumber(this.actionTimeCurrent, 0) + " / " + + formatNumber(computedActionTimeCurrent, 0) + " / " + formatNumber(this.actionTimeToComplete, 0) + ")" : action.name, display:"inline-block", })); if (isActive) { // Progress bar if its active - var progress = this.actionTimeCurrent / this.actionTimeToComplete; + var progress = computedActionTimeCurrent / this.actionTimeToComplete; el.appendChild(createElement("p", { display:"block", innerText:createProgressBarText({progress:progress}), @@ -1931,17 +1938,18 @@ Bladeburner.prototype.updateContractsUIElement = function(el, action) { removeChildrenFromElement(el); var isActive = el.classList.contains(ActiveActionCssClass); var estimatedSuccessChance = action.getSuccessChance(this, {est:true}); + var computedActionTimeCurrent = Math.min(this.actionTimeCurrent+this.actionTimeOverflow,this.actionTimeToComplete); el.appendChild(createElement("h2", { // Header innerText:isActive ? action.name + " (IN PROGRESS - " + - formatNumber(this.actionTimeCurrent, 0) + " / " + + formatNumber(computedActionTimeCurrent, 0) + " / " + formatNumber(this.actionTimeToComplete, 0) + ")" : action.name, display:"inline-block", })); if (isActive) { // Progress bar if its active - var progress = this.actionTimeCurrent / this.actionTimeToComplete; + var progress = computedActionTimeCurrent / this.actionTimeToComplete; el.appendChild(createElement("p", { display:"block", innerText:createProgressBarText({progress:progress}), @@ -2030,16 +2038,18 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) { removeChildrenFromElement(el); var isActive = el.classList.contains(ActiveActionCssClass); var estimatedSuccessChance = action.getSuccessChance(this, {est:true}); + var computedActionTimeCurrent = Math.min(this.actionTimeCurrent+this.actionTimeOverflow,this.actionTimeToComplete); + el.appendChild(createElement("h2", { // Header innerText:isActive ? action.name + " (IN PROGRESS - " + - formatNumber(this.actionTimeCurrent, 0) + " / " + + formatNumber(computedActionTimeCurrent, 0) + " / " + formatNumber(this.actionTimeToComplete, 0) + ")" : action.name, display:"inline-block", })); if (isActive) { // Progress bar if its active - var progress = this.actionTimeCurrent / this.actionTimeToComplete; + var progress = computedActionTimeCurrent / this.actionTimeToComplete; el.appendChild(createElement("p", { display:"block", innerText:createProgressBarText({progress:progress}), @@ -2171,6 +2181,7 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) { var estimatedSuccessChance = action.getSuccessChance(this, {est:true}); var actionTime = action.getActionTime(this); var hasReqdRank = this.rank >= action.reqdRank; + var computedActionTimeCurrent = Math.min(this.actionTimeCurrent+this.actionTimeOverflow,this.actionTimeToComplete); // UI for Completed Black Op if (isCompleted) { @@ -2182,14 +2193,14 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) { el.appendChild(createElement("h2", { // Header innerText:isActive ? action.name + " (IN PROGRESS - " + - formatNumber(this.actionTimeCurrent, 0) + " / " + + formatNumber(computedActionTimeCurrent, 0) + " / " + formatNumber(this.actionTimeToComplete, 0) + ")" : action.name, display:"inline-block", })); if (isActive) { // Progress bar if its active - var progress = this.actionTimeCurrent / this.actionTimeToComplete; + var progress = computedActionTimeCurrent / this.actionTimeToComplete; el.appendChild(createElement("p", { display:"block", innerText:createProgressBarText({progress:progress}), From f8a085af7ac0046b7d3eabaa1457f61ccbba4ef6 Mon Sep 17 00:00:00 2001 From: Daniel Ferri Date: Tue, 11 May 2021 15:34:05 +0200 Subject: [PATCH 06/31] Autofocus the input when opening a "Set Team Size" popup --- src/Bladeburner.jsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Bladeburner.jsx b/src/Bladeburner.jsx index 824259577..843d43a7a 100644 --- a/src/Bladeburner.jsx +++ b/src/Bladeburner.jsx @@ -2103,6 +2103,7 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) { }, }); createPopup(popupId, [txt, input, setBtn, cancelBtn]); + input.focus(); }, })); } @@ -2254,6 +2255,7 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) { }, }); createPopup(popupId, [txt, input, setBtn, cancelBtn]); + input.focus(); }, })); } From 08b0c7710dac2cdee941d59040207947c171d38b Mon Sep 17 00:00:00 2001 From: Daniel Ferri Date: Tue, 11 May 2021 19:27:02 +0200 Subject: [PATCH 07/31] Changed import so it saves and reloads the page --- src/SaveObject.jsx | 71 ++-------------------------------------------- src/engine.jsx | 16 ++++++----- 2 files changed, 11 insertions(+), 76 deletions(-) diff --git a/src/SaveObject.jsx b/src/SaveObject.jsx index 884d47d02..5c5b2f485 100755 --- a/src/SaveObject.jsx +++ b/src/SaveObject.jsx @@ -460,75 +460,8 @@ function loadImportedGame(saveObj, saveString) { console.error("ERROR: Failed to parse AllGangsSave: " + e); } } - - var popupId = "import-game-restart-game-notice"; - var txt = createElement("p", { - innerText:"Imported game! You need to SAVE the game and then RELOAD the page " + - "to make sure everything runs smoothly", - }); - var gotitBtn = createElement("a", { - class:"a-link-button", float:"right", padding:"6px", innerText:"Got it!", - clickListener:() => { - removeElementById(popupId); - }, - }); - createPopup(popupId, [txt, gotitBtn]); - gameOptionsBoxClose(); - - // Re-start game - Engine.setDisplayElements(); // Sets variables for important DOM elements - Engine.init(); // Initialize buttons, work, etc. - - // Calculate the number of cycles have elapsed while offline - Engine._lastUpdate = new Date().getTime(); - var lastUpdate = Player.lastUpdate; - var numCyclesOffline = Math.floor((Engine._lastUpdate - lastUpdate) / Engine._idleSpeed); - - // Process offline progress - var offlineProductionFromScripts = loadAllRunningScripts(); // This also takes care of offline production for those scripts - if (Player.isWorking) { - if (Player.workType == CONSTANTS.WorkTypeFaction) { - Player.workForFaction(numCyclesOffline); - } else if (Player.workType == CONSTANTS.WorkTypeCreateProgram) { - Player.createProgramWork(numCyclesOffline); - } else if (Player.workType == CONSTANTS.WorkTypeStudyClass) { - Player.takeClass(numCyclesOffline); - } else if (Player.workType == CONSTANTS.WorkTypeCrime) { - Player.commitCrime(numCyclesOffline); - } else if (Player.workType == CONSTANTS.WorkTypeCompanyPartTime) { - Player.workPartTime(numCyclesOffline); - } else { - Player.work(numCyclesOffline); - } - } - - // Hacknet Nodes offline progress - var offlineProductionFromHacknetNodes = processHacknetEarnings(numCyclesOffline); - - // Passive faction rep gain offline - processPassiveFactionRepGain(numCyclesOffline); - - // Update total playtime - var time = numCyclesOffline * Engine._idleSpeed; - if (Player.totalPlaytime == null) {Player.totalPlaytime = 0;} - if (Player.playtimeSinceLastAug == null) {Player.playtimeSinceLastAug = 0;} - if (Player.playtimeSinceLastBitnode == null) {Player.playtimeSinceLastBitnode = 0;} - Player.totalPlaytime += time; - Player.playtimeSinceLastAug += time; - Player.playtimeSinceLastBitnode += time; - - // Re-apply augmentations - Player.reapplyAllAugmentations(); - - // Clear terminal - $("#terminal tr:not(:last)").remove(); - - Player.lastUpdate = Engine._lastUpdate; - Engine.start(); // Run main game loop and Scripts loop - const timeOfflineString = convertTimeMsToTimeElapsedString(time); - dialogBoxCreate(<>Offline for {timeOfflineString}. While you were offline, your scripts -generated {Money(offlineProductionFromScripts)} -and your Hacknet Nodes generated hacknetProdInfo); + saveObject.saveGame(Engine.indexedDb); + location.reload(); return true; } diff --git a/src/engine.jsx b/src/engine.jsx index 540328fa3..da215de96 100644 --- a/src/engine.jsx +++ b/src/engine.jsx @@ -236,6 +236,8 @@ const Engine = { characterInfo: null, }, + indexedDb: undefined, + // Time variables (milliseconds unix epoch time) _lastUpdate: new Date().getTime(), _idleSpeed: 200, // Speed (in ms) at which the main loop is updated @@ -815,7 +817,7 @@ const Engine = { Engine.Counters.autoSaveCounter = Infinity; } else { Engine.Counters.autoSaveCounter = Settings.AutosaveInterval * 5; - saveObject.saveGame(indexedDb); + saveObject.saveGame(Engine.indexedDb); } } @@ -1468,13 +1470,13 @@ const Engine = { // Save, Delete, Import/Export buttons Engine.Clickables.saveMainMenuButton = document.getElementById("save-game-link"); Engine.Clickables.saveMainMenuButton.addEventListener("click", function() { - saveObject.saveGame(indexedDb); + saveObject.saveGame(Engine.indexedDb); return false; }); Engine.Clickables.deleteMainMenuButton = document.getElementById("delete-game-link"); Engine.Clickables.deleteMainMenuButton.addEventListener("click", function() { - saveObject.deleteGame(indexedDb); + saveObject.deleteGame(Engine.indexedDb); return false; }); @@ -1485,7 +1487,7 @@ const Engine = { // Character Overview buttons document.getElementById("character-overview-save-button").addEventListener("click", function() { - saveObject.saveGame(indexedDb); + saveObject.saveGame(Engine.indexedDb); return false; }); @@ -1597,7 +1599,7 @@ const Engine = { }, }; -var indexedDb, indexedDbRequest; +var indexedDbRequest; window.onload = function() { if (!window.indexedDB) { return Engine.load(null); // Will try to load from localstorage @@ -1617,8 +1619,8 @@ window.onload = function() { }; indexedDbRequest.onsuccess = function(e) { - indexedDb = e.target.result; - var transaction = indexedDb.transaction(["savestring"]); + Engine.indexedDb = e.target.result; + var transaction = Engine.indexedDb.transaction(["savestring"]); var objectStore = transaction.objectStore("savestring"); var request = objectStore.get("save"); request.onerror = function(e) { From 0cb2fd1a878a3b1b25894f2e00f32a17f8fe9416 Mon Sep 17 00:00:00 2001 From: Daniel Ferri Date: Tue, 11 May 2021 19:46:51 +0200 Subject: [PATCH 08/31] Removed useless code --- src/SaveObject.jsx | 48 ++++++++-------------------------------------- 1 file changed, 8 insertions(+), 40 deletions(-) diff --git a/src/SaveObject.jsx b/src/SaveObject.jsx index 5c5b2f485..9434bad3a 100755 --- a/src/SaveObject.jsx +++ b/src/SaveObject.jsx @@ -8,16 +8,10 @@ import { Companies, loadCompanies } from "./Company/Companies"; import { CONSTANTS } from "./Constants"; import { Engine } from "./engine"; import { Factions, loadFactions } from "./Faction/Factions"; -import { processPassiveFactionRepGain } from "./Faction/FactionHelpers"; import { loadFconf } from "./Fconf/Fconf"; import { FconfSettings } from "./Fconf/FconfSettings"; import { loadAllGangs, AllGangs } from "./Gang"; -import { - hasHacknetServers, - processHacknetEarnings, -} from "./Hacknet/HacknetHelpers"; import { loadMessages, initMessages, Messages } from "./Message/MessageHelpers"; -import { loadAllRunningScripts } from "./NetscriptWorker"; import { Player, loadPlayer } from "./Player"; import { AllServers, loadAllServers } from "./Server/AllServers"; import { Settings } from "./Settings/Settings"; @@ -34,17 +28,12 @@ import { setTimeoutRef } from "./utils/SetTimeoutRef"; import { LastExportBonus } from "./ExportBonus"; import { dialogBoxCreate } from "../utils/DialogBox"; -import { gameOptionsBoxClose } from "../utils/GameOptions"; -import { convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions"; import { clearEventListeners } from "../utils/uiHelpers/clearEventListeners"; import { Reviver, Generic_toJSON, Generic_fromJSON, } from "../utils/JSONReviver"; -import { createElement } from "../utils/uiHelpers/createElement"; -import { createPopup } from "../utils/uiHelpers/createPopup"; -import { removeElementById } from "../utils/uiHelpers/removeElementById"; import Decimal from "decimal.js"; @@ -288,22 +277,11 @@ function loadGame(saveString) { function loadImportedGame(saveObj, saveString) { var tempSaveObj = null; var tempPlayer = null; - var tempAllServers = null; - var tempCompanies = null; - var tempFactions = null; - var tempSpecialServerIps = null; - var tempAliases = null; - var tempGlobalAliases = null; - var tempMessages = null; - var tempStockMarket = null; - var tempAllGangs = null; - let tempCorporationResearchTrees = null; // Check to see if the imported save file can be parsed. If any // errors are caught it will fail try { var decodedSaveString = decodeURIComponent(escape(atob(saveString))); - tempSaveObj = new BitburnerSaveObject(); tempSaveObj = JSON.parse(decodedSaveString, Reviver); tempPlayer = JSON.parse(tempSaveObj.PlayerSave, Reviver); @@ -311,33 +289,27 @@ function loadImportedGame(saveObj, saveString) { // Parse Decimal.js objects tempPlayer.money = new Decimal(tempPlayer.money); - tempAllServers = JSON.parse(tempSaveObj.AllServersSave, Reviver); - tempCompanies = JSON.parse(tempSaveObj.CompaniesSave, Reviver); - tempFactions = JSON.parse(tempSaveObj.FactionsSave, Reviver); - tempSpecialServerIps = JSON.parse(tempSaveObj.SpecialServerIpsSave, Reviver); + JSON.parse(tempSaveObj.AllServersSave, Reviver); + JSON.parse(tempSaveObj.CompaniesSave, Reviver); + JSON.parse(tempSaveObj.FactionsSave, Reviver); + JSON.parse(tempSaveObj.SpecialServerIpsSave, Reviver); if (tempSaveObj.hasOwnProperty("AliasesSave")) { try { - tempAliases = JSON.parse(tempSaveObj.AliasesSave, Reviver); + JSON.parse(tempSaveObj.AliasesSave, Reviver); } catch(e) { console.error(`Parsing Aliases save failed: ${e}`); - tempAliases = {}; } - } else { - tempAliases = {}; } if (tempSaveObj.hasOwnProperty("GlobalAliases")) { try { - tempGlobalAliases = JSON.parse(tempSaveObj.AliasesSave, Reviver); + JSON.parse(tempSaveObj.AliasesSave, Reviver); } catch(e) { console.error(`Parsing Global Aliases save failed: ${e}`); - tempGlobalAliases = {}; } - } else { - tempGlobalAliases = {}; } if (tempSaveObj.hasOwnProperty("MessagesSave")) { try { - tempMessages = JSON.parse(tempSaveObj.MessagesSave, Reviver); + JSON.parse(tempSaveObj.MessagesSave, Reviver); } catch(e) { console.error(`Parsing Messages save failed: ${e}`); initMessages(); @@ -347,13 +319,10 @@ function loadImportedGame(saveObj, saveString) { } if (saveObj.hasOwnProperty("StockMarketSave")) { try { - tempStockMarket = JSON.parse(tempSaveObj.StockMarketSave, Reviver); + JSON.parse(tempSaveObj.StockMarketSave, Reviver); } catch(e) { console.error(`Parsing StockMarket save failed: ${e}`); - tempStockMarket = {}; } - } else { - tempStockMarket = {}; } if (tempSaveObj.hasOwnProperty("VersionSave")) { try { @@ -362,7 +331,6 @@ function loadImportedGame(saveObj, saveString) { } catch(e) { console.error("Parsing Version save failed: " + e); } - } else { } if (tempPlayer.inGang() && tempSaveObj.hasOwnProperty("AllGangsSave")) { try { From 1b57c1f7e0e9d5448e4379a0e0b0550db55b8ffb Mon Sep 17 00:00:00 2001 From: Daniel Ferri Date: Tue, 11 May 2021 20:16:18 +0200 Subject: [PATCH 09/31] Changed loops to be more concise --- src/Bladeburner.jsx | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/Bladeburner.jsx b/src/Bladeburner.jsx index 843d43a7a..514a0a2d5 100644 --- a/src/Bladeburner.jsx +++ b/src/Bladeburner.jsx @@ -382,22 +382,16 @@ Bladeburner.prototype.process = function() { this.stamina = Math.min(this.maxStamina, this.stamina); // Count increase for contracts/operations - for (var contractName in this.contracts) { - if (this.contracts.hasOwnProperty(contractName)) { - var contract = this.contracts[contractName]; - contract.count += (seconds * contract.countGrowth/BladeburnerConstants.ActionCountGrowthPeriod); - } + for (let contract of Object.values(this.contracts)) { + contract.count += (seconds * contract.countGrowth/BladeburnerConstants.ActionCountGrowthPeriod); } - for (var operationName in this.operations) { - if (this.operations.hasOwnProperty(operationName)) { - var op = this.operations[operationName]; - op.count += (seconds * op.countGrowth/BladeburnerConstants.ActionCountGrowthPeriod); - } + for (let op of Object.values(this.operations)) { + op.count += (seconds * op.countGrowth/BladeburnerConstants.ActionCountGrowthPeriod); } // Chaos goes down very slowly - for (var i = 0; i < BladeburnerConstants.CityNames.length; ++i) { - var city = this.cities[BladeburnerConstants.CityNames[i]]; + for (let cityName of BladeburnerConstants.CityNames) { + var city = this.cities[cityName]; if (!(city instanceof City)) {throw new Error("Invalid City object when processing passive chaos reduction in Bladeburner.process");} city.chaos -= (0.0001 * seconds); city.chaos = Math.max(0, city.chaos); From 5e517d1671d1bcdd04ccb7b2bde29ec4ca5f998f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 May 2021 00:32:31 +0000 Subject: [PATCH 10/31] Bump codemirror from 5.43.0 to 5.58.2 Bumps [codemirror](https://github.com/codemirror/CodeMirror) from 5.43.0 to 5.58.2. - [Release notes](https://github.com/codemirror/CodeMirror/releases) - [Changelog](https://github.com/codemirror/CodeMirror/blob/master/CHANGELOG.md) - [Commits](https://github.com/codemirror/CodeMirror/compare/5.43.0...5.58.2) Signed-off-by: dependabot[bot] --- package-lock.json | 18 +++++++++--------- package.json | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index aa02bc6cc..c763d4ddd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { "name": "bitburner", - "version": "0.51.5", + "version": "0.51.8", "lockfileVersion": 2, "requires": true, "packages": { "": { - "version": "0.51.5", + "version": "0.51.8", "hasInstallScript": true, "license": "SEE LICENSE IN license.txt", "dependencies": { @@ -21,7 +21,7 @@ "async": "^2.6.1", "autosize": "^4.0.2", "brace": "^0.11.1", - "codemirror": "^5.43.0", + "codemirror": "^5.58.2", "decimal.js": "7.2.3", "enhanced-resolve": "^4.0.0", "escodegen": "^1.11.0", @@ -3516,9 +3516,9 @@ } }, "node_modules/codemirror": { - "version": "5.43.0", - "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.43.0.tgz", - "integrity": "sha512-mljwQWUaWIf85I7QwTBryF2ASaIvmYAL4s5UCanCJFfKeXOKhrqdHWdHiZWAMNT+hjLTCnVx2S/SYTORIgxsgA==" + "version": "5.58.2", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.58.2.tgz", + "integrity": "sha512-K/hOh24cCwRutd1Mk3uLtjWzNISOkm4fvXiMO7LucCrqbh6aJDdtqUziim3MZUI6wOY0rvY1SlL1Ork01uMy6w==" }, "node_modules/collapse-white-space": { "version": "1.0.4", @@ -21942,9 +21942,9 @@ "dev": true }, "codemirror": { - "version": "5.43.0", - "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.43.0.tgz", - "integrity": "sha512-mljwQWUaWIf85I7QwTBryF2ASaIvmYAL4s5UCanCJFfKeXOKhrqdHWdHiZWAMNT+hjLTCnVx2S/SYTORIgxsgA==" + "version": "5.58.2", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.58.2.tgz", + "integrity": "sha512-K/hOh24cCwRutd1Mk3uLtjWzNISOkm4fvXiMO7LucCrqbh6aJDdtqUziim3MZUI6wOY0rvY1SlL1Ork01uMy6w==" }, "collapse-white-space": { "version": "1.0.4", diff --git a/package.json b/package.json index c12e247c6..133755934 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "async": "^2.6.1", "autosize": "^4.0.2", "brace": "^0.11.1", - "codemirror": "^5.43.0", + "codemirror": "^5.58.2", "decimal.js": "7.2.3", "enhanced-resolve": "^4.0.0", "escodegen": "^1.11.0", From 525c0ada5564bd288681c0cf95f4c5cea379286b Mon Sep 17 00:00:00 2001 From: Daniel Ferri Date: Wed, 12 May 2021 21:10:36 +0200 Subject: [PATCH 11/31] Added dynamic generation of functionNames --- src/NetscriptFunctions.js | 91 ++++++++------------------------------- 1 file changed, 18 insertions(+), 73 deletions(-) diff --git a/src/NetscriptFunctions.js b/src/NetscriptFunctions.js index d85cc6c48..696fb4ea9 100644 --- a/src/NetscriptFunctions.js +++ b/src/NetscriptFunctions.js @@ -179,77 +179,6 @@ import { createElement } from "../utils/uiHelpers/createElement"; import { createPopup } from "../utils/uiHelpers/createPopup"; import { removeElementById } from "../utils/uiHelpers/removeElementById"; -const possibleLogs = { - ALL: true, - scan: true, - hack: true, - sleep: true, - disableLog: true, - enableLog: true, - grow: true, - weaken: true, - nuke: true, - brutessh: true, - ftpcrack: true, - relaysmtp: true, - httpworm: true, - sqlinject: true, - run:true, - exec:true, - spawn: true, - kill: true, - killall: true, - scp: true, - getHackingLevel: true, - getServerMoneyAvailable: true, - getServerSecurityLevel: true, - getServerBaseSecurityLevel: true, - getServerMinSecurityLevel: true, - getServerRequiredHackingLevel: true, - getServerMaxMoney: true, - getServerGrowth: true, - getServerNumPortsRequired: true, - getServerRam: true, - - // TIX API - buyStock: true, - sellStock: true, - shortStock: true, - sellShort: true, - purchase4SMarketData: true, - purchase4SMarketDataTixApi: true, - - // Singularity Functions - purchaseServer: true, - deleteServer: true, - universityCourse: true, - gymWorkout: true, - travelToCity: true, - purchaseTor: true, - purchaseProgram: true, - stopAction: true, - upgradeHomeRam: true, - workForCompany: true, - applyToCompany: true, - joinFaction: true, - workForFaction: true, - donateToFaction: true, - createProgram: true, - commitCrime: true, - - // Bladeburner API - startAction: true, - upgradeSkill: true, - setTeamSize: true, - joinBladeburnerFaction: true, - - // Gang API - recruitMember: true, - setMemberTask: true, - purchaseEquipment: true, - setTerritoryWarfare: true, -} - const defaultInterpreter = new Interpreter('', () => undefined); // the acorn interpreter has a bug where it doesn't convert arrays correctly. @@ -739,7 +668,7 @@ function NetscriptFunctions(workerScript) { return out; } - return { + const functions = { hacknet : { numNodes : function() { return Player.hacknetNodes.length; @@ -4544,7 +4473,23 @@ function NetscriptFunctions(workerScript) { } return ret; }, - } // End return + } + + function getFunctionNames(obj) { + const functionNames = []; + for(const [key, value] of Object.entries(obj)){ + if(typeof(value)=="function"){ + functionNames.push(key); + }else if(typeof(value)=="object"){ + functionNames.push(...getFunctionNames(value)); + } + } + return functionNames; + } + + const possibleLogs = Object.fromEntries(["ALL", ...getFunctionNames(functions)].map(a => [a, true])) + + return functions; } // End NetscriptFunction() export { NetscriptFunctions }; \ No newline at end of file From 8411de8e4281c09a07a9bb02254dba1435df4a91 Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Sat, 15 May 2021 10:54:19 -0400 Subject: [PATCH 12/31] remove offline calc from importing game --- src/SaveObject.jsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/SaveObject.jsx b/src/SaveObject.jsx index 884d47d02..8a3f341a7 100755 --- a/src/SaveObject.jsx +++ b/src/SaveObject.jsx @@ -525,10 +525,6 @@ function loadImportedGame(saveObj, saveString) { Player.lastUpdate = Engine._lastUpdate; Engine.start(); // Run main game loop and Scripts loop - const timeOfflineString = convertTimeMsToTimeElapsedString(time); - dialogBoxCreate(<>Offline for {timeOfflineString}. While you were offline, your scripts -generated {Money(offlineProductionFromScripts)} -and your Hacknet Nodes generated hacknetProdInfo); return true; } From e27b19ffaec83aa950893f55b22cbc0058d75ec9 Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Sat, 15 May 2021 11:05:52 -0400 Subject: [PATCH 13/31] update changelog --- src/Constants.ts | 59 ++++++++---------------------------------------- 1 file changed, 9 insertions(+), 50 deletions(-) diff --git a/src/Constants.ts b/src/Constants.ts index 27e1b2dfa..c110f6997 100644 --- a/src/Constants.ts +++ b/src/Constants.ts @@ -6,7 +6,7 @@ import { IMap } from "./types"; export const CONSTANTS: IMap = { - Version: "0.51.8", + Version: "0.51.9", /** Max level for any skill, assuming no multipliers. Determined by max numerical value in javascript for experience * and the skill level formula in Player.js. Note that all this means it that when experience hits MAX_INT, then @@ -228,60 +228,19 @@ export const CONSTANTS: IMap = { LatestUpdate: ` - v0.51.8 - 2021-05-07 It was there all along (hydroflame) + v0.51.9 - 2021-05-07 untitled yet ------- - Servers + Offline - * Update n00dles metadata + * Offline money gain has been reworked (it is more generous) + * If you're not working anywhere and go offline the game will work for you + at all your factions evenly. - Netscript - - * 'hashGainRate' use the correct 'usedRam' and 'maxRam' - * Fix 'setActionAutolevel' logging. - * Fix 'setActionLevel' not working at all. - * Add 'installBackdoor' singularity function. - - Hacknet - - * Fix Hacknet Servers total production always displaying 0 - - Documentation - - * Updated guide to no longer recommend BN12. - * Fix documentation for maxNumNodes (@ModdedGamers) - * Fix typo in 'sourcefiles.rst' - * Fix typo in 'recommendedbitnodeorder.rst' - * Fix 'getServer' documentation missing 'server' argument. - * Fix missing ram cost in 'getData.rst' - * Fix basic formulas examples. - * Fix typo in BN11 description. - * Fix formatting issue in Bladeburner (@Pimgd) + Export + * Exporting now gives +1 favor to all joined factions every 24h. Misc. - - * Fix negative money being displayed in full. - * Fix Hacking Missions not working. - * Fix Corporation tree not rendering. - * Fix script being needlessly recompiled. This should save real ram (not game ram) - * w0r1d_d43m0n can be backdoored - * Coding Contracts title is click-to-copy (@Rodeth) - * Covenant memory upgrade works better. - * Fix Neuroflux not being correctly calculated when entering BN with SF12. - * Delete Active Script now delete all active scripts, not just home. - * Now you can 'cd' in directories that only contain '.txt' files. - * Fix 'analyze' always saying players had root access - * Passive faction rep no longer builds for special factions. - * Donation option no longer appears for special factions. - * Rephrased some milestones. - * donation textbox now accepts money in the format '1b' and the like (@Dawe) - * Fix being able to join hated factions simultaneously. (@Dawe) - * 'ls' now displays files in multiple column. (Helps players with many files) - * Bladeburner multiplers now appear under Character>Stats and - Character>Augmentation when they are relevant. - * Fix missing functions syntax highlight in codemirror. - * Fix infiltration number formatting. - * script income transfers to parent on death. This helps keep track of - income for scripts that spawn short lived scripts. + * ls now correctly lists all files. `, } \ No newline at end of file From 299e964e2b8df4512cddc7f7cedaa0132ecc8d06 Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Sat, 15 May 2021 11:09:32 -0400 Subject: [PATCH 14/31] update changelog --- src/Constants.ts | 4 ++++ src/Terminal.jsx | 1 - 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Constants.ts b/src/Constants.ts index c110f6997..73e974fd7 100644 --- a/src/Constants.ts +++ b/src/Constants.ts @@ -231,6 +231,10 @@ export const CONSTANTS: IMap = { v0.51.9 - 2021-05-07 untitled yet ------- + Alias + * several commands can be included in 1 alias. Recursive alias now work to + a depth of 10. + Offline * Offline money gain has been reworked (it is more generous) diff --git a/src/Terminal.jsx b/src/Terminal.jsx index add64e19d..066a8cc32 100644 --- a/src/Terminal.jsx +++ b/src/Terminal.jsx @@ -630,7 +630,6 @@ let Terminal = { .map(substituteAliases) .map(c => c.match(/(?:'[^']*'|"[^"]*"|[^;"])*/g)) .flat(); - console.log(commands); for (let i = 0; i < commands.length; i++) { if(commands[i].match(/^\s*$/)) { continue; } // Don't run commands that only have whitespace Terminal.executeCommand(commands[i].trim()); From 1503d82e35dbc81cdab4d37828fbeee241437285 Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Sat, 15 May 2021 11:19:02 -0400 Subject: [PATCH 15/31] update changelog --- src/Constants.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Constants.ts b/src/Constants.ts index 73e974fd7..847112d92 100644 --- a/src/Constants.ts +++ b/src/Constants.ts @@ -233,7 +233,7 @@ export const CONSTANTS: IMap = { Alias * several commands can be included in 1 alias. Recursive alias now work to - a depth of 10. + a depth of 10. (@Dawe) Offline @@ -246,5 +246,6 @@ export const CONSTANTS: IMap = { Misc. * ls now correctly lists all files. + * importing auto save+reloads (@Dawe) `, } \ No newline at end of file From ae04b7357e8f5d86ad7e9ed01dfa7a177fe9b81b Mon Sep 17 00:00:00 2001 From: Martin Fournier Date: Thu, 13 May 2021 08:11:42 -0400 Subject: [PATCH 16/31] Add setting to suppress Bladeburner popups Used to suppress the message that is shown when your Bladeburner action is cancelled when busy with something else. Will be hidden if the player does not have access to Bladeburners. --- src/Bladeburner.jsx | 5 ++++- src/Settings/Settings.ts | 7 +++++++ src/index.html | 10 ++++++++++ src/ui/setSettingsLabels.js | 10 +++++++++- 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/Bladeburner.jsx b/src/Bladeburner.jsx index 6893feaeb..64738708d 100644 --- a/src/Bladeburner.jsx +++ b/src/Bladeburner.jsx @@ -24,6 +24,7 @@ import { convertTimeMsToTimeElapsedString, } from "../utils/StringHelperFunctions"; +import { Settings } from "./Settings/Settings"; import { ConsoleHelpText } from "./Bladeburner/data/Help"; import { City } from "./Bladeburner/City"; import { BladeburnerConstants } from "./Bladeburner/data/Constants"; @@ -358,7 +359,9 @@ Bladeburner.prototype.process = function() { msg += `

Your automation was disabled as well. You will have to re-enable it through the Bladeburner console` this.automateEnabled = false; } - dialogBoxCreate(msg); + if (!Settings.SuppressBladeburnerPopup) { + dialogBoxCreate(msg); + } } this.resetAction(); } diff --git a/src/Settings/Settings.ts b/src/Settings/Settings.ts index af7376174..ab0956d78 100644 --- a/src/Settings/Settings.ts +++ b/src/Settings/Settings.ts @@ -74,6 +74,11 @@ interface IDefaultSettings { * Whether the user should be asked to confirm travelling between cities. */ SuppressTravelConfirmation: boolean; + + /** + * Whether the user should be displayed a popup message when his Bladeburner actions are cancelled. + */ + SuppressBladeburnerPopup: boolean; } /** @@ -122,6 +127,7 @@ const defaultSettings: IDefaultSettings = { SuppressHospitalizationPopup: false, SuppressMessages: false, SuppressTravelConfirmation: false, + SuppressBladeburnerPopup: false, }; /** @@ -147,6 +153,7 @@ export const Settings: ISettings & ISelfInitializer & ISelfLoading = { SuppressHospitalizationPopup: defaultSettings.SuppressHospitalizationPopup, SuppressMessages: defaultSettings.SuppressMessages, SuppressTravelConfirmation: defaultSettings.SuppressTravelConfirmation, + SuppressBladeburnerPopup: defaultSettings.SuppressBladeburnerPopup, init() { Object.assign(Settings, defaultSettings); }, diff --git a/src/index.html b/src/index.html index c39ae82a0..fd7b0ad26 100644 --- a/src/index.html +++ b/src/index.html @@ -519,6 +519,16 @@ if (htmlWebpackPlugin.options.googleAnalytics.trackingId) { %> + +
+ + +
+