mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-18 20:25:45 +01:00
commit
aff9b58040
44
dist/vendor.bundle.js
vendored
44
dist/vendor.bundle.js
vendored
File diff suppressed because one or more lines are too long
@ -113,7 +113,7 @@ The list contains the name of (i.e. the value returned by
|
||||
| | | to any position from i to i+n. |
|
||||
| | | |
|
||||
| | | Assuming you are initially positioned at the start of the array, determine |
|
||||
| | | whether you are able to reach the last index of the array. |
|
||||
| | | whether you are able to reach the last index of the array. |
|
||||
+------------------------------------+------------------------------------------------------------------------------------------+
|
||||
| Merge Overlapping Intervals | | Given an array of intervals, merge all overlapping intervals. An interval |
|
||||
| | | is an array with two numbers, where the first number is always less than |
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -48,7 +48,7 @@ for (let i = 0; i < scripts.length; ++i) {
|
||||
```ts
|
||||
// NS2:
|
||||
const ps = ns.ps("home");
|
||||
for (script of ps) {
|
||||
for (let script of ps) {
|
||||
ns.tprint(`${script.filename} ${ps[i].threads}`);
|
||||
ns.tprint(script.args);
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ export const Literatures: IMap<Literature> = {};
|
||||
"money on a server, and grow() increases the amount of money on a server by some percentage (multiplicatively)<br><br>" +
|
||||
"-Because hack() and grow() work by percentages, they are more effective if the target server has a high amount of money. " +
|
||||
"Therefore, you should try to increase the amount of money on a server (using grow()) to a certain amount before hacking it. Two " +
|
||||
"import Netscript functions for this are getServerMoneyAvailable() and getServerMaxMoney()<br><br>" +
|
||||
"important Netscript functions for this are getServerMoneyAvailable() and getServerMaxMoney()<br><br>" +
|
||||
"-Keep security level low. Security level affects everything when hacking. Two important Netscript functions " +
|
||||
"for this are getServerSecurityLevel() and getServerMinSecurityLevel()<br><br>" +
|
||||
"-Purchase additional servers by visiting 'Alpha Enterprises' in the city. They are relatively cheap " +
|
||||
|
@ -9,9 +9,6 @@ import { makeRuntimeRejectMsg } from "./NetscriptEvaluator";
|
||||
import { ScriptUrl } from "./Script/ScriptUrl";
|
||||
import { WorkerScript } from "./Netscript/WorkerScript";
|
||||
import { Script } from "./Script/Script";
|
||||
import { computeHash } from "./utils/helpers/computeHash";
|
||||
import { BlobCache } from "./utils/BlobCache";
|
||||
import { ImportCache } from "./utils/ImportCache";
|
||||
import { areImportsEquals } from "./Terminal/DirectoryHelpers";
|
||||
import { IPlayer } from "./PersonObjects/IPlayer";
|
||||
|
||||
@ -190,31 +187,12 @@ function _getScriptUrls(script: Script, scripts: Script[], seen: Script[]): Scri
|
||||
if (matchingScripts.length === 0) continue;
|
||||
|
||||
const [importedScript] = matchingScripts;
|
||||
// Check to see if the urls for this script are stored in the cache by the hash value.
|
||||
let urls = ImportCache.get(importedScript.hash());
|
||||
// If we don't have it in the cache, then we need to generate the urls for it.
|
||||
if (urls) {
|
||||
// Verify that these urls are valid and have not been updated.
|
||||
for (const url of urls) {
|
||||
if (isDependencyOutOfDate(url.filename, scripts, url.moduleSequenceNumber)) {
|
||||
// Revoke these URLs from the browser. We will be unable to use them again.
|
||||
for (const url of urls) URL.revokeObjectURL(url.url);
|
||||
// Clear the cache and prepare for new blobs.
|
||||
urls = null;
|
||||
ImportCache.remove(importedScript.hash());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!urls) {
|
||||
// Try to get a URL for the requested script and its dependencies.
|
||||
urls = _getScriptUrls(importedScript, scripts, seen);
|
||||
}
|
||||
|
||||
const urls = _getScriptUrls(importedScript, scripts, seen);
|
||||
|
||||
// The top url in the stack is the replacement import file for this script.
|
||||
urlStack.push(...urls);
|
||||
const blob = urls[urls.length - 1].url;
|
||||
ImportCache.store(importedScript.hash(), urls);
|
||||
|
||||
// Replace the blob inside the import statement.
|
||||
transformedCode = transformedCode.substring(0, node.start) + blob + transformedCode.substring(node.end);
|
||||
@ -224,17 +202,7 @@ function _getScriptUrls(script: Script, scripts: Script[], seen: Script[]): Scri
|
||||
// accidental calls to window.print() do not bring up the "print screen" dialog
|
||||
transformedCode += `\n\nfunction print() {throw new Error("Invalid call to window.print(). Did you mean to use Netscript's print()?");}`;
|
||||
|
||||
// If we successfully transformed the code, create a blob url for it
|
||||
// Compute the hash for the transformed code
|
||||
const transformedHash = computeHash(transformedCode);
|
||||
// Check to see if this transformed hash is in our cache
|
||||
let blob = BlobCache.get(transformedHash);
|
||||
if (!blob) {
|
||||
blob = URL.createObjectURL(makeScriptBlob(transformedCode));
|
||||
}
|
||||
// Store this blob in the cache. Any script that transforms the same
|
||||
// (e.g. same scripts on server, same hash value, etc) can use this blob url.
|
||||
BlobCache.store(transformedHash, blob);
|
||||
const blob = URL.createObjectURL(makeScriptBlob(transformedCode));
|
||||
// Push the blob URL onto the top of the stack.
|
||||
urlStack.push(new ScriptUrl(script.filename, blob, script.moduleSequenceNumber));
|
||||
return urlStack;
|
||||
|
@ -8,6 +8,5 @@ export function StartSharing(threads: number): () => void {
|
||||
}
|
||||
|
||||
export function CalculateShareMult(): number {
|
||||
console.log(`${sharePower} => ${CSM(sharePower)}`);
|
||||
return CSM(sharePower);
|
||||
}
|
||||
|
@ -9,13 +9,14 @@ import { ScriptUrl } from "./ScriptUrl";
|
||||
|
||||
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver";
|
||||
import { roundToTwo } from "../utils/helpers/roundToTwo";
|
||||
import { computeHash } from "../utils/helpers/computeHash";
|
||||
import { ImportCache } from "../utils/ImportCache";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
|
||||
let globalModuleSequenceNumber = 0;
|
||||
|
||||
interface ScriptReference { filename: string; server: string }
|
||||
interface ScriptReference {
|
||||
filename: string;
|
||||
server: string;
|
||||
}
|
||||
|
||||
export class Script {
|
||||
// Code for this script
|
||||
@ -47,9 +48,6 @@ export class Script {
|
||||
// hostname of server that this script is on.
|
||||
server = "";
|
||||
|
||||
// sha256 hash of the code in the Script. Do not access directly.
|
||||
_hash = "";
|
||||
|
||||
constructor(player: IPlayer | null = null, fn = "", code = "", server = "", otherScripts: Script[] = []) {
|
||||
this.filename = fn;
|
||||
this.code = code;
|
||||
@ -57,10 +55,8 @@ export class Script {
|
||||
this.server = server; // hostname of server this script is on
|
||||
this.module = "";
|
||||
this.moduleSequenceNumber = ++globalModuleSequenceNumber;
|
||||
this._hash = "";
|
||||
if (this.code !== "" && player !== null) {
|
||||
this.updateRamUsage(player, otherScripts);
|
||||
this.rehash();
|
||||
}
|
||||
}
|
||||
|
||||
@ -96,27 +92,6 @@ export class Script {
|
||||
markUpdated(): void {
|
||||
this.module = "";
|
||||
this.moduleSequenceNumber = ++globalModuleSequenceNumber;
|
||||
this.rehash();
|
||||
}
|
||||
|
||||
/**
|
||||
* Force update of the computed hash based on the source code.
|
||||
*/
|
||||
rehash(): void {
|
||||
const oldHash = this._hash;
|
||||
this._hash = computeHash(this.code);
|
||||
if (oldHash !== this._hash) {
|
||||
ImportCache.remove(oldHash);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the hash is not computed, computes the hash. Otherwise return the computed hash.
|
||||
* @returns the computed hash of the script
|
||||
*/
|
||||
hash(): string {
|
||||
if (!this._hash) this.rehash();
|
||||
return this._hash;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -133,7 +108,9 @@ export class Script {
|
||||
this.updateRamUsage(player, otherScripts);
|
||||
this.markUpdated();
|
||||
for (const dependent of this.dependents) {
|
||||
const [dependentScript] = otherScripts.filter(s => s.filename === dependent.filename && s.server == dependent.server);
|
||||
const [dependentScript] = otherScripts.filter(
|
||||
(s) => s.filename === dependent.filename && s.server == dependent.server,
|
||||
);
|
||||
if (dependentScript !== null) dependentScript.markUpdated();
|
||||
}
|
||||
}
|
||||
@ -166,8 +143,6 @@ export class Script {
|
||||
const s = Generic_fromJSON(Script, value.data);
|
||||
// Force the url to blank from the save data. Urls are not valid outside the current browser page load.
|
||||
s.url = "";
|
||||
// Rehash the code to ensure that hash is set properly.
|
||||
s.rehash();
|
||||
s.dependents = [];
|
||||
return s;
|
||||
}
|
||||
@ -177,7 +152,7 @@ export class Script {
|
||||
* @param {string} code - The code to format
|
||||
* @returns The formatted code
|
||||
*/
|
||||
static formatCode(code: string): string {
|
||||
static formatCode(code: string): string {
|
||||
return code.replace(/^\s+|\s+$/g, "");
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,13 @@ export function LoadingScreen(): React.ReactElement {
|
||||
const [show, setShow] = useState(false);
|
||||
const [loaded, setLoaded] = useState(false);
|
||||
|
||||
const version = `v${CONSTANTS.VersionString} (${hash()})`;
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
document.title = `[dev] Bitburner ${version}`;
|
||||
} else {
|
||||
document.title = `Bitburner ${version}`;
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const id = setTimeout(() => {
|
||||
if (!loaded) setShow(true);
|
||||
@ -70,9 +77,7 @@ export function LoadingScreen(): React.ReactElement {
|
||||
<CircularProgress size={150} color="primary" />
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Typography variant="h3">
|
||||
Loading Bitburner v{CONSTANTS.VersionString} ({hash()})
|
||||
</Typography>
|
||||
<Typography variant="h3">Loading Bitburner {version}</Typography>
|
||||
</Grid>
|
||||
{show && (
|
||||
<Grid item>
|
||||
|
@ -453,14 +453,14 @@ export function CharacterOverview({ save, killScripts }: IProps): React.ReactEle
|
||||
</Table>
|
||||
<Box sx={{ display: "flex", borderTop: `1px solid ${Settings.theme.welllight}` }}>
|
||||
<Box sx={{ display: "flex", flex: 1, justifyContent: "flex-start", alignItems: "center" }}>
|
||||
<IconButton onClick={save}>
|
||||
<IconButton aria-label="save game" onClick={save}>
|
||||
<Tooltip title="Save game">
|
||||
<SaveIcon color={Settings.AutosaveInterval !== 0 ? "primary" : "error"} />
|
||||
</Tooltip>
|
||||
</IconButton>
|
||||
</Box>
|
||||
<Box sx={{ display: "flex", flex: 1, justifyContent: "flex-end", alignItems: "center" }}>
|
||||
<IconButton onClick={() => setKillOpen(true)}>
|
||||
<IconButton aria-label="kill all scripts" onClick={() => setKillOpen(true)}>
|
||||
<Tooltip title="Kill all running scripts">
|
||||
<ClearAllIcon color="error" />
|
||||
</Tooltip>
|
||||
|
@ -21,7 +21,7 @@ import TextField from "@mui/material/TextField";
|
||||
|
||||
import DownloadIcon from "@mui/icons-material/Download";
|
||||
import UploadIcon from "@mui/icons-material/Upload";
|
||||
import SaveIcon from '@mui/icons-material/Save';
|
||||
import SaveIcon from "@mui/icons-material/Save";
|
||||
|
||||
import { FileDiagnosticModal } from "../../Diagnostic/FileDiagnosticModal";
|
||||
import { dialogBoxCreate } from "./DialogBox";
|
||||
@ -152,7 +152,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
|
||||
console.log(error); // We'll handle below
|
||||
}
|
||||
|
||||
if (!newSave || newSave === '') {
|
||||
if (!newSave || newSave === "") {
|
||||
SnackbarEvents.emit("Save game had not content or was not base64 encoded", "error", 5000);
|
||||
return;
|
||||
}
|
||||
@ -164,7 +164,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
|
||||
console.log(error); // We'll handle below
|
||||
}
|
||||
|
||||
if (!parsedSave || parsedSave.ctor !== 'BitburnerSaveObject' || !parsedSave.data) {
|
||||
if (!parsedSave || parsedSave.ctor !== "BitburnerSaveObject" || !parsedSave.data) {
|
||||
SnackbarEvents.emit("Save game did not seem valid", "error", 5000);
|
||||
return;
|
||||
}
|
||||
@ -172,14 +172,14 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
|
||||
const data: ImportData = {
|
||||
base64: contents,
|
||||
parsed: parsedSave,
|
||||
}
|
||||
};
|
||||
|
||||
const timestamp = parsedSave.data.SaveTimestamp;
|
||||
if (timestamp && timestamp !== '0') {
|
||||
data.exportDate = new Date(parseInt(timestamp, 10))
|
||||
if (timestamp && timestamp !== "0") {
|
||||
data.exportDate = new Date(parseInt(timestamp, 10));
|
||||
}
|
||||
|
||||
setImportData(data)
|
||||
setImportData(data);
|
||||
setImportSaveOpen(true);
|
||||
};
|
||||
reader.readAsText(file);
|
||||
@ -191,7 +191,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
|
||||
setImportSaveOpen(false);
|
||||
save(importData.base64).then(() => {
|
||||
setImportData(null);
|
||||
setTimeout(() => location.reload(), 1000)
|
||||
setTimeout(() => location.reload(), 1000);
|
||||
});
|
||||
}
|
||||
|
||||
@ -213,7 +213,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
|
||||
</Typography>
|
||||
}
|
||||
>
|
||||
<Typography>Netscript exec time (ms)</Typography>
|
||||
<Typography>.script exec time (ms)</Typography>
|
||||
</Tooltip>
|
||||
<Slider
|
||||
value={execTime}
|
||||
@ -304,128 +304,165 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<OptionSwitch checked={Settings.SuppressMessages}
|
||||
onChange={(newValue) => Settings.SuppressMessages = newValue}
|
||||
<OptionSwitch
|
||||
checked={Settings.SuppressMessages}
|
||||
onChange={(newValue) => (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.
|
||||
</>} />
|
||||
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.
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<OptionSwitch checked={Settings.SuppressFactionInvites}
|
||||
onChange={(newValue) => Settings.SuppressFactionInvites = newValue}
|
||||
<OptionSwitch
|
||||
checked={Settings.SuppressFactionInvites}
|
||||
onChange={(newValue) => (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.
|
||||
</>} />
|
||||
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.
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<OptionSwitch checked={Settings.SuppressTravelConfirmation}
|
||||
onChange={(newValue) => Settings.SuppressTravelConfirmation = newValue}
|
||||
<OptionSwitch
|
||||
checked={Settings.SuppressTravelConfirmation}
|
||||
onChange={(newValue) => (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.
|
||||
</>} />
|
||||
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.
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<OptionSwitch checked={Settings.SuppressBuyAugmentationConfirmation}
|
||||
onChange={(newValue) => Settings.SuppressBuyAugmentationConfirmation = newValue}
|
||||
<OptionSwitch
|
||||
checked={Settings.SuppressBuyAugmentationConfirmation}
|
||||
onChange={(newValue) => (Settings.SuppressBuyAugmentationConfirmation = newValue)}
|
||||
text="Suppress augmentations confirmation"
|
||||
tooltip={<>
|
||||
If this is set, the confirmation message before buying augmentation will not show up.
|
||||
</>} />
|
||||
tooltip={<>If this is set, the confirmation message before buying augmentation will not show up.</>}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<OptionSwitch checked={Settings.SuppressTIXPopup}
|
||||
onChange={(newValue) => Settings.SuppressTIXPopup = newValue}
|
||||
<OptionSwitch
|
||||
checked={Settings.SuppressTIXPopup}
|
||||
onChange={(newValue) => (Settings.SuppressTIXPopup = newValue)}
|
||||
text="Suppress TIX messages"
|
||||
tooltip={<>
|
||||
If this is set, the stock market will never create any popup.
|
||||
</>} />
|
||||
tooltip={<>If this is set, the stock market will never create any popup.</>}
|
||||
/>
|
||||
</ListItem>
|
||||
{!!props.player.bladeburner && (
|
||||
<ListItem>
|
||||
<OptionSwitch checked={Settings.SuppressBladeburnerPopup}
|
||||
onChange={(newValue) => Settings.SuppressBladeburnerPopup = newValue}
|
||||
<OptionSwitch
|
||||
checked={Settings.SuppressBladeburnerPopup}
|
||||
onChange={(newValue) => (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.
|
||||
</>} />
|
||||
tooltip={
|
||||
<>
|
||||
If this is set, then having your Bladeburner actions interrupted by being busy with something else
|
||||
will not display a popup message.
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
)}
|
||||
<ListItem>
|
||||
<OptionSwitch checked={Settings.SuppressSavedGameToast}
|
||||
onChange={(newValue) => Settings.SuppressSavedGameToast = newValue}
|
||||
<OptionSwitch
|
||||
checked={Settings.SuppressSavedGameToast}
|
||||
onChange={(newValue) => (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.
|
||||
</>} />
|
||||
tooltip={<>If this is set, there will be no "Game Saved!" toast appearing after an auto-save.</>}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<OptionSwitch checked={Settings.DisableHotkeys}
|
||||
onChange={(newValue) => Settings.DisableHotkeys = newValue}
|
||||
<OptionSwitch
|
||||
checked={Settings.DisableHotkeys}
|
||||
onChange={(newValue) => (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.
|
||||
</>} />
|
||||
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.
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<OptionSwitch checked={Settings.DisableASCIIArt}
|
||||
onChange={(newValue) => Settings.DisableASCIIArt = newValue}
|
||||
<OptionSwitch
|
||||
checked={Settings.DisableASCIIArt}
|
||||
onChange={(newValue) => (Settings.DisableASCIIArt = newValue)}
|
||||
text="Disable ascii art"
|
||||
tooltip={<>
|
||||
If this is set all ASCII art will be disabled.
|
||||
</>} />
|
||||
tooltip={<>If this is set all ASCII art will be disabled.</>}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<OptionSwitch checked={Settings.DisableTextEffects}
|
||||
onChange={(newValue) => Settings.DisableTextEffects = newValue}
|
||||
<OptionSwitch
|
||||
checked={Settings.DisableTextEffects}
|
||||
onChange={(newValue) => (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.
|
||||
</>} />
|
||||
tooltip={
|
||||
<>
|
||||
If this is set, text effects will not be displayed. This can help if text is difficult to read in
|
||||
certain areas.
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<OptionSwitch checked={Settings.DisableOverviewProgressBars}
|
||||
onChange={(newValue) => Settings.DisableOverviewProgressBars = newValue}
|
||||
<OptionSwitch
|
||||
checked={Settings.DisableOverviewProgressBars}
|
||||
onChange={(newValue) => (Settings.DisableOverviewProgressBars = newValue)}
|
||||
text="Disable Overview Progress Bars"
|
||||
tooltip={<>
|
||||
If this is set, the progress bars in the character overview will be hidden.
|
||||
</>} />
|
||||
tooltip={<>If this is set, the progress bars in the character overview will be hidden.</>}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<OptionSwitch checked={Settings.EnableBashHotkeys}
|
||||
onChange={(newValue) => Settings.EnableBashHotkeys = newValue}
|
||||
<OptionSwitch
|
||||
checked={Settings.EnableBashHotkeys}
|
||||
onChange={(newValue) => (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.
|
||||
</>} />
|
||||
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.
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<OptionSwitch checked={Settings.UseIEC60027_2}
|
||||
onChange={(newValue) => Settings.UseIEC60027_2 = newValue}
|
||||
<OptionSwitch
|
||||
checked={Settings.UseIEC60027_2}
|
||||
onChange={(newValue) => (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.
|
||||
</>} />
|
||||
tooltip={
|
||||
<>
|
||||
If this is set all references to memory will use GiB instead of GB, in accordance with IEC 60027-2.
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<OptionSwitch checked={Settings.ExcludeRunningScriptsFromSave}
|
||||
onChange={(newValue) => Settings.ExcludeRunningScriptsFromSave = newValue}
|
||||
<OptionSwitch
|
||||
checked={Settings.ExcludeRunningScriptsFromSave}
|
||||
onChange={(newValue) => (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.
|
||||
</>} />
|
||||
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.
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<Tooltip
|
||||
@ -460,12 +497,12 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
|
||||
</ListItem>
|
||||
|
||||
<ListItem>
|
||||
<OptionSwitch checked={Settings.SaveGameOnFileSave}
|
||||
onChange={(newValue) => Settings.SaveGameOnFileSave = newValue}
|
||||
<OptionSwitch
|
||||
checked={Settings.SaveGameOnFileSave}
|
||||
onChange={(newValue) => (Settings.SaveGameOnFileSave = newValue)}
|
||||
text="Save game on file save"
|
||||
tooltip={<>
|
||||
Save your game any time a file is saved in the script editor.
|
||||
</>} />
|
||||
tooltip={<>Save your game any time a file is saved in the script editor.</>}
|
||||
/>
|
||||
</ListItem>
|
||||
|
||||
<ListItem>
|
||||
@ -522,20 +559,28 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
|
||||
</>
|
||||
)}
|
||||
</Grid>
|
||||
<Box sx={{ display: 'grid', width: 'fit-content', height: 'fit-content' }}>
|
||||
<Box sx={{ display: 'grid', gridTemplateColumns: '1fr 1fr' }}>
|
||||
<Button onClick={() => props.save()} startIcon={<SaveIcon />} >
|
||||
<Box sx={{ display: "grid", width: "fit-content", height: "fit-content" }}>
|
||||
<Box sx={{ display: "grid", gridTemplateColumns: "1fr 1fr" }}>
|
||||
<Button onClick={() => props.save()} startIcon={<SaveIcon />}>
|
||||
Save Game
|
||||
</Button>
|
||||
<DeleteGameButton />
|
||||
</Box>
|
||||
<Box sx={{ display: 'grid', gridTemplateColumns: '1fr 1fr' }}>
|
||||
<Box sx={{ display: "grid", gridTemplateColumns: "1fr 1fr" }}>
|
||||
<Tooltip title={<Typography>Export your game to a text file.</Typography>}>
|
||||
<Button onClick={() => props.export()} startIcon={<DownloadIcon />}>
|
||||
Export Game
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip title={<Typography>Import your game from a text file.<br />This will <strong>overwrite</strong> your current game. Back it up first!</Typography>}>
|
||||
<Tooltip
|
||||
title={
|
||||
<Typography>
|
||||
Import your game from a text file.
|
||||
<br />
|
||||
This will <strong>overwrite</strong> your current game. Back it up first!
|
||||
</Typography>
|
||||
}
|
||||
>
|
||||
<Button onClick={startImport} startIcon={<UploadIcon />}>
|
||||
Import Game
|
||||
<input ref={importInput} id="import-game-file-selector" type="file" hidden onChange={onImport} />
|
||||
@ -555,16 +600,18 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
|
||||
The file you are attempting to import seems valid.
|
||||
<br />
|
||||
<br />
|
||||
{importData?.exportDate && (<>
|
||||
The export date of the save file is <strong>{importData?.exportDate.toString()}</strong>
|
||||
<br />
|
||||
<br />
|
||||
</>)}
|
||||
{importData?.exportDate && (
|
||||
<>
|
||||
The export date of the save file is <strong>{importData?.exportDate.toString()}</strong>
|
||||
<br />
|
||||
<br />
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
<Box sx={{ display: 'grid' }}>
|
||||
<Box sx={{ display: "grid" }}>
|
||||
<Tooltip
|
||||
title={
|
||||
<Typography>
|
||||
@ -579,8 +626,11 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
|
||||
<Button onClick={() => props.forceKill()}>Force kill all active scripts</Button>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
<Box sx={{ display: 'grid', gridTemplateColumns: '1fr 1fr' }}>
|
||||
<SoftResetButton noConfirmation={Settings.SuppressBuyAugmentationConfirmation} onTriggered={props.softReset} />
|
||||
<Box sx={{ display: "grid", gridTemplateColumns: "1fr 1fr" }}>
|
||||
<SoftResetButton
|
||||
noConfirmation={Settings.SuppressBuyAugmentationConfirmation}
|
||||
onTriggered={props.softReset}
|
||||
/>
|
||||
<Tooltip
|
||||
title={
|
||||
<Typography>
|
||||
@ -592,7 +642,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
|
||||
<Button onClick={() => setDiagnosticOpen(true)}>Diagnose files</Button>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
<Box sx={{ display: 'grid', gridTemplateColumns: '1fr 1fr' }}>
|
||||
<Box sx={{ display: "grid", gridTemplateColumns: "1fr 1fr" }}>
|
||||
<Button onClick={() => setThemeEditorOpen(true)}>Theme editor</Button>
|
||||
<Button onClick={() => setStyleEditorOpen(true)}>Style editor</Button>
|
||||
</Box>
|
||||
|
@ -124,7 +124,12 @@ export function Overview({ children, mode }: IProps): React.ReactElement {
|
||||
<Typography flexGrow={1} color="secondary">
|
||||
{header}
|
||||
</Typography>
|
||||
<Button variant="text" size="small" className={classes.visibilityToggle}>
|
||||
<Button
|
||||
aria-label="expand or collapse character overview"
|
||||
variant="text"
|
||||
size="small"
|
||||
className={classes.visibilityToggle}
|
||||
>
|
||||
{<CurrentIcon className={classes.icon} color="secondary" onClick={() => setOpen((old) => !old)} />}
|
||||
</Button>
|
||||
</Box>
|
||||
|
@ -1,18 +0,0 @@
|
||||
|
||||
const blobCache: { [hash: string]: string } = {};
|
||||
|
||||
export class BlobCache {
|
||||
static get(hash: string): string {
|
||||
return blobCache[hash];
|
||||
}
|
||||
|
||||
static store(hash: string, value: string): void {
|
||||
if (blobCache[hash]) return;
|
||||
blobCache[hash] = value;
|
||||
}
|
||||
|
||||
static removeByValue(value: string): void {
|
||||
const keys = Object.keys(blobCache).filter((key) => blobCache[key] === value);
|
||||
keys.forEach((key) => delete blobCache[key]);
|
||||
}
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
import { ScriptUrl } from "../Script/ScriptUrl";
|
||||
|
||||
const importCache: { [hash: string]: ScriptUrl[] } = {};
|
||||
|
||||
export class ImportCache {
|
||||
static get(hash: string): ScriptUrl[] | null {
|
||||
return importCache[hash] || null;
|
||||
}
|
||||
|
||||
static store(hash: string, value: ScriptUrl[]): void {
|
||||
if (importCache[hash]) return;
|
||||
importCache[hash] = value;
|
||||
}
|
||||
|
||||
static remove(hash: string): void {
|
||||
delete importCache[hash];
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
import { sha256 } from "js-sha256";
|
||||
|
||||
/**
|
||||
* Computes a SHA-256 hash of a string synchronously
|
||||
* @param message The input string
|
||||
* @returns The SHA-256 hash in hex
|
||||
*/
|
||||
export function computeHash(message: string): string {
|
||||
const hash = sha256.create();
|
||||
hash.update(message);
|
||||
return hash.hex();
|
||||
}
|
Loading…
Reference in New Issue
Block a user