diff --git a/src/BitNode/ui/BitverseRoot.tsx b/src/BitNode/ui/BitverseRoot.tsx index b9ca56661..c9152ae33 100644 --- a/src/BitNode/ui/BitverseRoot.tsx +++ b/src/BitNode/ui/BitverseRoot.tsx @@ -2,7 +2,7 @@ import React, { useState } from "react"; import { SourceFileFlags } from "../../SourceFile/SourceFileFlags"; import { IRouter } from "../../ui/Router"; import { BitNodes } from "../BitNode"; -import { enterBitNode } from "../../RedPill"; +import { enterBitNode, setRedPillFlag } from "../../RedPill"; import { PortalPopup } from "./PortalPopup"; import { createPopup } from "../../ui/React/createPopup"; import { CinematicText } from "../../ui/React/CinematicText"; @@ -71,6 +71,7 @@ interface IProps { } export function BitverseRoot(props: IProps): React.ReactElement { + setRedPillFlag(true); const player = use.Player(); const enter = enterBitNode; const destroyed = player.bitNodeN; diff --git a/src/Message/MessageHelpers.js b/src/Message/MessageHelpers.js index 1b9a9be53..1dd9879bd 100644 --- a/src/Message/MessageHelpers.js +++ b/src/Message/MessageHelpers.js @@ -48,17 +48,18 @@ function addMessageToServer(msg, serverHostname) { //Checks if any of the 'timed' messages should be sent function checkForMessagesToSend() { - var jumper0 = Messages[MessageFilenames.Jumper0]; - var jumper1 = Messages[MessageFilenames.Jumper1]; - var jumper2 = Messages[MessageFilenames.Jumper2]; - var jumper3 = Messages[MessageFilenames.Jumper3]; - var jumper4 = Messages[MessageFilenames.Jumper4]; - var cybersecTest = Messages[MessageFilenames.CyberSecTest]; - var nitesecTest = Messages[MessageFilenames.NiteSecTest]; - var bitrunnersTest = Messages[MessageFilenames.BitRunnersTest]; - var redpill = Messages[MessageFilenames.RedPill]; + if (redPillFlag) return; + const jumper0 = Messages[MessageFilenames.Jumper0]; + const jumper1 = Messages[MessageFilenames.Jumper1]; + const jumper2 = Messages[MessageFilenames.Jumper2]; + const jumper3 = Messages[MessageFilenames.Jumper3]; + const jumper4 = Messages[MessageFilenames.Jumper4]; + const cybersecTest = Messages[MessageFilenames.CyberSecTest]; + const nitesecTest = Messages[MessageFilenames.NiteSecTest]; + const bitrunnersTest = Messages[MessageFilenames.BitRunnersTest]; + const redpill = Messages[MessageFilenames.RedPill]; - var redpillOwned = false; + const redpillOwned = false; if (Augmentations[AugmentationNames.TheRedPill].owned) { redpillOwned = true; } diff --git a/src/RedPill.d.ts b/src/RedPill.d.ts index d60d01977..b9909c1d1 100644 --- a/src/RedPill.d.ts +++ b/src/RedPill.d.ts @@ -1,2 +1,3 @@ export declare let redPillFlag: boolean; export declare function enterBitNode(router: IRouter, flume: boolean, destroyedBitNode: number, newBitNode: number); +export declare function setRedPillFlag(b: boolean): void; diff --git a/src/RedPill.jsx b/src/RedPill.jsx index ef4f685a1..768175910 100644 --- a/src/RedPill.jsx +++ b/src/RedPill.jsx @@ -9,7 +9,11 @@ import { SourceFiles } from "./SourceFile/SourceFiles"; import { dialogBoxCreate } from "../utils/DialogBox"; -let redPillFlag = false; +export let redPillFlag = false; + +export function setRedPillFlag(b) { + redPillFlag = b; +} function giveSourceFile(bitNodeNumber) { var sourceFileKey = "SourceFile" + bitNodeNumber.toString(); @@ -81,5 +85,3 @@ export function enterBitNode(router, flume, destroyedBitNode, newBitNode) { } prestigeSourceFile(flume); } - -export { redPillFlag }; diff --git a/src/SaveObject.jsx b/src/SaveObject.jsx index d8c06168b..fdc7c5893 100755 --- a/src/SaveObject.jsx +++ b/src/SaveObject.jsx @@ -3,8 +3,6 @@ import { Companies, loadCompanies } from "./Company/Companies"; import { CONSTANTS } from "./Constants"; import { Engine } from "./engine"; import { Factions, loadFactions } from "./Faction/Factions"; -import { loadFconf } from "./Fconf/Fconf"; -import { FconfSettings } from "./Fconf/FconfSettings"; import { loadAllGangs, AllGangs } from "./Gang/AllGangs"; import { loadMessages, initMessages, Messages } from "./Message/MessageHelpers"; import { Player, loadPlayer } from "./Player"; @@ -42,7 +40,6 @@ function BitburnerSaveObject() { this.MessagesSave = ""; this.StockMarketSave = ""; this.SettingsSave = ""; - this.FconfSettingsSave = ""; this.VersionSave = ""; this.AllGangsSave = ""; this.LastExportBonus = ""; @@ -74,7 +71,6 @@ BitburnerSaveObject.prototype.getSaveString = function () { this.MessagesSave = JSON.stringify(Messages); this.StockMarketSave = JSON.stringify(StockMarket); this.SettingsSave = JSON.stringify(Settings); - this.FconfSettingsSave = JSON.stringify(FconfSettings); this.VersionSave = JSON.stringify(CONSTANTS.Version); this.LastExportBonus = JSON.stringify(ExportBonus.LastExportBonus); if (Player.inGang()) { diff --git a/src/Script/RunningScript.ts b/src/Script/RunningScript.ts index cf5f9fac9..683b095be 100644 --- a/src/Script/RunningScript.ts +++ b/src/Script/RunningScript.ts @@ -75,7 +75,7 @@ export class RunningScript { } let logEntry = txt; - if (FconfSettings.ENABLE_TIMESTAMPS) { + if (Settings.EnableTimestamps) { logEntry = "[" + getTimestamp() + "] " + logEntry; } diff --git a/src/Settings/Settings.ts b/src/Settings/Settings.ts index 596bfaf89..99a168e6e 100644 --- a/src/Settings/Settings.ts +++ b/src/Settings/Settings.ts @@ -38,6 +38,16 @@ interface IDefaultSettings { */ DisableTextEffects: boolean; + /** + * Enable bash hotkeys + */ + EnableBashHotkeys: boolean; + + /** + * Enable timestamps + */ + EnableTimestamps: boolean; + /** * Locale used for display numbers */ @@ -116,6 +126,8 @@ const defaultSettings: IDefaultSettings = { DisableASCIIArt: false, DisableHotkeys: false, DisableTextEffects: false, + EnableBashHotkeys: false, + EnableTimestamps: false, Locale: "en", MaxLogCapacity: 50, MaxPortCapacity: 50, @@ -140,6 +152,8 @@ export const Settings: ISettings & ISelfInitializer & ISelfLoading = { DisableASCIIArt: defaultSettings.DisableASCIIArt, DisableHotkeys: defaultSettings.DisableHotkeys, DisableTextEffects: defaultSettings.DisableTextEffects, + EnableBashHotkeys: defaultSettings.EnableBashHotkeys, + EnableTimestamps: defaultSettings.EnableTimestamps, Locale: "en", MaxLogCapacity: defaultSettings.MaxLogCapacity, MaxPortCapacity: defaultSettings.MaxPortCapacity, diff --git a/src/Sidebar/ui/SidebarRoot.tsx b/src/Sidebar/ui/SidebarRoot.tsx index 8d648c6e6..4138a8522 100644 --- a/src/Sidebar/ui/SidebarRoot.tsx +++ b/src/Sidebar/ui/SidebarRoot.tsx @@ -52,7 +52,6 @@ import { redPillFlag } from "../../RedPill"; import { inMission } from "../../Missions"; import { KEY } from "../../../utils/helpers/keyCodes"; -import { FconfSettings } from "../../Fconf/FconfSettings"; const openedMixin = (theme: Theme): CSSObject => ({ width: theme.spacing(31), @@ -297,7 +296,7 @@ export function SidebarRoot(props: IProps): React.ReactElement { clickCreateProgram(); } else if (event.keyCode === KEY.F && event.altKey) { // Overriden by Fconf - if (props.page == Page.Terminal && FconfSettings.ENABLE_BASH_HOTKEYS) { + if (props.page == Page.Terminal && Settings.EnableBashHotkeys) { return; } event.preventDefault(); diff --git a/src/Terminal/ITerminal.ts b/src/Terminal/ITerminal.ts index c7c842605..7c8922706 100644 --- a/src/Terminal/ITerminal.ts +++ b/src/Terminal/ITerminal.ts @@ -2,6 +2,8 @@ import { TextFile } from "../TextFile"; 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"; export class Output { text: string; @@ -10,6 +12,7 @@ export class Output { text: string, color: "inherit" | "initial" | "primary" | "secondary" | "error" | "textPrimary" | "textSecondary" | undefined, ) { + if (Settings.EnableTimestamps) text = "[" + getTimestamp() + "] " + text; this.text = text; this.color = color; } @@ -18,6 +21,7 @@ export class Output { export class Link { hostname: string; constructor(hostname: string) { + if (Settings.EnableTimestamps) hostname = "[" + getTimestamp() + "] " + hostname; this.hostname = hostname; } } diff --git a/src/Terminal/ui/TerminalInput.tsx b/src/Terminal/ui/TerminalInput.tsx index 9dfc5b900..4c360a0b6 100644 --- a/src/Terminal/ui/TerminalInput.tsx +++ b/src/Terminal/ui/TerminalInput.tsx @@ -12,7 +12,7 @@ import { IRouter } from "../../ui/Router"; import { IPlayer } from "../../PersonObjects/IPlayer"; import { determineAllPossibilitiesForTabCompletion } from "../determineAllPossibilitiesForTabCompletion"; import { tabCompletion } from "../tabCompletion"; -import { FconfSettings } from "../../Fconf/FconfSettings"; +import { Settings } from "../../Settings/Settings"; const useStyles = makeStyles((theme: Theme) => createStyles({ @@ -230,11 +230,8 @@ export function TerminalInput({ terminal, router, player }: IProps): React.React } // Select previous command. - if ( - event.keyCode === KEY.UPARROW || - (FconfSettings.ENABLE_BASH_HOTKEYS && event.keyCode === KEY.P && event.ctrlKey) - ) { - if (FconfSettings.ENABLE_BASH_HOTKEYS) { + if (event.keyCode === KEY.UPARROW || (Settings.EnableBashHotkeys && event.keyCode === KEY.P && event.ctrlKey)) { + if (Settings.EnableBashHotkeys) { event.preventDefault(); } const i = terminal.commandHistoryIndex; @@ -261,11 +258,8 @@ export function TerminalInput({ terminal, router, player }: IProps): React.React } // Select next command - if ( - event.keyCode === KEY.DOWNARROW || - (FconfSettings.ENABLE_BASH_HOTKEYS && event.keyCode === KEY.M && event.ctrlKey) - ) { - if (FconfSettings.ENABLE_BASH_HOTKEYS) { + if (event.keyCode === KEY.DOWNARROW || (Settings.EnableBashHotkeys && event.keyCode === KEY.M && event.ctrlKey)) { + if (Settings.EnableBashHotkeys) { event.preventDefault(); } const i = terminal.commandHistoryIndex; @@ -290,7 +284,7 @@ export function TerminalInput({ terminal, router, player }: IProps): React.React } // Extra Bash Emulation Hotkeys, must be enabled through .fconf - if (FconfSettings.ENABLE_BASH_HOTKEYS) { + if (Settings.EnableBashHotkeys) { if (event.keyCode === KEY.A && event.ctrlKey) { event.preventDefault(); moveTextCursor("home"); diff --git a/src/index.tsx b/src/index.tsx index e0be26a7b..2cbaceb5c 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,7 +1,7 @@ import React from "react"; import ReactDOM from "react-dom"; -import { TTheme as Theme, colors } from "./ui/React/Theme"; +import { TTheme as Theme, ThemeEvents } from "./ui/React/Theme"; import { LoadingScreen } from "./ui/LoadingScreen"; import "./engineStyle"; @@ -12,13 +12,15 @@ ReactDOM.render( document.getElementById("mainmenu-container"), ); -// setTimeout(() => { -// colors.primary = "#fff"; -// refreshTheme(); -// ReactDOM.render( -// -// -// , -// document.getElementById("mainmenu-container"), -// ); -// }, 5000); +function rerender() { + ReactDOM.render( + + + , + document.getElementById("mainmenu-container"), + ); +} + +(function () { + ThemeEvents.subscribe(rerender); +})(); diff --git a/src/ui/React/GameOptionsRoot.tsx b/src/ui/React/GameOptionsRoot.tsx index 6d4fbd911..1fe4fcc55 100644 --- a/src/ui/React/GameOptionsRoot.tsx +++ b/src/ui/React/GameOptionsRoot.tsx @@ -74,6 +74,9 @@ export function GameOptionsRoot(props: IProps): React.ReactElement { const [disableHotkeys, setDisableHotkeys] = useState(Settings.DisableHotkeys); 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 [locale, setLocale] = useState(Settings.Locale); const [diagnosticOpen, setDiagnosticOpen] = useState(false); const [deleteGameOpen, setDeleteOpen] = useState(false); @@ -152,6 +155,15 @@ export function GameOptionsRoot(props: IProps): React.ReactElement { Settings.Locale = event.target.value as string; } + function handleEnableBashHotkeysChange(event: React.ChangeEvent): void { + setEnableBashHotkeys(event.target.checked); + Settings.EnableBashHotkeys = event.target.checked; + } + function handleEnableTimestampsChange(event: React.ChangeEvent): void { + setEnableTimestamps(event.target.checked); + Settings.EnableTimestamps = event.target.checked; + } + function startImport(): void { if (!window.File || !window.FileReader || !window.FileList || !window.Blob) return; const ii = importInput.current; @@ -454,6 +466,43 @@ export function GameOptionsRoot(props: IProps): React.ReactElement { } /> + + + } + label={ + + Improved Bash emulation mode. Setting this to 1 enables several new Terminal shortcuts and + features that more closely resemble a real Bash-style shell. Note that when this mode is + enabled, the default browser shortcuts are overriden by the new Bash shortcuts. + + } + > + Enable bash hotkeys + + } + /> + + + } + label={ + + Terminal commands and log entries will be timestamped. The timestamp will have the format: M/D + h:m + + } + > + Enable timestamps + + } + /> + + Sets the locale for displaying numbers.}> Locale  diff --git a/src/ui/React/Theme.tsx b/src/ui/React/Theme.tsx index da4c3ed4c..bcfdda8da 100644 --- a/src/ui/React/Theme.tsx +++ b/src/ui/React/Theme.tsx @@ -1,5 +1,8 @@ import React from "react"; import { createTheme, ThemeProvider, Theme, StyledEngineProvider } from "@mui/material/styles"; +import { EventEmitter } from "../../utils/EventEmitter"; + +export const ThemeEvents = new EventEmitter<[]>(); declare module "@mui/material/styles" { interface Theme {