mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2026-05-02 05:47:14 +02:00
MISC: Support compression of save data (#1162)
* Use Compression Streams API instead of jszip or other libraries. * Remove usage of base64 in the new binary format. * Do not convert binary data to string and back. The type of save data is SaveData, it's either string (old base64 format) or Uint8Array (new binary format). * Proper support for interacting with electron-related code. Electron-related code assumes that save data is in the base64 format. * Proper support for other tools (DevMenu, pretty-save.js). Full support for DevMenu will be added in a follow-up PR. Check the comments in src\DevMenu\ui\SaveFileDev.tsx for details.
This commit is contained in:
@@ -38,6 +38,7 @@ import { Page } from "../../Router";
|
||||
import { useBoolean } from "../hooks";
|
||||
|
||||
import { ComparisonIcon } from "./ComparisonIcon";
|
||||
import { SaveData } from "../../../types";
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
@@ -89,7 +90,7 @@ const playerSkills: (keyof Skills)[] = ["hacking", "strength", "defense", "dexte
|
||||
|
||||
let initialAutosave = 0;
|
||||
|
||||
export const ImportSave = (props: { importString: string; automatic: boolean }): JSX.Element => {
|
||||
export const ImportSave = (props: { saveData: SaveData; automatic: boolean }): JSX.Element => {
|
||||
const classes = useStyles();
|
||||
const [importData, setImportData] = useState<ImportData | undefined>();
|
||||
const [currentData, setCurrentData] = useState<ImportData | undefined>();
|
||||
@@ -105,7 +106,7 @@ export const ImportSave = (props: { importString: string; automatic: boolean }):
|
||||
};
|
||||
|
||||
const handleImport = async (): Promise<void> => {
|
||||
await saveObject.importGame(props.importString, true);
|
||||
await saveObject.importGame(props.saveData, true);
|
||||
pushImportResult(true);
|
||||
};
|
||||
|
||||
@@ -122,16 +123,16 @@ export const ImportSave = (props: { importString: string; automatic: boolean }):
|
||||
|
||||
useEffect(() => {
|
||||
async function fetchData(): Promise<void> {
|
||||
const dataBeingImported = await saveObject.getImportDataFromString(props.importString);
|
||||
const dataCurrentlyInGame = await saveObject.getImportDataFromString(saveObject.getSaveString(true));
|
||||
const dataBeingImported = await saveObject.getImportDataFromSaveData(props.saveData);
|
||||
const dataCurrentlyInGame = await saveObject.getImportDataFromSaveData(await saveObject.getSaveData(true));
|
||||
|
||||
setImportData(dataBeingImported);
|
||||
setCurrentData(dataCurrentlyInGame);
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
if (props.importString) fetchData();
|
||||
}, [props.importString]);
|
||||
if (props.saveData) fetchData();
|
||||
}, [props.saveData]);
|
||||
|
||||
if (!importData || !currentData) return <></>;
|
||||
|
||||
|
||||
@@ -12,11 +12,15 @@ import { SoftResetButton } from "./SoftResetButton";
|
||||
|
||||
import DirectionsRunIcon from "@mui/icons-material/DirectionsRun";
|
||||
import GitHubIcon from "@mui/icons-material/GitHub";
|
||||
import { isBinaryFormat } from "../../../electron/saveDataBinaryFormat";
|
||||
import { InvalidSaveData, UnsupportedSaveData } from "../../utils/SaveDataUtils";
|
||||
|
||||
export let RecoveryMode = false;
|
||||
let sourceError: unknown;
|
||||
|
||||
export function ActivateRecoveryMode(): void {
|
||||
export function ActivateRecoveryMode(error: unknown): void {
|
||||
RecoveryMode = true;
|
||||
sourceError = error;
|
||||
}
|
||||
|
||||
interface IProps {
|
||||
@@ -29,6 +33,7 @@ export function RecoveryRoot({ softReset, errorData, resetError }: IProps): Reac
|
||||
function recover(): void {
|
||||
if (resetError) resetError();
|
||||
RecoveryMode = false;
|
||||
sourceError = undefined;
|
||||
Router.toPage(Page.Terminal);
|
||||
}
|
||||
Settings.AutosaveInterval = 0;
|
||||
@@ -37,41 +42,65 @@ export function RecoveryRoot({ softReset, errorData, resetError }: IProps): Reac
|
||||
load()
|
||||
.then((content) => {
|
||||
const epochTime = Math.round(Date.now() / 1000);
|
||||
const filename = `RECOVERY_BITBURNER_${epochTime}.json`;
|
||||
const extension = isBinaryFormat(content) ? "json.gz" : "json";
|
||||
const filename = `RECOVERY_BITBURNER_${epochTime}.${extension}`;
|
||||
download(filename, content);
|
||||
})
|
||||
.catch((err) => console.error(err));
|
||||
}, []);
|
||||
|
||||
let instructions;
|
||||
if (sourceError instanceof UnsupportedSaveData) {
|
||||
instructions = <Typography variant="h6">Please update your browser.</Typography>;
|
||||
} else if (sourceError instanceof InvalidSaveData) {
|
||||
instructions = (
|
||||
<Typography variant="h6">Your save data is invalid. Please import a valid backup save file.</Typography>
|
||||
);
|
||||
} else {
|
||||
instructions = (
|
||||
<Box>
|
||||
<Typography>It is recommended to alert a developer.</Typography>
|
||||
<Typography>
|
||||
<Link href={errorData?.issueUrl ?? newIssueUrl} target="_blank">
|
||||
File an issue on github
|
||||
</Link>
|
||||
</Typography>
|
||||
<Typography>
|
||||
<Link href="https://www.reddit.com/r/Bitburner/" target="_blank">
|
||||
Make a reddit post
|
||||
</Link>
|
||||
</Typography>
|
||||
<Typography>
|
||||
<Link href="https://discord.gg/TFc3hKD" target="_blank">
|
||||
Post in the #bug-report channel on Discord.
|
||||
</Link>
|
||||
</Typography>
|
||||
<Typography>Please include your save file.</Typography>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Box sx={{ padding: "8px 16px", minHeight: "100vh", maxWidth: "1200px", boxSizing: "border-box" }}>
|
||||
<Typography variant="h3">RECOVERY MODE ACTIVATED</Typography>
|
||||
<Typography>
|
||||
There was an error with your save file and the game went into recovery mode. In this mode saving is disabled and
|
||||
the game will automatically export your save file (to prevent corruption).
|
||||
There was an error with your save file and the game went into recovery mode. In this mode, saving is disabled
|
||||
and the game will automatically export your save file to prevent corruption.
|
||||
</Typography>
|
||||
<Typography>At this point it is recommended to alert a developer.</Typography>
|
||||
<Typography>
|
||||
<Link href={errorData?.issueUrl ?? newIssueUrl} target="_blank">
|
||||
File an issue on github
|
||||
</Link>
|
||||
</Typography>
|
||||
<Typography>
|
||||
<Link href="https://www.reddit.com/r/Bitburner/" target="_blank">
|
||||
Make a reddit post
|
||||
</Link>
|
||||
</Typography>
|
||||
<Typography>
|
||||
<Link href="https://discord.gg/TFc3hKD" target="_blank">
|
||||
Post in the #bug-report channel on Discord.
|
||||
</Link>
|
||||
</Typography>
|
||||
<Typography>Please include your save file.</Typography>
|
||||
<br />
|
||||
{sourceError && (
|
||||
<Box>
|
||||
<Typography variant="h6" color={Settings.theme.error}>
|
||||
Error: {sourceError.toString()}
|
||||
</Typography>
|
||||
<br />
|
||||
</Box>
|
||||
)}
|
||||
{instructions}
|
||||
<br />
|
||||
<Typography>You can disable recovery mode now. But chances are the game will not work correctly.</Typography>
|
||||
<Typography>You can disable the recovery mode, but the game may not work correctly.</Typography>
|
||||
<ButtonGroup sx={{ my: 2 }}>
|
||||
<Tooltip title="Disables the recovery mode & attempt to head back to the terminal page. This may or may not work. Ensure you have saved the recovery file.">
|
||||
<Tooltip title="Disable the recovery mode and attempt to head back to the terminal page. This may or may not work. Ensure you saved the recovery file.">
|
||||
<Button onClick={recover} startIcon={<DirectionsRunIcon />}>
|
||||
Disable Recovery Mode
|
||||
</Button>
|
||||
@@ -96,7 +125,7 @@ export function RecoveryRoot({ softReset, errorData, resetError }: IProps): Reac
|
||||
sx={{ "& .MuiOutlinedInput-root": { color: Settings.theme.secondary } }}
|
||||
/>
|
||||
</Box>
|
||||
<Tooltip title="Submitting an issue to GitHub really help us improve the game!">
|
||||
<Tooltip title="Submitting an issue to GitHub really helps us improve the game!">
|
||||
<Button
|
||||
component={Link}
|
||||
startIcon={<GitHubIcon />}
|
||||
|
||||
Reference in New Issue
Block a user