rework options menu

This commit is contained in:
Olivier Gagnon 2021-09-14 21:05:49 -04:00
parent f895da118d
commit dc9b5c3341
8 changed files with 618 additions and 342 deletions

@ -40,12 +40,7 @@ export function CodingContracts(): React.ReactElement {
</tr> </tr>
<tr> <tr>
<td> <td>
<Select <Select onChange={setCodingcontractDropdown} value={codingcontract}>
id="contract-types-dropdown"
className="dropdown"
onChange={setCodingcontractDropdown}
value={codingcontract}
>
{Object.values(CodingContractTypes).map((cc) => ( {Object.values(CodingContractTypes).map((cc) => (
<MenuItem key={cc.name} value={cc.name}> <MenuItem key={cc.name} value={cc.name}>
{cc.name} {cc.name}

@ -29,4 +29,5 @@ export interface IEngine {
loadInfiltrationContent: (name: string, difficulty: number, maxLevel: number) => void; loadInfiltrationContent: (name: string, difficulty: number, maxLevel: number) => void;
loadMissionContent: () => void; loadMissionContent: () => void;
loadResleevingContent: () => void; loadResleevingContent: () => void;
loadGameOptionsContent: () => void;
} }

@ -254,6 +254,10 @@ export function SidebarRoot(props: IProps): React.ReactElement {
setActiveTab("Milestones"); setActiveTab("Milestones");
props.engine.loadMilestonesContent(); props.engine.loadMilestonesContent();
} }
function clickOptions(): void {
setActiveTab("Options");
props.engine.loadGameOptionsContent();
}
function clickDev(): void { function clickDev(): void {
setActiveTab("Dev"); setActiveTab("Dev");
@ -355,7 +359,7 @@ export function SidebarRoot(props: IProps): React.ReactElement {
> >
<ListItem button onClick={toggleDrawer}> <ListItem button onClick={toggleDrawer}>
<ListItemIcon>{!open ? <ChevronRightIcon /> : <ChevronLeftIcon />}</ListItemIcon> <ListItemIcon>{!open ? <ChevronRightIcon /> : <ChevronLeftIcon />}</ListItemIcon>
<ListItemText primary={<Typography color="primary">Bitburner {CONSTANTS.Version}</Typography>} /> <ListItemText primary={<Typography color="primary">Bitburner v{CONSTANTS.Version}</Typography>} />
</ListItem> </ListItem>
<Divider /> <Divider />
<List> <List>
@ -711,20 +715,21 @@ export function SidebarRoot(props: IProps): React.ReactElement {
</Typography> </Typography>
</ListItemText> </ListItemText>
</ListItem> </ListItem>
{/*<ListItem <ListItem
button button
key={"Options"} key={"Options"}
className={clsx({ className={clsx({
[classes.active]: activeTab === "Options", [classes.active]: activeTab === "Options",
})} })}
onClick={clickOptions}
> >
<ListItemIcon> <ListItemIcon>
<SettingsIcon color={activeTab !== "Options" ? "secondary" : "primary"} /> <SettingsIcon color={activeTab !== "Options" ? "secondary" : "primary"} />
</ListItemIcon> </ListItemIcon>
<ListItemText> <ListItemText>
<Typography color={activeTab !== "Options" ? "secondary" : "primary"}>options</Typography> <Typography color={activeTab !== "Options" ? "secondary" : "primary"}>Options</Typography>
</ListItemText> </ListItemText>
</ListItem>*/} </ListItem>
{process.env.NODE_ENV === "development" && ( {process.env.NODE_ENV === "development" && (
<ListItem <ListItem
button button

@ -26,6 +26,7 @@ import { SidebarRoot } from "./Sidebar/ui/SidebarRoot";
import { CorporationRoot } from "./Corporation/ui/CorporationRoot"; import { CorporationRoot } from "./Corporation/ui/CorporationRoot";
import { ResleeveRoot } from "./PersonObjects/Resleeving/ui/ResleeveRoot"; import { ResleeveRoot } from "./PersonObjects/Resleeving/ui/ResleeveRoot";
import { GameOptionsRoot } from "./ui/React/GameOptionsRoot"; import { GameOptionsRoot } from "./ui/React/GameOptionsRoot";
import { Theme } from "./ui/React/Theme";
import { SleeveRoot } from "./PersonObjects/Sleeve/ui/SleeveRoot"; import { SleeveRoot } from "./PersonObjects/Sleeve/ui/SleeveRoot";
import { displayInfiltrationContent } from "./Infiltration/Helper"; import { displayInfiltrationContent } from "./Infiltration/Helper";
import { import {
@ -360,7 +361,28 @@ const Engine = {
routing.navigateTo(Page.GameOptions); routing.navigateTo(Page.GameOptions);
Engine.Display.content.style.display = "block"; Engine.Display.content.style.display = "block";
MainMenuLinks.City.classList.add("active"); MainMenuLinks.City.classList.add("active");
ReactDOM.render(<GameOptionsRoot />, Engine.Display.content); ReactDOM.render(
<Theme>
<GameOptionsRoot
player={Player}
save={() => saveObject.saveGame(Engine.indexedDb)}
delete={() => saveObject.deleteGame(Engine.indexedDb)}
export={() => saveObject.exportGame()}
import={() => saveObject.importGame()}
forceKill={() => {
for (const hostname of Object.keys(AllServers)) {
AllServers[hostname].runningScripts = [];
}
dialogBoxCreate("Forcefully deleted all running scripts. Please save and refresh page.");
}}
softReset={() => {
dialogBoxCreate("Soft Reset!");
prestigeAugmentation();
}}
/>
</Theme>,
Engine.Display.content,
);
}, },
// Helper function that hides all content // Helper function that hides all content

@ -1,337 +1,521 @@
import React from "react"; import React, { useState } from "react";
interface IProps {} import { IPlayer } from "../../PersonObjects/IPlayer";
import { makeStyles, createStyles, Theme } from "@material-ui/core/styles";
import Typography from "@material-ui/core/Typography";
import Slider from "@material-ui/core/Slider";
import Grid from "@material-ui/core/Grid";
import FormControlLabel from "@material-ui/core/FormControlLabel";
import Switch from "@material-ui/core/Switch";
import Select from "@material-ui/core/Select";
import MenuItem from "@material-ui/core/MenuItem";
import Button from "@material-ui/core/Button";
import Box from "@material-ui/core/Box";
import List from "@material-ui/core/List";
import ListItem from "@material-ui/core/ListItem";
import Link from "@material-ui/core/Link";
import Tooltip from "@material-ui/core/Tooltip";
import { Modal } from "../../ui/React/Modal";
import { FileDiagnosticPopup } from "../../Diagnostic/FileDiagnosticPopup";
import { Settings } from "../../Settings/Settings";
const useStyles = makeStyles((theme: Theme) =>
createStyles({
root: {
width: theme.spacing(50),
padding: theme.spacing(2),
userSelect: "none",
},
pad: {
padding: theme.spacing(2),
},
}),
);
interface IProps {
player: IPlayer;
save: () => void;
delete: () => void;
export: () => void;
import: () => void;
forceKill: () => void;
softReset: () => void;
}
export function GameOptionsRoot(props: IProps): React.ReactElement { export function GameOptionsRoot(props: IProps): React.ReactElement {
return ( const classes = useStyles();
<>
<h1>Game Options</h1> const [execTime, setExecTime] = useState(Settings.CodeInstructionRunTime);
</> const [logSize, setLogSize] = useState(Settings.MaxLogCapacity);
const [portSize, setPortSize] = useState(Settings.MaxPortCapacity);
const [autosaveInterval, setAutosaveInterval] = useState(Settings.AutosaveInterval);
const [suppressMessages, setSuppressMessages] = useState(Settings.SuppressMessages);
const [suppressFactionInvites, setSuppressFactionInvites] = useState(Settings.SuppressFactionInvites);
const [suppressTravelConfirmations, setSuppressTravelConfirmations] = useState(Settings.SuppressTravelConfirmation);
const [suppressBuyAugmentationConfirmation, setSuppressBuyAugmentationConfirmation] = useState(
Settings.SuppressBuyAugmentationConfirmation,
);
const [suppressHospitalizationPopup, setSuppressHospitalizationPopup] = useState(
Settings.SuppressHospitalizationPopup,
); );
/*
<h1>Game Options</h1> const [suppressBladeburnerPopup, setSuppressBladeburnerPopup] = useState(Settings.SuppressBladeburnerPopup);
<br />
<div id="game-options-left-panel">
<!-- Netscript execution time -->
<fieldset>
<label for="settingsNSExecTimeRangeVal" class="tooltip"
>Netscript exec time:&nbsp;
<span class="tooltiptext">
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 default value is 25ms.
</span>
</label>
<input const [disableHotkeys, setDisableHotkeys] = useState(Settings.DisableHotkeys);
class="optionRange" const [disableASCIIArt, setDisableASCIIArt] = useState(Settings.DisableASCIIArt);
type="range" const [disableTextEffects, setDisableTextEffects] = useState(Settings.DisableTextEffects);
max="100" const [locale, setLocale] = useState(Settings.Locale);
min="10" const [diagnosticOpen, setDiagnosticOpen] = useState(false);
step="1"
name="settingsNSExecTimeRangeVal" function handleExecTimeChange(event: any, newValue: number | number[]): void {
id="settingsNSExecTimeRangeVal" setExecTime(newValue as number);
value="25" Settings.CodeInstructionRunTime = newValue as number;
}
function handleLogSizeChange(event: any, newValue: number | number[]): void {
setLogSize(newValue as number);
Settings.MaxLogCapacity = newValue as number;
}
function handlePortSizeChange(event: any, newValue: number | number[]): void {
setPortSize(newValue as number);
Settings.MaxPortCapacity = newValue as number;
}
function handleAutosaveIntervalChange(event: any, newValue: number | number[]): void {
setAutosaveInterval(newValue as number);
Settings.AutosaveInterval = newValue as number;
}
function handleSuppressMessagesChange(event: React.ChangeEvent<HTMLInputElement>): void {
setSuppressMessages(event.target.checked);
Settings.SuppressMessages = event.target.checked;
}
function handleSuppressFactionInvitesChange(event: React.ChangeEvent<HTMLInputElement>): void {
setSuppressFactionInvites(event.target.checked);
Settings.SuppressFactionInvites = event.target.checked;
}
function handleSuppressTravelConfirmationsChange(event: React.ChangeEvent<HTMLInputElement>): void {
setSuppressTravelConfirmations(event.target.checked);
Settings.SuppressTravelConfirmation = event.target.checked;
}
function handleSuppressBuyAugmentationConfirmationChange(event: React.ChangeEvent<HTMLInputElement>): void {
setSuppressBuyAugmentationConfirmation(event.target.checked);
Settings.SuppressBuyAugmentationConfirmation = event.target.checked;
}
function handleSuppressHospitalizationPopupChange(event: React.ChangeEvent<HTMLInputElement>): void {
setSuppressHospitalizationPopup(event.target.checked);
Settings.SuppressHospitalizationPopup = event.target.checked;
}
function handleSuppressBladeburnerPopupChange(event: React.ChangeEvent<HTMLInputElement>): void {
setSuppressBladeburnerPopup(event.target.checked);
Settings.SuppressBladeburnerPopup = event.target.checked;
}
function handleDisableHotkeysChange(event: React.ChangeEvent<HTMLInputElement>): void {
setDisableHotkeys(event.target.checked);
Settings.DisableHotkeys = event.target.checked;
}
function handleDisableASCIIArtChange(event: React.ChangeEvent<HTMLInputElement>): void {
setDisableASCIIArt(event.target.checked);
Settings.DisableASCIIArt = event.target.checked;
}
function handleDisableTextEffectsChange(event: React.ChangeEvent<HTMLInputElement>): void {
setDisableTextEffects(event.target.checked);
Settings.DisableTextEffects = event.target.checked;
}
function handleLocaleChange(event: React.ChangeEvent<{ value: unknown }>): void {
setLocale(event.target.value as string);
Settings.Locale = event.target.value as string;
}
return (
<div className={classes.root} style={{ width: "90%" }}>
<Typography variant="h4" gutterBottom>
Options
</Typography>
<Grid container spacing={3}>
<Grid item xs={12} sm={6}>
<List>
<ListItem>
<Tooltip
title={
<Typography>
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.
</Typography>
}
>
<Typography>Netscript exec time (ms)</Typography>
</Tooltip>
<Slider
value={execTime}
onChange={handleExecTimeChange}
step={1}
min={10}
max={100}
valueLabelDisplay="auto"
/> />
<em id="settingsNSExecTimeRangeValLabel" style="font-style: normal"></em> </ListItem>
</fieldset> <ListItem>
<Tooltip
<!-- Log capacity --> title={
<fieldset> <Typography>
<label for="settingsNSLogRangeVal" class="tooltip" The maximum number of lines a script's logs can hold. Setting this too high can cause the game to
>Netscript log size:&nbsp;&nbsp; use a lot of memory if you have many scripts running.
<span class="tooltiptext"> </Typography>
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 default value is 50. >
</span> <Typography>Netscript log size</Typography>
</label> </Tooltip>
<Slider
<input value={logSize}
class="optionRange" onChange={handleLogSizeChange}
type="range" step={1}
max="100" min={20}
min="20" max={100}
step="1" valueLabelDisplay="auto"
name="settingsNSLogRangeVal"
id="settingsNSLogRangeVal"
value="50"
/> />
<em id="settingsNSLogRangeValLabel" style="font-style: normal"></em> </ListItem>
</fieldset> <ListItem>
<Tooltip
<!-- Port capacity --> title={
<fieldset> <Typography>
<label for="settingsNSPortRangeVal" class="tooltip"
>Netscript port size:&nbsp;
<span class="tooltiptext">
The maximum number of entries that can be written to a port using Netscript's write() function. 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 default value is 50. Setting this too high can cause the game to use a lot of memory.
</span> </Typography>
</label> }
>
<input <Typography>Netscript port size</Typography>
class="optionRange" </Tooltip>
type="range" <Slider
max="100" value={portSize}
min="20" onChange={handlePortSizeChange}
step="1" step={1}
name="settingsNSPortRangeVal" min={20}
id="settingsNSPortRangeVal" max={100}
value="50" valueLabelDisplay="auto"
/> />
<em id="settingsNSPortRangeValLabel" style="font-style: normal"></em> </ListItem>
</fieldset> <ListItem>
<Tooltip
<!-- Autosave Interval --> title={
<fieldset> <Typography>The time (in seconds) between each autosave. Set to 0 to disable autosave.</Typography>
<label for="settingsAutosaveIntervalVal" class="tooltip" }
>Autosave Interval:&nbsp;&nbsp;&nbsp; >
<span class="tooltiptext"> <Typography>Autosave interval (s)</Typography>
The time (in seconds) between each autosave. Set to 0 to disable autosave. </Tooltip>
</span> <Slider
</label> value={autosaveInterval}
onChange={handleAutosaveIntervalChange}
<input step={30}
class="optionRange" min={0}
type="range" max={600}
max="600" valueLabelDisplay="auto"
min="0" marks
step="1"
name="settingsAutosaveIntervalVal"
id="settingsAutosaveIntervalVal"
value="60"
/> />
<em id="settingsAutosaveIntervalValLabel" style="font-style: normal"></em> </ListItem>
</fieldset> <ListItem>
<FormControlLabel
<!-- Suppress messages --> control={<Switch color="primary" checked={suppressMessages} onChange={handleSuppressMessagesChange} />}
<fieldset> label={
<label for="settingsSuppressMessages" class="tooltip" <Tooltip
>Suppress Messages: title={
<span class="tooltiptext"> <Typography>
If this is set, then any messages you receive will not appear as popups on the screen. They will still If this is set, then any messages you receive will not appear as popups on the screen. They will
get sent to your home computer as '.msg' files and can be viewed with the 'cat' Terminal command. still get sent to your home computer as '.msg' files and can be viewed with the 'cat' Terminal
</span> command.
</label> </Typography>
<input }
class="optionCheckbox" >
type="checkbox" <Typography>Supress messages</Typography>
name="settingsSuppressMessages" </Tooltip>
id="settingsSuppressMessages" }
/> />
</fieldset> </ListItem>
<ListItem>
<!-- Suppress faction invites --> <FormControlLabel
<fieldset> control={
<label for="settingsSuppressFactionInvites" class="tooltip" <Switch
>Suppress Faction Invites: color="primary"
<span class="tooltiptexthigh"> checked={suppressFactionInvites}
If this is set, then any faction invites you receive will not appear as popups on the screen. Your onChange={handleSuppressFactionInvitesChange}
outstanding faction invites can be viewed in the 'Factions' page.
</span>
</label>
<input
class="optionCheckbox"
type="checkbox"
name="settingsSuppressFactionInvites"
id="settingsSuppressFactionInvites"
/> />
</fieldset> }
label={
<!-- Suppress travel confirmation --> <Tooltip
<fieldset> title={
<label for="settingsSuppressTravelConfirmation" class="tooltip" <Typography>
>Suppress Travel Confirmation: If this is set, then any faction invites you receive will not appear as popups on the screen.
<span class="tooltiptexthigh"> Your outstanding faction invites can be viewed in the 'Factions' page.
If this is set, the confirmation message before traveling will not show up. You will automatically be </Typography>
deducted the travel cost as soon as you click. }
</span> >
</label> <Typography>Supress faction invites</Typography>
<input </Tooltip>
class="optionCheckbox" }
type="checkbox"
name="settingsSuppressTravelConfirmation"
id="settingsSuppressTravelConfirmation"
/> />
</fieldset> </ListItem>
<ListItem>
<!-- Suppress buy aug confirmation --> <FormControlLabel
<fieldset> control={
<label for="settingsSuppressBuyAugmentationConfirmation" class="tooltip" <Switch
>Suppress buy augmentation confirmation: color="primary"
<span class="tooltiptexthigh"> checked={suppressTravelConfirmations}
onChange={handleSuppressTravelConfirmationsChange}
/>
}
label={
<Tooltip
title={
<Typography>
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.
</Typography>
}
>
<Typography>Supress travel confirmations</Typography>
</Tooltip>
}
/>
</ListItem>
<ListItem>
<FormControlLabel
control={
<Switch
color="primary"
checked={suppressBuyAugmentationConfirmation}
onChange={handleSuppressBuyAugmentationConfirmationChange}
/>
}
label={
<Tooltip
title={
<Typography>
If this is set, the confirmation message before buying augmentation will not show up. If this is set, the confirmation message before buying augmentation will not show up.
</span> </Typography>
</label> }
<input >
class="optionCheckbox" <Typography>Supress buy augmentation confirmation</Typography>
type="checkbox" </Tooltip>
name="settingsSuppressBuyAugmentationConfirmation" }
id="settingsSuppressBuyAugmentationConfirmation"
/> />
</fieldset> </ListItem>
<ListItem>
<!-- Hospitalization Popup --> <FormControlLabel
<fieldset> control={
<label for="settingsSuppressHospitalizationPopup" class="tooltip" <Switch
>Suppress Hospitalization popup: color="primary"
<span class="tooltiptexthigh"> checked={suppressHospitalizationPopup}
If this is set, a popup message will no longer be shown when you are hospitalized after taking too onChange={handleSuppressHospitalizationPopupChange}
much damage.
</span>
</label>
<input
class="optionCheckbox"
type="checkbox"
name="settingsSuppressHospitalizationPopup"
id="settingsSuppressHospitalizationPopup"
/> />
</fieldset> }
label={
<!-- Suppress Bladeburner popups --> <Tooltip
<fieldset> title={
<label for="settingsSuppressBladeburnerPopup" class="tooltip" <Typography>
>Suppress Bladeburner Popup: If this is set, a popup message will no longer be shown when you are hospitalized after taking
<span class="tooltiptext"> too much damage.
If this is set, then having your Bladeburner actions interrupted by being busy with something else </Typography>
will not display a popup message. }
</span> >
</label> <Typography>Supress hospitalization popup</Typography>
<input </Tooltip>
class="optionCheckbox" }
type="checkbox"
name="settingsSuppressBladeburnerPopup"
id="settingsSuppressBladeburnerPopup"
/> />
</fieldset> </ListItem>
{!!props.player.bladeburner && (
<!-- Disable Terminal and Navigation Shortcuts --> <ListItem>
<fieldset> <FormControlLabel
<label for="settingsDisableHotkeys" class="tooltip" control={
>Disable Hotkeys: <Switch
<span class="tooltiptexthigh"> color="primary"
checked={suppressBladeburnerPopup}
onChange={handleSuppressBladeburnerPopupChange}
/>
}
label={
<Tooltip
title={
<Typography>
If this is set, then having your Bladeburner actions interrupted by being busy with something
else will not display a popup message.
</Typography>
}
>
<Typography>Supress bladeburner popup</Typography>
</Tooltip>
}
/>
</ListItem>
)}
<ListItem>
<FormControlLabel
control={<Switch color="primary" checked={disableHotkeys} onChange={handleDisableHotkeysChange} />}
label={
<Tooltip
title={
<Typography>
If this is set, then most hotkeys (keyboard shortcuts) in the game are disabled. This includes 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 Terminal commands, hotkeys to navigate between different parts of the game, and the "Save and
(Ctrl + b)" hotkey in the Text Editor. Close (Ctrl + b)" hotkey in the Text Editor.
</span> </Typography>
</label> }
<input class="optionCheckbox" type="checkbox" name="settingsDisableHotkeys" id="settingsDisableHotkeys" /> >
</fieldset> <Typography>Disable hotkeys</Typography>
</Tooltip>
<!-- View city as list of buttons instead of ASCII art. --> }
<fieldset>
<label for="settingsDisableASCIIArt" class="tooltip"
>Disable ASCII art:
<span class="tooltiptexthigh"> If this is set all ASCII art will be disabled. </span>
</label>
<input
class="optionCheckbox"
type="checkbox"
name="settingsDisableASCIIArt"
id="settingsDisableASCIIArt"
/> />
</fieldset> </ListItem>
<ListItem>
<!-- Disable text effects such as corruption. --> <FormControlLabel
<fieldset> control={<Switch color="primary" checked={disableASCIIArt} onChange={handleDisableASCIIArtChange} />}
<label for="settingsDisableTextEffects" class="tooltip" label={
>Disable Text Effects: <Tooltip title={<Typography>If this is set all ASCII art will be disabled.</Typography>}>
<span class="tooltiptexthigh"> <Typography>Disable ascii art</Typography>
If this is set, text effects will not be displayed. This can help if text is difficult to read in </Tooltip>
certain areas. }
</span>
</label>
<input
class="optionCheckbox"
type="checkbox"
name="settingsDisableTextEffects"
id="settingsDisableTextEffects"
/> />
</fieldset> </ListItem>
<ListItem>
<!-- Locale for displaying numbers --> <FormControlLabel
<fieldset> control={
<label for="settingsLocale" class="tooltip" <Switch color="primary" checked={disableTextEffects} onChange={handleDisableTextEffectsChange} />
>Locale: }
<span class="tooltiptexthigh"> Sets the locale for displaying numbers. Defaults to 'en' </span> label={
</label> <Tooltip
<select name="settingsLocale" id="settingsLocale" class="dropdown"> title={
<option value="en">en</option> <Typography>
<option value="bg">bg</option> If this is set, text effects will not be displayed. This can help if text is difficult to read
<option value="cs">cs</option> in certain areas.
<option value="da-dk">da-dk</option> </Typography>
<option value="de">de</option> }
<option value="en-au">en-au</option> >
<option value="en-gb">en-gb</option> <Typography>Disable text effects</Typography>
<option value="es">es</option> </Tooltip>
<option value="fr">fr</option> }
<option value="hu">hu</option> />
<option value="it">it</option> </ListItem>
<option value="lv">lv</option> <ListItem>
<option value="no">no</option> <Tooltip title={<Typography>Sets the locale for displaying numbers.</Typography>}>
<option value="pl">pl</option> <Typography>Locale&nbsp;</Typography>
<option value="ru">ru</option> </Tooltip>
</select> <Select value={locale} onChange={handleLocaleChange}>
</fieldset> <MenuItem value="en">en</MenuItem>
<MenuItem value="bg">bg</MenuItem>
<!-- Donate button --> <MenuItem value="cs">cs</MenuItem>
<MenuItem value="da-dk">da-dk</MenuItem>
<MenuItem value="de">de</MenuItem>
<MenuItem value="en-au">en-au</MenuItem>
<MenuItem value="en-gb">en-gb</MenuItem>
<MenuItem value="es">es</MenuItem>
<MenuItem value="fr">fr</MenuItem>
<MenuItem value="hu">hu</MenuItem>
<MenuItem value="it">it</MenuItem>
<MenuItem value="lv">lv</MenuItem>
<MenuItem value="no">no</MenuItem>
<MenuItem value="pl">pl</MenuItem>
<MenuItem value="ru">ru</MenuItem>
</Select>
</ListItem>
</List>
<br />
<br />
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_blank"> <form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_blank">
<input type="hidden" name="cmd" value="_s-xclick" /> <input type="hidden" name="cmd" value="_s-xclick" />
<input <input
type="hidden" type="hidden"
name="encrypted" name="encrypted"
value="-----BEGIN PKCS7-----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-----END PKCS7----- value="-----BEGIN PKCS7-----MIIHRwYJKoZIhvcNAQcEoIIHODCCBzQCAQExggEwMIIBLAIBADCBlDCBjjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtQYXlQYWwgSW5jLjETMBEGA1UECxQKbGl2ZV9jZXJ0czERMA8GA1UEAxQIbGl2ZV9hcGkxHDAaBgkqhkiG9w0BCQEWDXJlQHBheXBhbC5jb20CAQAwDQYJKoZIhvcNAQEBBQAEgYA2Y2VGE75oWct89z//G2YEJKmzx0uDTXNrpje9ThxmUnBLFZCY+I11Pors7lGRvFqo5okwnu41CfYMPHDxpAgyYyQndMX9pWUX0gLfBMm2BaHwsNBCwt34WmpQqj7TGsQ+aw9NbmkxiJltGnOa+6/gy10mPZAA3HxiieLeCKkGgDELMAkGBSsOAwIaBQAwgcQGCSqGSIb3DQEHATAUBggqhkiG9w0DBwQI72F1YSzHUd2AgaDMekHU3AKT93Ey9wkB3486bV+ngFSD6VOHrPweH9QATsp+PMe9QM9vmq+s2bGtTbZaYrFqM3M97SnQ0l7IQ5yuOzdZhRdfysu5uJ8dnuHUzq4gLSzqMnZ6/3c+PoHB8AS1nYHUVL4U0+ogZsO1s97IAQyfck9SaoFlxVtqQhkb8752MkQJJvGu3ZQSQGcVC4hFDPk8prXqyq4BU/k/EliwoIIDhzCCA4MwggLsoAMCAQICAQAwDQYJKoZIhvcNAQEFBQAwgY4xCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEUMBIGA1UEChMLUGF5UGFsIEluYy4xEzARBgNVBAsUCmxpdmVfY2VydHMxETAPBgNVBAMUCGxpdmVfYXBpMRwwGgYJKoZIhvcNAQkBFg1yZUBwYXlwYWwuY29tMB4XDTA0MDIxMzEwMTMxNVoXDTM1MDIxMzEwMTMxNVowgY4xCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEUMBIGA1UEChMLUGF5UGFsIEluYy4xEzARBgNVBAsUCmxpdmVfY2VydHMxETAPBgNVBAMUCGxpdmVfYXBpMRwwGgYJKoZIhvcNAQkBFg1yZUBwYXlwYWwuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBR07d/ETMS1ycjtkpkvjXZe9k+6CieLuLsPumsJ7QC1odNz3sJiCbs2wC0nLE0uLGaEtXynIgRqIddYCHx88pb5HTXv4SZeuv0Rqq4+axW9PLAAATU8w04qqjaSXgbGLP3NmohqM6bV9kZZwZLR/klDaQGo1u9uDb9lr4Yn+rBQIDAQABo4HuMIHrMB0GA1UdDgQWBBSWn3y7xm8XvVk/UtcKG+wQ1mSUazCBuwYDVR0jBIGzMIGwgBSWn3y7xm8XvVk/UtcKG+wQ1mSUa6GBlKSBkTCBjjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtQYXlQYWwgSW5jLjETMBEGA1UECxQKbGl2ZV9jZXJ0czERMA8GA1UEAxQIbGl2ZV9hcGkxHDAaBgkqhkiG9w0BCQEWDXJlQHBheXBhbC5jb22CAQAwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQCBXzpWmoBa5e9fo6ujionW1hUhPkOBakTr3YCDjbYfvJEiv/2P+IobhOGJr85+XHhN0v4gUkEDI8r2/rNk1m0GA8HKddvTjyGw/XqXa+LSTlDYkqI8OwR8GEYj4efEtcRpRYBxV8KxAW93YDWzFGvruKnnLbDAF6VR5w/cCMn5hzGCAZowggGWAgEBMIGUMIGOMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxFDASBgNVBAoTC1BheVBhbCBJbmMuMRMwEQYDVQQLFApsaXZlX2NlcnRzMREwDwYDVQQDFAhsaXZlX2FwaTEcMBoGCSqGSIb3DQEJARYNcmVAcGF5cGFsLmNvbQIBADAJBgUrDgMCGgUAoF0wGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMTcwNzI1MDExODE2WjAjBgkqhkiG9w0BCQQxFgQUNo8efiZ7sk7nwKM/6B6Z7sU8hIIwDQYJKoZIhvcNAQEBBQAEgYB+JB4vZ/r48815/1HF/xK3+rOx7bPz3kAXmbhW/mkoF4OUbzqMeljvDIA9q/BDdlCLtxFOw9XlftTzv0eZCW/uCIiwu5wTzPIfPY1SI8WHe4cJbP2f2EYxIVs8D7OSirbW4yVa0+gACaLLj0rzIzNN8P/5PxgB03D+jwkcJABqng==-----END PKCS7-----"
"
/> />
<input <input
type="image" type="image"
src="https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif" src="https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif"
border="0"
name="submit" name="submit"
alt="PayPal - The safer, easier way to pay online!" alt="PayPal - The safer, easier way to pay online!"
/> />
<img alt="" border="0" src="https://www.paypalobjects.com/en_US/i/scr/pixel.gif" width="1" height="1" />
</form> </form>
</div> </Grid>
<div id="game-options-right-panel"> <Grid item xs={12} sm={6}>
<a class="a-link-button" href="https://bitburner.readthedocs.io/en/latest/changelog.html" target="_blank"> <Box>
Changelog <Button onClick={() => props.save()}>Save Game</Button>
</a> <Button onClick={() => props.delete()}>Delete Game</Button>
<a class="a-link-button" href="https://bitburner.readthedocs.io/en/latest/index.html" target="_blank" </Box>
>Documentation</a <Box>
> <Button onClick={() => props.export()}>Export Game</Button>
<a class="a-link-button" href="https://discord.gg/TFc3hKD" target="_blank">Discord</a> <Button onClick={() => props.import()}>Import Game</Button>
<a class="a-link-button" href="https://www.reddit.com/r/bitburner" target="_blank">Subreddit</a> </Box>
<button id="save-game-link" class="a-link-button">Save Game</button> <Box>
<button id="delete-game-link" class="a-link-button">Delete Game</button> <Tooltip
<button id="export-game-link" class="a-link-button">Export Game</button> title={
<input type="file" id="import-game-file-selector" name="file" /> <Typography>
<button id="import-game-link" class="a-link-button">Import Game</button>
<button id="copy-save-to-clipboard-link" class="std-button">Copy Save data to Clipboard</button>
<button id="debug-delete-scripts-link" class="a-link-button tooltip">
Force kill all active scripts
<span class="tooltiptextleft">
Forcefully kill all active running scripts, in case there is a bug or some unexpected issue with the Forcefully kill all active running scripts, in case there is a bug or some unexpected issue with the
game. After using this, save the game and then reload the page. This is different then normal kill in game. After using this, save the game and then reload the page. This is different then normal kill in
that normal kill will tell the script to shut down while force kill just removes the references to it that normal kill will tell the script to shut down while force kill just removes the references to it
(and it should crash on it's own). This will not remove the files on your computer. Just forcefully kill (and it should crash on it's own). This will not remove the files on your computer. Just forcefully
all running instance of all scripts. kill all running instance of all scripts.
</span> </Typography>
</button> }
<button id="debug-soft-reset" class="a-link-button tooltip"> >
Soft Reset <Button onClick={() => props.forceKill()}>Force kill all active scripts</Button>
<span class="tooltiptextleft"> </Tooltip>
</Box>
<Box>
<Tooltip
title={
<Typography>
Perform a soft reset. Resets everything as if you had just purchased an Augmentation. Perform a soft reset. Resets everything as if you had just purchased an Augmentation.
</span> </Typography>
</button> }
<button id="debug-files" class="a-link-button tooltip"> >
Diagnose files <Button onClick={() => props.softReset()}>Soft Reset</Button>
<span class="tooltiptextleft"> </Tooltip>
</Box>
<Box>
<Tooltip
title={
<Typography>
If your save file is extremely big you can use this button to view a map of all the files on every If your save file is extremely big you can use this button to view a map of all the files on every
server. Be careful there might be spoilers. server. Be careful there might be spoilers.
</span> </Typography>
</button> }
>
<Button onClick={() => setDiagnosticOpen(true)}>Diagnose files</Button>
</Tooltip>
</Box>
<Box>
<Link href="https://bitburner.readthedocs.io/en/latest/changelog.html" target="_blank">
<Typography>Changelog</Typography>
</Link>
<Link href="https://bitburner.readthedocs.io/en/latest/index.html" target="_blank">
<Typography>Documentation</Typography>
</Link>
<Link href="https://bitburner.readthedocs.io/en/latest/changelog.html" target="_blank">
<Typography>Changelog</Typography>
</Link>
<Link href="https://discord.gg/TFc3hKD" target="_blank">
<Typography>Discord</Typography>
</Link>
<Link href="https://www.reddit.com/r/bitburner" target="_blank">
<Typography>Reddit</Typography>
</Link>
</Box>
</Grid>
</Grid>
<Modal open={diagnosticOpen} close={() => setDiagnosticOpen(false)}>
<FileDiagnosticPopup />
</Modal>
</div> </div>
);
*/
} }

47
src/ui/React/Modal.tsx Normal file

@ -0,0 +1,47 @@
import React from "react";
import { makeStyles, createStyles, Theme } from "@material-ui/core";
import M from "@material-ui/core/Modal";
import Backdrop from "@material-ui/core/Backdrop";
import Fade from "@material-ui/core/Fade";
const useStyles = makeStyles((theme: Theme) =>
createStyles({
modal: {
display: "flex",
alignItems: "center",
justifyContent: "center",
},
paper: {
backgroundColor: theme.palette.background.paper,
border: "2px solid " + theme.palette.primary.main,
boxShadow: theme.shadows[5],
padding: theme.spacing(2, 4, 3),
},
}),
);
interface IProps {
open: boolean;
close: () => void;
children: JSX.Element[] | JSX.Element;
}
export const Modal = (props: IProps): React.ReactElement => {
const classes = useStyles();
return (
<M
open={props.open}
onClose={props.close}
closeAfterTransition
className={classes.modal}
BackdropComponent={Backdrop}
BackdropProps={{
timeout: 500,
}}
>
<Fade in={props.open}>
<div className={classes.paper}>{props.children}</div>
</Fade>
</M>
);
};

@ -14,6 +14,7 @@ export const colors = {
secondary: "#888", secondary: "#888",
secondarydark: "#666", secondarydark: "#666",
welllight: "#444",
well: "#222", well: "#222",
white: "#fff", white: "#fff",
black: "#000", black: "#000",
@ -36,6 +37,9 @@ export const theme = createMuiTheme({
main: colors.error, main: colors.error,
dark: colors.errordark, dark: colors.errordark,
}, },
background: {
paper: colors.well,
},
}, },
typography: { typography: {
fontFamily: "monospace", fontFamily: "monospace",
@ -150,12 +154,25 @@ export const theme = createMuiTheme({
backgroundColor: colors.black, backgroundColor: colors.black,
}, },
paperAnchorDockedLeft: { paperAnchorDockedLeft: {
borderRight: "1px solid #444", borderRight: "1px solid " + colors.welllight,
}, },
}, },
MuiDivider: { MuiDivider: {
root: { root: {
backgroundColor: "#444", backgroundColor: colors.welllight,
},
},
MuiFormControlLabel: {
root: {
color: colors.primary,
},
},
MuiSwitch: {
switchBase: {
color: colors.primarydark,
},
track: {
backgroundColor: colors.welllight,
}, },
}, },
}, },

@ -122,6 +122,11 @@ export enum Page {
* Purchase Resleeves * Purchase Resleeves
*/ */
Resleeves = "Re-sleeving", Resleeves = "Re-sleeving",
/**
* Game options
*/
GameOptions = "GameOptions",
} }
/** /**