2022-01-20 20:55:28 +01:00
|
|
|
import React, { useEffect, useState } from "react";
|
|
|
|
|
|
|
|
import {
|
|
|
|
Paper,
|
|
|
|
Table,
|
|
|
|
TableHead,
|
|
|
|
TableRow,
|
|
|
|
TableBody,
|
|
|
|
TableContainer,
|
|
|
|
TableCell,
|
|
|
|
Typography,
|
|
|
|
Tooltip,
|
|
|
|
Box,
|
|
|
|
Button,
|
|
|
|
ButtonGroup,
|
|
|
|
} from "@mui/material";
|
|
|
|
|
|
|
|
import makeStyles from "@mui/styles/makeStyles";
|
|
|
|
import createStyles from "@mui/styles/createStyles";
|
|
|
|
import { Theme } from "@mui/material/styles";
|
|
|
|
|
|
|
|
import ThumbUpAlt from "@mui/icons-material/ThumbUpAlt";
|
|
|
|
import ThumbDownAlt from "@mui/icons-material/ThumbDownAlt";
|
|
|
|
import DirectionsRunIcon from "@mui/icons-material/DirectionsRun";
|
|
|
|
import ArrowBackIcon from "@mui/icons-material/ArrowBack";
|
|
|
|
import WarningIcon from "@mui/icons-material/Warning";
|
|
|
|
|
|
|
|
import { ImportData, saveObject } from "../../SaveObject";
|
|
|
|
import { Settings } from "../../Settings/Settings";
|
|
|
|
import { convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions";
|
|
|
|
import { numeralWrapper } from "../numeralFormat";
|
|
|
|
import { ConfirmationModal } from "./ConfirmationModal";
|
2022-01-18 18:21:53 +01:00
|
|
|
import { pushImportResult } from "../../Electron";
|
2022-01-22 16:53:16 +01:00
|
|
|
import { IRouter } from "../Router";
|
2022-01-20 20:55:28 +01:00
|
|
|
|
|
|
|
const useStyles = makeStyles((theme: Theme) =>
|
|
|
|
createStyles({
|
|
|
|
root: {
|
|
|
|
padding: theme.spacing(2),
|
|
|
|
maxWidth: "1000px",
|
|
|
|
|
|
|
|
"& .MuiTable-root": {
|
|
|
|
"& .MuiTableCell-root": {
|
|
|
|
borderBottom: `1px solid ${Settings.theme.welllight}`,
|
|
|
|
},
|
|
|
|
|
|
|
|
"& .MuiTableHead-root .MuiTableRow-root": {
|
|
|
|
backgroundColor: Settings.theme.backgroundsecondary,
|
|
|
|
|
|
|
|
"& .MuiTableCell-root": {
|
|
|
|
color: Settings.theme.primary,
|
|
|
|
fontWeight: "bold",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
"& .MuiTableBody-root": {
|
|
|
|
"& .MuiTableRow-root:nth-of-type(odd)": {
|
|
|
|
backgroundColor: Settings.theme.well,
|
|
|
|
|
|
|
|
"& .MuiTableCell-root": {
|
|
|
|
color: Settings.theme.primarylight,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"& .MuiTableRow-root:nth-of-type(even)": {
|
|
|
|
backgroundColor: Settings.theme.backgroundsecondary,
|
|
|
|
|
|
|
|
"& .MuiTableCell-root": {
|
|
|
|
color: Settings.theme.primarylight,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
);
|
|
|
|
|
|
|
|
function ComparisonIcon({ isBetter }: { isBetter: boolean }): JSX.Element {
|
|
|
|
if (isBetter) {
|
|
|
|
return (
|
|
|
|
<Tooltip
|
|
|
|
title={
|
|
|
|
<>
|
|
|
|
Imported value is <b>larger</b>!
|
|
|
|
</>
|
|
|
|
}
|
|
|
|
>
|
|
|
|
<ThumbUpAlt color="success" />
|
|
|
|
</Tooltip>
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
return (
|
|
|
|
<Tooltip
|
|
|
|
title={
|
|
|
|
<>
|
|
|
|
Imported value is <b>smaller</b>!
|
|
|
|
</>
|
|
|
|
}
|
|
|
|
>
|
|
|
|
<ThumbDownAlt color="error" />
|
|
|
|
</Tooltip>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-22 16:53:16 +01:00
|
|
|
export interface IProps {
|
2022-01-20 20:55:28 +01:00
|
|
|
importString: string;
|
|
|
|
automatic: boolean;
|
2022-01-22 16:53:16 +01:00
|
|
|
router: IRouter;
|
2022-01-20 20:55:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
let initialAutosave = 0;
|
|
|
|
|
2022-01-22 16:53:16 +01:00
|
|
|
export function ImportSaveRoot(props: IProps): JSX.Element {
|
2022-01-20 20:55:28 +01:00
|
|
|
const classes = useStyles();
|
|
|
|
const [importData, setImportData] = useState<ImportData | undefined>();
|
|
|
|
const [currentData, setCurrentData] = useState<ImportData | undefined>();
|
|
|
|
const [importModalOpen, setImportModalOpen] = useState(false);
|
2022-01-22 16:53:16 +01:00
|
|
|
const [headback, setHeadback] = useState(false);
|
2022-01-20 20:55:28 +01:00
|
|
|
|
|
|
|
function handleGoBack(): void {
|
|
|
|
Settings.AutosaveInterval = initialAutosave;
|
2022-01-18 18:21:53 +01:00
|
|
|
pushImportResult(false);
|
2022-01-22 16:53:16 +01:00
|
|
|
props.router.allowRouting(true);
|
2022-04-07 01:30:08 +02:00
|
|
|
setHeadback(true);
|
2022-01-20 20:55:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
async function handleImport(): Promise<void> {
|
2022-01-22 16:53:16 +01:00
|
|
|
await saveObject.importGame(props.importString, true);
|
2022-01-18 18:21:53 +01:00
|
|
|
pushImportResult(true);
|
2022-01-20 20:55:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
// We want to disable autosave while we're in this mode
|
|
|
|
initialAutosave = Settings.AutosaveInterval;
|
|
|
|
Settings.AutosaveInterval = 0;
|
2022-01-22 16:53:16 +01:00
|
|
|
props.router.allowRouting(false);
|
2022-01-20 20:55:28 +01:00
|
|
|
}, []);
|
|
|
|
|
2022-01-22 16:53:16 +01:00
|
|
|
useEffect(() => {
|
|
|
|
if (headback) props.router.toTerminal();
|
|
|
|
}, [headback]);
|
|
|
|
|
2022-01-20 20:55:28 +01:00
|
|
|
useEffect(() => {
|
|
|
|
async function fetchData(): Promise<void> {
|
2022-01-22 16:53:16 +01:00
|
|
|
const dataBeingImported = await saveObject.getImportDataFromString(props.importString);
|
2022-01-20 20:55:28 +01:00
|
|
|
const dataCurrentlyInGame = await saveObject.getImportDataFromString(saveObject.getSaveString(true));
|
|
|
|
|
|
|
|
setImportData(dataBeingImported);
|
|
|
|
setCurrentData(dataCurrentlyInGame);
|
|
|
|
|
|
|
|
return Promise.resolve();
|
|
|
|
}
|
2022-01-22 16:53:16 +01:00
|
|
|
if (props.importString) fetchData();
|
|
|
|
}, [props.importString]);
|
2022-01-20 20:55:28 +01:00
|
|
|
|
|
|
|
if (!importData || !currentData) return <></>;
|
|
|
|
return (
|
|
|
|
<Box className={classes.root}>
|
|
|
|
<Typography variant="h4" sx={{ mb: 2 }}>
|
|
|
|
Import Save Comparison
|
|
|
|
</Typography>
|
2022-01-22 16:53:16 +01:00
|
|
|
{props.automatic && (
|
2022-01-20 20:55:28 +01:00
|
|
|
<Typography sx={{ mb: 2 }}>
|
|
|
|
We've found a <b>NEWER save</b> that you may want to use instead.
|
|
|
|
</Typography>
|
|
|
|
)}
|
|
|
|
<Typography variant="body1" sx={{ mb: 2 }}>
|
|
|
|
Your current game's data is on the left and the data that will be imported is on the right.
|
|
|
|
<br />
|
|
|
|
Please double check everything is fine before proceeding!
|
|
|
|
</Typography>
|
|
|
|
<TableContainer color="secondary" component={Paper}>
|
|
|
|
<Table>
|
|
|
|
<TableHead>
|
|
|
|
<TableRow>
|
|
|
|
<TableCell></TableCell>
|
|
|
|
<TableCell>Current Game</TableCell>
|
|
|
|
<TableCell>Being Imported</TableCell>
|
|
|
|
<TableCell></TableCell>
|
|
|
|
</TableRow>
|
|
|
|
</TableHead>
|
|
|
|
|
|
|
|
<TableBody>
|
|
|
|
<TableRow>
|
|
|
|
<TableCell>Game Identifier</TableCell>
|
|
|
|
<TableCell>{currentData.playerData?.identifier ?? "n/a"}</TableCell>
|
|
|
|
<TableCell>{importData.playerData?.identifier ?? "n/a"}</TableCell>
|
|
|
|
<TableCell>
|
|
|
|
{importData.playerData?.identifier !== currentData.playerData?.identifier && (
|
|
|
|
<Tooltip title="These are two different games!">
|
|
|
|
<WarningIcon color="warning" />
|
|
|
|
</Tooltip>
|
|
|
|
)}
|
|
|
|
</TableCell>
|
|
|
|
</TableRow>
|
|
|
|
<TableRow>
|
|
|
|
<TableCell>Playtime</TableCell>
|
|
|
|
<TableCell>{convertTimeMsToTimeElapsedString(currentData.playerData?.totalPlaytime ?? 0)}</TableCell>
|
|
|
|
<TableCell>{convertTimeMsToTimeElapsedString(importData.playerData?.totalPlaytime ?? 0)}</TableCell>
|
|
|
|
<TableCell>
|
|
|
|
{importData.playerData?.totalPlaytime !== currentData.playerData?.totalPlaytime && (
|
|
|
|
<ComparisonIcon
|
|
|
|
isBetter={
|
|
|
|
(importData.playerData?.totalPlaytime ?? 0) > (currentData.playerData?.totalPlaytime ?? 0)
|
|
|
|
}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
</TableCell>
|
|
|
|
</TableRow>
|
|
|
|
|
|
|
|
<TableRow>
|
|
|
|
<TableCell>Saved On</TableCell>
|
2022-01-22 16:53:16 +01:00
|
|
|
<TableCell>
|
2022-04-07 01:30:08 +02:00
|
|
|
{(currentData.playerData?.lastSave ?? 0) > 0
|
|
|
|
? new Date(currentData.playerData?.lastSave ?? 0).toLocaleString()
|
|
|
|
: "n/a"}
|
2022-01-22 16:53:16 +01:00
|
|
|
</TableCell>
|
|
|
|
<TableCell>
|
2022-04-07 01:30:08 +02:00
|
|
|
{(importData.playerData?.lastSave ?? 0) > 0
|
|
|
|
? new Date(importData.playerData?.lastSave ?? 0).toLocaleString()
|
|
|
|
: "n/a"}
|
2022-01-22 16:53:16 +01:00
|
|
|
</TableCell>
|
2022-01-20 20:55:28 +01:00
|
|
|
<TableCell>
|
|
|
|
{importData.playerData?.lastSave !== currentData.playerData?.lastSave && (
|
|
|
|
<ComparisonIcon
|
|
|
|
isBetter={(importData.playerData?.lastSave ?? 0) > (currentData.playerData?.lastSave ?? 0)}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
</TableCell>
|
|
|
|
</TableRow>
|
|
|
|
|
|
|
|
<TableRow>
|
|
|
|
<TableCell>Money</TableCell>
|
|
|
|
<TableCell>{numeralWrapper.formatMoney(currentData.playerData?.money ?? 0)}</TableCell>
|
|
|
|
<TableCell>{numeralWrapper.formatMoney(importData.playerData?.money ?? 0)}</TableCell>
|
|
|
|
<TableCell>
|
|
|
|
{importData.playerData?.money !== currentData.playerData?.money && (
|
|
|
|
<ComparisonIcon
|
|
|
|
isBetter={(importData.playerData?.money ?? 0) > (currentData.playerData?.money ?? 0)}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
</TableCell>
|
|
|
|
</TableRow>
|
|
|
|
|
|
|
|
<TableRow>
|
|
|
|
<TableCell>Hacking</TableCell>
|
|
|
|
<TableCell>{numeralWrapper.formatSkill(currentData.playerData?.hacking ?? 0)}</TableCell>
|
|
|
|
<TableCell>{numeralWrapper.formatSkill(importData.playerData?.hacking ?? 0)}</TableCell>
|
|
|
|
<TableCell>
|
|
|
|
{importData.playerData?.hacking !== currentData.playerData?.hacking && (
|
|
|
|
<ComparisonIcon
|
|
|
|
isBetter={(importData.playerData?.hacking ?? 0) > (currentData.playerData?.hacking ?? 0)}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
</TableCell>
|
|
|
|
</TableRow>
|
|
|
|
|
|
|
|
<TableRow>
|
|
|
|
<TableCell>Augmentations</TableCell>
|
|
|
|
<TableCell>{currentData.playerData?.augmentations}</TableCell>
|
|
|
|
<TableCell>{importData.playerData?.augmentations}</TableCell>
|
|
|
|
<TableCell>
|
|
|
|
{importData.playerData?.augmentations !== currentData.playerData?.augmentations && (
|
|
|
|
<ComparisonIcon
|
|
|
|
isBetter={
|
|
|
|
(importData.playerData?.augmentations ?? 0) > (currentData.playerData?.augmentations ?? 0)
|
|
|
|
}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
</TableCell>
|
|
|
|
</TableRow>
|
|
|
|
|
|
|
|
<TableRow>
|
|
|
|
<TableCell>Factions</TableCell>
|
|
|
|
<TableCell>{currentData.playerData?.factions}</TableCell>
|
|
|
|
<TableCell>{importData.playerData?.factions}</TableCell>
|
|
|
|
<TableCell>
|
|
|
|
{importData.playerData?.factions !== currentData.playerData?.factions && (
|
|
|
|
<ComparisonIcon
|
|
|
|
isBetter={(importData.playerData?.factions ?? 0) > (currentData.playerData?.factions ?? 0)}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
</TableCell>
|
|
|
|
</TableRow>
|
|
|
|
<TableRow>
|
|
|
|
<TableCell>Achievements</TableCell>
|
|
|
|
<TableCell>{currentData.playerData?.achievements}</TableCell>
|
|
|
|
<TableCell>{importData.playerData?.achievements}</TableCell>
|
|
|
|
<TableCell>
|
|
|
|
{importData.playerData?.achievements !== currentData.playerData?.achievements && (
|
|
|
|
<ComparisonIcon
|
|
|
|
isBetter={(importData.playerData?.achievements ?? 0) > (currentData.playerData?.achievements ?? 0)}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
</TableCell>
|
|
|
|
</TableRow>
|
|
|
|
|
|
|
|
<TableRow>
|
|
|
|
<TableCell>Source Files</TableCell>
|
|
|
|
<TableCell>{currentData.playerData?.sourceFiles}</TableCell>
|
|
|
|
<TableCell>{importData.playerData?.sourceFiles}</TableCell>
|
|
|
|
<TableCell>
|
|
|
|
{importData.playerData?.sourceFiles !== currentData.playerData?.sourceFiles && (
|
|
|
|
<ComparisonIcon
|
|
|
|
isBetter={(importData.playerData?.sourceFiles ?? 0) > (currentData.playerData?.sourceFiles ?? 0)}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
</TableCell>
|
|
|
|
</TableRow>
|
|
|
|
|
|
|
|
<TableRow>
|
|
|
|
<TableCell>BitNode</TableCell>
|
|
|
|
<TableCell>
|
|
|
|
{currentData.playerData?.bitNode}-{currentData.playerData?.bitNodeLevel}
|
|
|
|
</TableCell>
|
|
|
|
<TableCell>
|
|
|
|
{importData.playerData?.bitNode}-{importData.playerData?.bitNodeLevel}
|
|
|
|
</TableCell>
|
|
|
|
<TableCell></TableCell>
|
|
|
|
</TableRow>
|
|
|
|
</TableBody>
|
|
|
|
</Table>
|
|
|
|
</TableContainer>
|
|
|
|
|
|
|
|
<Box sx={{ display: "flex", justifyContent: "flex-end" }}>
|
|
|
|
<ButtonGroup>
|
|
|
|
<Button onClick={handleGoBack} sx={{ my: 2 }} startIcon={<ArrowBackIcon />} color="secondary">
|
|
|
|
Take me back!
|
|
|
|
</Button>
|
|
|
|
<Button
|
|
|
|
onClick={() => setImportModalOpen(true)}
|
|
|
|
sx={{ my: 2 }}
|
|
|
|
startIcon={<DirectionsRunIcon />}
|
|
|
|
color="warning"
|
|
|
|
>
|
|
|
|
Proceed with import
|
|
|
|
</Button>
|
|
|
|
</ButtonGroup>
|
|
|
|
<ConfirmationModal
|
|
|
|
open={importModalOpen}
|
|
|
|
onClose={() => setImportModalOpen(false)}
|
|
|
|
onConfirm={handleImport}
|
|
|
|
confirmationText={
|
|
|
|
<>
|
|
|
|
Importing new save game data will <strong>completely wipe</strong> the current game data!
|
|
|
|
<br />
|
|
|
|
</>
|
|
|
|
}
|
|
|
|
/>
|
|
|
|
</Box>
|
|
|
|
</Box>
|
|
|
|
);
|
|
|
|
}
|