diff --git a/src/GameOptions/ui/CurrentOptionsPage.tsx b/src/GameOptions/ui/CurrentOptionsPage.tsx deleted file mode 100644 index 171eaca17..000000000 --- a/src/GameOptions/ui/CurrentOptionsPage.tsx +++ /dev/null @@ -1,414 +0,0 @@ -import { MenuItem, Select, SelectChangeEvent, TextField, Tooltip, Typography, Link } from "@mui/material"; -import React, { useState } from "react"; -import { IPlayer } from "../../PersonObjects/IPlayer"; -import { isRemoteFileApiConnectionLive, newRemoteFileApiConnection } from "../../RemoteFileAPI/RemoteFileAPI"; -import { Settings } from "../../Settings/Settings"; -import { OptionSwitch } from "../../ui/React/OptionSwitch"; -import { formatTime } from "../../utils/helpers/formatTime"; -import { GameOptionsTab } from "../GameOptionsTab"; -import { GameOptionsPage } from "./GameOptionsPage"; -import { OptionsSlider } from "./OptionsSlider"; -import Button from "@mui/material/Button"; -import { ConnectionBauble } from "./ConnectionBauble"; - -interface IProps { - currentTab: GameOptionsTab; - player: IPlayer; -} - -export const CurrentOptionsPage = (props: IProps): React.ReactElement => { - const [execTime, setExecTime] = useState(Settings.CodeInstructionRunTime); - const [recentScriptsSize, setRecentScriptsSize] = useState(Settings.MaxRecentScriptsCapacity); - const [logSize, setLogSize] = useState(Settings.MaxLogCapacity); - const [portSize, setPortSize] = useState(Settings.MaxPortCapacity); - const [terminalSize, setTerminalSize] = useState(Settings.MaxTerminalCapacity); - const [autosaveInterval, setAutosaveInterval] = useState(Settings.AutosaveInterval); - const [timestampFormat, setTimestampFormat] = useState(Settings.TimestampsFormat); - const [remoteFileApiPort, setRemoteFileApiPort] = useState(Settings.RemoteFileApiPort); - const [locale, setLocale] = useState(Settings.Locale); - - function handleExecTimeChange( - _event: Event | React.SyntheticEvent, - newValue: number | number[], - ): void { - setExecTime(newValue as number); - Settings.CodeInstructionRunTime = newValue as number; - } - - function handleRecentScriptsSizeChange( - _event: Event | React.SyntheticEvent, - newValue: number | number[], - ): void { - setRecentScriptsSize(newValue as number); - Settings.MaxRecentScriptsCapacity = newValue as number; - } - - function handleLogSizeChange( - _event: Event | React.SyntheticEvent, - newValue: number | number[], - ): void { - setLogSize(newValue as number); - Settings.MaxLogCapacity = newValue as number; - } - - function handlePortSizeChange( - _event: Event | React.SyntheticEvent, - newValue: number | number[], - ): void { - setPortSize(newValue as number); - Settings.MaxPortCapacity = newValue as number; - } - - function handleTerminalSizeChange( - _event: Event | React.SyntheticEvent, - newValue: number | number[], - ): void { - setTerminalSize(newValue as number); - Settings.MaxTerminalCapacity = newValue as number; - } - - function handleAutosaveIntervalChange( - _event: Event | React.SyntheticEvent, - newValue: number | number[], - ): void { - setAutosaveInterval(newValue as number); - Settings.AutosaveInterval = newValue as number; - } - - function handleLocaleChange(event: SelectChangeEvent): void { - setLocale(event.target.value); - Settings.Locale = event.target.value; - } - - function handleTimestampFormatChange(event: React.ChangeEvent): void { - setTimestampFormat(event.target.value); - Settings.TimestampsFormat = event.target.value; - } - - function handleRemoteFileApiPortChange(event: React.ChangeEvent): void { - setRemoteFileApiPort(Number(event.target.value) as number); - Settings.RemoteFileApiPort = Number(event.target.value); - } - - const pages = { - [GameOptionsTab.SYSTEM]: ( - - {/* Wrap in a React fragment to prevent the sliders from breaking as list items */} - <> - - The minimum number of milliseconds it takes to execute an operation in Netscript. Setting this too low - can result in poor performance if you have many scripts running. - - } - /> - The maximum number of recently killed scripts the game will keep.} - /> - - The maximum number of lines a script's logs can hold. Setting this too high can cause the game to use a - lot of memory if you have many scripts running. - - } - /> - - The maximum number of entries that can be written to a port using Netscript's write() function. Setting - this too high can cause the game to use a lot of memory. - - } - /> - - The maximum number of entries that can be written to the terminal. Setting this too high can cause the - game to use a lot of memory. - - } - marks - /> - The time (in seconds) between each autosave. Set to 0 to disable autosave.} - marks - /> - - (Settings.SuppressSavedGameToast = newValue)} - text="Suppress Auto-Save Game Toast" - tooltip={<>If this is set, there will be no "Game Saved!" toast appearing after an auto-save.} - /> - (Settings.SuppressAutosaveDisabledWarnings = newValue)} - text="Suppress Auto-Save Disabled Warning" - tooltip={<>If this is set, there will be no warning triggered when auto-save is disabled (at 0).} - /> - (Settings.SaveGameOnFileSave = newValue)} - text="Save game on file save" - tooltip={<>Save your game any time a file is saved in the script editor.} - /> - (Settings.ExcludeRunningScriptsFromSave = newValue)} - text="Exclude Running Scripts from Save" - tooltip={ - <> - If this is set, the save file will exclude all running scripts. This is only useful if your save is - lagging a lot. You'll have to restart your script every time you launch the game. - - } - /> - - ), - [GameOptionsTab.INTERFACE]: ( - - (Settings.DisableASCIIArt = newValue)} - text="Disable ascii art" - tooltip={<>If this is set all ASCII art will be disabled.} - /> - (Settings.DisableTextEffects = newValue)} - text="Disable text effects" - tooltip={ - <> - If this is set, text effects will not be displayed. This can help if text is difficult to read in certain - areas. - - } - /> - (Settings.DisableOverviewProgressBars = newValue)} - text="Disable Overview Progress Bars" - tooltip={<>If this is set, the progress bars in the character overview will be hidden.} - /> - (Settings.UseIEC60027_2 = newValue)} - text="Use GiB instead of GB" - tooltip={ - <>If this is set all references to memory will use GiB instead of GB, in accordance with IEC 60027-2. - } - /> - - Terminal commands and log entries will be timestamped. See https://date-fns.org/docs/Getting-Started/ - - } - > - - Timestamp format: - - ), - }} - value={timestampFormat} - onChange={handleTimestampFormatChange} - placeholder="yyyy-MM-dd hh:mm:ss" - /> - - <> - Sets the locale for displaying numbers.}> - Locale - - - - - ), - [GameOptionsTab.GAMEPLAY]: ( - - (Settings.SuppressMessages = newValue)} - text="Suppress story messages" - tooltip={ - <> - If this is set, then any messages you receive will not appear as popups on the screen. They will still get - sent to your home computer as '.msg' files and can be viewed with the 'cat' Terminal command. - - } - /> - (Settings.SuppressFactionInvites = newValue)} - text="Suppress faction invites" - tooltip={ - <> - If this is set, then any faction invites you receive will not appear as popups on the screen. Your - outstanding faction invites can be viewed in the 'Factions' page. - - } - /> - (Settings.SuppressTravelConfirmation = newValue)} - text="Suppress travel confirmations" - tooltip={ - <> - If this is set, the confirmation message before traveling will not show up. You will automatically be - deducted the travel cost as soon as you click. - - } - /> - (Settings.SuppressBuyAugmentationConfirmation = newValue)} - text="Suppress augmentations confirmation" - tooltip={<>If this is set, the confirmation message before buying augmentation will not show up.} - /> - (Settings.SuppressTIXPopup = newValue)} - text="Suppress TIX messages" - tooltip={<>If this is set, the stock market will never create any popup.} - /> - {props.player.bladeburner && ( - (Settings.SuppressBladeburnerPopup = newValue)} - text="Suppress bladeburner popup" - tooltip={ - <> - If this is set, then having your Bladeburner actions interrupted by being busy with something else will - not display a popup message. - - } - /> - )} - - ), - [GameOptionsTab.MISC]: ( - - (Settings.DisableHotkeys = newValue)} - text="Disable hotkeys" - tooltip={ - <> - If this is set, then most hotkeys (keyboard shortcuts) in the game are disabled. This includes Terminal - commands, hotkeys to navigate between different parts of the game, and the "Save and Close (Ctrl + b)" - hotkey in the Text Editor. - - } - /> - (Settings.EnableBashHotkeys = newValue)} - text="Enable bash hotkeys" - tooltip={ - <> - 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. - - } - /> - - ), - [GameOptionsTab.REMOTE_API]: ( - - - These settings control the Remote API for bitburner. This is typically used to write scripts using an external - text editor and then upload files to the home server. - - - - Documentation - - - - - This port number is used to connect to a Remote API port, please ensure that it matches with your Remote - API server port. Set to 0 to disable the feature. - - } - > - 0 && remoteFileApiPort <= 65535 ? "success" : "error"}> - Port:  - - ), - endAdornment: , - }} - value={remoteFileApiPort} - onChange={handleRemoteFileApiPortChange} - placeholder="12525" - /> - - - ), - }; - - return pages[props.currentTab]; -}; diff --git a/src/GameOptions/ui/GameOptionsRoot.tsx b/src/GameOptions/ui/GameOptionsRoot.tsx index ee8097f92..da78eae2c 100644 --- a/src/GameOptions/ui/GameOptionsRoot.tsx +++ b/src/GameOptions/ui/GameOptionsRoot.tsx @@ -3,8 +3,12 @@ import React, { useState } from "react"; import { IPlayer } from "../../PersonObjects/IPlayer"; import { IRouter } from "../../ui/Router"; import { GameOptionsTab } from "../GameOptionsTab"; -import { CurrentOptionsPage } from "./CurrentOptionsPage"; import { GameOptionsSidebar } from "./GameOptionsSidebar"; +import { GameplayPage } from "./GameplayPage"; +import { InterfacePage } from "./InterfacePage"; +import { MiscPage } from "./MiscPage"; +import { RemoteAPIPage } from "./RemoteAPIPage"; +import { SystemPage } from "./SystemPage"; interface IProps { player: IPlayer; @@ -32,7 +36,11 @@ export function GameOptionsRoot(props: IProps): React.ReactElement { forceKill={props.forceKill} softReset={props.softReset} /> - + {currentTab === GameOptionsTab.SYSTEM && } + {currentTab === GameOptionsTab.INTERFACE && } + {currentTab === GameOptionsTab.GAMEPLAY && } + {currentTab === GameOptionsTab.MISC && } + {currentTab === GameOptionsTab.REMOTE_API && } ); diff --git a/src/GameOptions/ui/GameplayPage.tsx b/src/GameOptions/ui/GameplayPage.tsx new file mode 100644 index 000000000..f6492acfe --- /dev/null +++ b/src/GameOptions/ui/GameplayPage.tsx @@ -0,0 +1,71 @@ +import React from "react"; +import { OptionSwitch } from "../../ui/React/OptionSwitch"; +import { Settings } from "../../Settings/Settings"; +import { GameOptionsPage } from "./GameOptionsPage"; +import { use } from "../../ui/Context"; + +export const GameplayPage = (): React.ReactElement => { + const player = use.Player(); + return ( + + (Settings.SuppressMessages = newValue)} + text="Suppress story messages" + tooltip={ + <> + If this is set, then any messages you receive will not appear as popups on the screen. They will still get + sent to your home computer as '.msg' files and can be viewed with the 'cat' Terminal command. + + } + /> + (Settings.SuppressFactionInvites = newValue)} + text="Suppress faction invites" + tooltip={ + <> + If this is set, then any faction invites you receive will not appear as popups on the screen. Your + outstanding faction invites can be viewed in the 'Factions' page. + + } + /> + (Settings.SuppressTravelConfirmation = newValue)} + text="Suppress travel confirmations" + tooltip={ + <> + If this is set, the confirmation message before traveling will not show up. You will automatically be + deducted the travel cost as soon as you click. + + } + /> + (Settings.SuppressBuyAugmentationConfirmation = newValue)} + text="Suppress augmentations confirmation" + tooltip={<>If this is set, the confirmation message before buying augmentation will not show up.} + /> + (Settings.SuppressTIXPopup = newValue)} + text="Suppress TIX messages" + tooltip={<>If this is set, the stock market will never create any popup.} + /> + {player.bladeburner && ( + (Settings.SuppressBladeburnerPopup = newValue)} + text="Suppress bladeburner popup" + tooltip={ + <> + If this is set, then having your Bladeburner actions interrupted by being busy with something else will + not display a popup message. + + } + /> + )} + + ); +}; diff --git a/src/GameOptions/ui/InterfacePage.tsx b/src/GameOptions/ui/InterfacePage.tsx new file mode 100644 index 000000000..5af2e79e3 --- /dev/null +++ b/src/GameOptions/ui/InterfacePage.tsx @@ -0,0 +1,99 @@ +import React, { useState } from "react"; +import { MenuItem, Select, SelectChangeEvent, TextField, Tooltip, Typography } from "@mui/material"; +import { Settings } from "../../Settings/Settings"; +import { OptionSwitch } from "../../ui/React/OptionSwitch"; +import { GameOptionsPage } from "./GameOptionsPage"; +import { formatTime } from "../../utils/helpers/formatTime"; + +export const InterfacePage = (): React.ReactElement => { + const [timestampFormat, setTimestampFormat] = useState(Settings.TimestampsFormat); + const [locale, setLocale] = useState(Settings.Locale); + + function handleLocaleChange(event: SelectChangeEvent): void { + setLocale(event.target.value); + Settings.Locale = event.target.value; + } + function handleTimestampFormatChange(event: React.ChangeEvent): void { + setTimestampFormat(event.target.value); + Settings.TimestampsFormat = event.target.value; + } + return ( + + (Settings.DisableASCIIArt = newValue)} + text="Disable ascii art" + tooltip={<>If this is set all ASCII art will be disabled.} + /> + (Settings.DisableTextEffects = newValue)} + text="Disable text effects" + tooltip={ + <> + If this is set, text effects will not be displayed. This can help if text is difficult to read in certain + areas. + + } + /> + (Settings.DisableOverviewProgressBars = newValue)} + text="Disable Overview Progress Bars" + tooltip={<>If this is set, the progress bars in the character overview will be hidden.} + /> + (Settings.UseIEC60027_2 = newValue)} + text="Use GiB instead of GB" + tooltip={ + <>If this is set all references to memory will use GiB instead of GB, in accordance with IEC 60027-2. + } + /> + + Terminal commands and log entries will be timestamped. See https://date-fns.org/docs/Getting-Started/ + + } + > + + Timestamp format: + + ), + }} + value={timestampFormat} + onChange={handleTimestampFormatChange} + placeholder="yyyy-MM-dd hh:mm:ss" + /> + + <> + Sets the locale for displaying numbers.}> + Locale + + + + + ); +}; diff --git a/src/GameOptions/ui/MiscPage.tsx b/src/GameOptions/ui/MiscPage.tsx new file mode 100644 index 000000000..8a4b14789 --- /dev/null +++ b/src/GameOptions/ui/MiscPage.tsx @@ -0,0 +1,35 @@ +import React from "react"; +import { Settings } from "../../Settings/Settings"; +import { OptionSwitch } from "../../ui/React/OptionSwitch"; +import { GameOptionsPage } from "./GameOptionsPage"; + +export const MiscPage = (): React.ReactElement => { + return ( + + (Settings.DisableHotkeys = newValue)} + text="Disable hotkeys" + tooltip={ + <> + If this is set, then most hotkeys (keyboard shortcuts) in the game are disabled. This includes Terminal + commands, hotkeys to navigate between different parts of the game, and the "Save and Close (Ctrl + b)" + hotkey in the Text Editor. + + } + /> + (Settings.EnableBashHotkeys = newValue)} + text="Enable bash hotkeys" + tooltip={ + <> + 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. + + } + /> + + ); +}; diff --git a/src/GameOptions/ui/RemoteAPIPage.tsx b/src/GameOptions/ui/RemoteAPIPage.tsx new file mode 100644 index 000000000..500187fe4 --- /dev/null +++ b/src/GameOptions/ui/RemoteAPIPage.tsx @@ -0,0 +1,52 @@ +import React, { useState } from "react"; +import { Button, Link, TextField, Tooltip, Typography } from "@mui/material"; +import { GameOptionsPage } from "./GameOptionsPage"; +import { Settings } from "../../Settings/Settings"; +import { ConnectionBauble } from "./ConnectionBauble"; +import { isRemoteFileApiConnectionLive, newRemoteFileApiConnection } from "../../RemoteFileAPI/RemoteFileAPI"; + +export const RemoteAPIPage = (): React.ReactElement => { + const [remoteFileApiPort, setRemoteFileApiPort] = useState(Settings.RemoteFileApiPort); + + function handleRemoteFileApiPortChange(event: React.ChangeEvent): void { + setRemoteFileApiPort(Number(event.target.value) as number); + Settings.RemoteFileApiPort = Number(event.target.value); + } + + return ( + + + These settings control the Remote API for bitburner. This is typically used to write scripts using an external + text editor and then upload files to the home server. + + + + Documentation + + + + + This port number is used to connect to a Remote API port, please ensure that it matches with your Remote API + server port. Set to 0 to disable the feature. + + } + > + 0 && remoteFileApiPort <= 65535 ? "success" : "error"}> + Port:  + + ), + endAdornment: , + }} + value={remoteFileApiPort} + onChange={handleRemoteFileApiPortChange} + placeholder="12525" + /> + + + ); +}; diff --git a/src/GameOptions/ui/SystemPage.tsx b/src/GameOptions/ui/SystemPage.tsx new file mode 100644 index 000000000..d36e9936a --- /dev/null +++ b/src/GameOptions/ui/SystemPage.tsx @@ -0,0 +1,174 @@ +import React, { useState } from "react"; +import { Settings } from "../../Settings/Settings"; +import { GameOptionsPage } from "./GameOptionsPage"; +import { OptionsSlider } from "./OptionsSlider"; +import { OptionSwitch } from "../../ui/React/OptionSwitch"; + +export const SystemPage = (): React.ReactElement => { + const [execTime, setExecTime] = useState(Settings.CodeInstructionRunTime); + const [recentScriptsSize, setRecentScriptsSize] = useState(Settings.MaxRecentScriptsCapacity); + const [logSize, setLogSize] = useState(Settings.MaxLogCapacity); + const [portSize, setPortSize] = useState(Settings.MaxPortCapacity); + const [terminalSize, setTerminalSize] = useState(Settings.MaxTerminalCapacity); + const [autosaveInterval, setAutosaveInterval] = useState(Settings.AutosaveInterval); + + function handlePortSizeChange( + _event: Event | React.SyntheticEvent, + newValue: number | number[], + ): void { + setPortSize(newValue as number); + Settings.MaxPortCapacity = newValue as number; + } + + function handleTerminalSizeChange( + _event: Event | React.SyntheticEvent, + newValue: number | number[], + ): void { + setTerminalSize(newValue as number); + Settings.MaxTerminalCapacity = newValue as number; + } + + function handleExecTimeChange( + _event: Event | React.SyntheticEvent, + newValue: number | number[], + ): void { + setExecTime(newValue as number); + Settings.CodeInstructionRunTime = newValue as number; + } + + function handleRecentScriptsSizeChange( + _event: Event | React.SyntheticEvent, + newValue: number | number[], + ): void { + setRecentScriptsSize(newValue as number); + Settings.MaxRecentScriptsCapacity = newValue as number; + } + + function handleLogSizeChange( + _event: Event | React.SyntheticEvent, + newValue: number | number[], + ): void { + setLogSize(newValue as number); + Settings.MaxLogCapacity = newValue as number; + } + + function handleAutosaveIntervalChange( + _event: Event | React.SyntheticEvent, + newValue: number | number[], + ): void { + setAutosaveInterval(newValue as number); + Settings.AutosaveInterval = newValue as number; + } + return ( + + {/* Wrap in a React fragment to prevent the sliders from breaking as list items */} + <> + + The minimum number of milliseconds it takes to execute an operation in Netscript. Setting this too low can + result in poor performance if you have many scripts running. + + } + /> + The maximum number of recently killed scripts the game will keep.} + /> + + The maximum number of lines a script's logs can hold. Setting this too high can cause the game to use a + lot of memory if you have many scripts running. + + } + /> + + The maximum number of entries that can be written to a port using Netscript's write() function. Setting + this too high can cause the game to use a lot of memory. + + } + /> + + The maximum number of entries that can be written to the terminal. Setting this too high can cause the + game to use a lot of memory. + + } + marks + /> + The time (in seconds) between each autosave. Set to 0 to disable autosave.} + marks + /> + + (Settings.SuppressSavedGameToast = newValue)} + text="Suppress Auto-Save Game Toast" + tooltip={<>If this is set, there will be no "Game Saved!" toast appearing after an auto-save.} + /> + (Settings.SuppressAutosaveDisabledWarnings = newValue)} + text="Suppress Auto-Save Disabled Warning" + tooltip={<>If this is set, there will be no warning triggered when auto-save is disabled (at 0).} + /> + (Settings.SaveGameOnFileSave = newValue)} + text="Save game on file save" + tooltip={<>Save your game any time a file is saved in the script editor.} + /> + (Settings.ExcludeRunningScriptsFromSave = newValue)} + text="Exclude Running Scripts from Save" + tooltip={ + <> + If this is set, the save file will exclude all running scripts. This is only useful if your save is lagging + a lot. You'll have to restart your script every time you launch the game. + + } + /> + + ); +}; diff --git a/src/RemoteFileAPI/RemoteFileAPI.ts b/src/RemoteFileAPI/RemoteFileAPI.ts index c55ed6bfd..82c82a462 100644 --- a/src/RemoteFileAPI/RemoteFileAPI.ts +++ b/src/RemoteFileAPI/RemoteFileAPI.ts @@ -5,10 +5,11 @@ let server: Remote; export function newRemoteFileApiConnection(): void { if (server) server.stopConnection(); + if (Settings.RemoteFileApiPort === 0) return; server = new Remote("localhost", Settings.RemoteFileApiPort); server.startConnection(); } export function isRemoteFileApiConnectionLive(): boolean { - return server.connection != undefined && server.connection.readyState == 1; + return server && server.connection != undefined && server.connection.readyState == 1; }