mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-19 04:35:46 +01:00
UI: Correct behavior of "back" button on faction augs page
Plus router refactoring
This commit is contained in:
parent
9a0a843ffc
commit
1af01401d9
@ -1,6 +1,7 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { Modal } from "../../ui/React/Modal";
|
import { Modal } from "../../ui/React/Modal";
|
||||||
import { Router } from "../../ui/GameRoot";
|
import { Router } from "../../ui/GameRoot";
|
||||||
|
import { Page } from "../../ui/Router";
|
||||||
import { EventEmitter } from "../../utils/EventEmitter";
|
import { EventEmitter } from "../../utils/EventEmitter";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
@ -10,7 +11,7 @@ export const BitFlumeEvent = new EventEmitter<[]>();
|
|||||||
export function BitFlumeModal(): React.ReactElement {
|
export function BitFlumeModal(): React.ReactElement {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
function flume(): void {
|
function flume(): void {
|
||||||
Router.toBitVerse(true, false);
|
Router.toPage(Page.BitVerse, { flume: true, quick: false });
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import { BlackOperationName, FactionName } from "@enums";
|
|||||||
import { BlackOpList } from "./BlackOpList";
|
import { BlackOpList } from "./BlackOpList";
|
||||||
import { Bladeburner } from "../Bladeburner";
|
import { Bladeburner } from "../Bladeburner";
|
||||||
import { Router } from "../../ui/GameRoot";
|
import { Router } from "../../ui/GameRoot";
|
||||||
|
import { Page } from "../../ui/Router";
|
||||||
import { CorruptableText } from "../../ui/React/CorruptableText";
|
import { CorruptableText } from "../../ui/React/CorruptableText";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
@ -28,7 +29,7 @@ export function BlackOpPage(props: IProps): React.ReactElement {
|
|||||||
losses.
|
losses.
|
||||||
</Typography>
|
</Typography>
|
||||||
{props.bladeburner.blackops[BlackOperationName.OperationDaedalus] ? (
|
{props.bladeburner.blackops[BlackOperationName.OperationDaedalus] ? (
|
||||||
<Button sx={{ my: 1, p: 1 }} onClick={() => Router.toBitVerse(false, false)}>
|
<Button sx={{ my: 1, p: 1 }} onClick={() => Router.toPage(Page.BitVerse, { flume: false, quick: false })}>
|
||||||
<CorruptableText content="Destroy w0rld_d34mon"></CorruptableText>
|
<CorruptableText content="Destroy w0rld_d34mon"></CorruptableText>
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
|
@ -8,6 +8,7 @@ import { Money } from "../../ui/React/Money";
|
|||||||
import { formatNumberNoSuffix, formatPopulation, formatBigNumber } from "../../ui/formatNumber";
|
import { formatNumberNoSuffix, formatPopulation, formatBigNumber } from "../../ui/formatNumber";
|
||||||
import { Factions } from "../../Faction/Factions";
|
import { Factions } from "../../Faction/Factions";
|
||||||
import { Router } from "../../ui/GameRoot";
|
import { Router } from "../../ui/GameRoot";
|
||||||
|
import { Page } from "../../ui/Router";
|
||||||
import { joinFaction } from "../../Faction/FactionHelpers";
|
import { joinFaction } from "../../Faction/FactionHelpers";
|
||||||
import { Bladeburner } from "../Bladeburner";
|
import { Bladeburner } from "../Bladeburner";
|
||||||
|
|
||||||
@ -34,7 +35,7 @@ export function Stats(props: IProps): React.ReactElement {
|
|||||||
joinFaction(faction);
|
joinFaction(faction);
|
||||||
}
|
}
|
||||||
|
|
||||||
Router.toFaction(faction);
|
Router.toPage(Page.Faction, { faction });
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -16,6 +16,7 @@ import { Player } from "@player";
|
|||||||
import { FactionName } from "@enums";
|
import { FactionName } from "@enums";
|
||||||
import { Money } from "../../ui/React/Money";
|
import { Money } from "../../ui/React/Money";
|
||||||
import { Router } from "../../ui/GameRoot";
|
import { Router } from "../../ui/GameRoot";
|
||||||
|
import { Page } from "../../ui/Router";
|
||||||
import { Bladeburner } from "../../Bladeburner/Bladeburner";
|
import { Bladeburner } from "../../Bladeburner/Bladeburner";
|
||||||
import { GangConstants } from "../../Gang/data/Constants";
|
import { GangConstants } from "../../Gang/data/Constants";
|
||||||
import { checkForMessagesToSend } from "../../Message/MessageHelpers";
|
import { checkForMessagesToSend } from "../../Message/MessageHelpers";
|
||||||
@ -37,10 +38,10 @@ export function General(): React.ReactElement {
|
|||||||
const upgradeRam = () => (Player.getHomeComputer().maxRam *= 2);
|
const upgradeRam = () => (Player.getHomeComputer().maxRam *= 2);
|
||||||
|
|
||||||
// Node-clearing functions
|
// Node-clearing functions
|
||||||
const quickB1tFlum3 = () => Router.toBitVerse(true, true);
|
const quickB1tFlum3 = () => Router.toPage(Page.BitVerse, { flume: true, quick: true });
|
||||||
const b1tflum3 = () => Router.toBitVerse(true, false);
|
const b1tflum3 = () => Router.toPage(Page.BitVerse, { flume: true, quick: false });
|
||||||
const quickHackW0r1dD43m0n = () => Router.toBitVerse(false, true);
|
const quickHackW0r1dD43m0n = () => Router.toPage(Page.BitVerse, { flume: false, quick: true });
|
||||||
const hackW0r1dD43m0n = () => Router.toBitVerse(false, false);
|
const hackW0r1dD43m0n = () => Router.toPage(Page.BitVerse, { flume: false, quick: false });
|
||||||
|
|
||||||
// Corp functions
|
// Corp functions
|
||||||
const createCorporation = () => {
|
const createCorporation = () => {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { Player } from "@player";
|
import { Player } from "@player";
|
||||||
import { Router } from "./ui/GameRoot";
|
import { Router } from "./ui/GameRoot";
|
||||||
|
import { Page } from "./ui/Router";
|
||||||
import { Terminal } from "./Terminal";
|
import { Terminal } from "./Terminal";
|
||||||
import { SnackbarEvents } from "./ui/React/Snackbar";
|
import { SnackbarEvents } from "./ui/React/Snackbar";
|
||||||
import { ToastVariant } from "@enums";
|
import { ToastVariant } from "@enums";
|
||||||
@ -28,8 +29,8 @@ declare global {
|
|||||||
triggerGameExport: () => void;
|
triggerGameExport: () => void;
|
||||||
triggerScriptsExport: () => void;
|
triggerScriptsExport: () => void;
|
||||||
getSaveData: () => { save: string; fileName: string };
|
getSaveData: () => { save: string; fileName: string };
|
||||||
getSaveInfo: (base64save: string) => Promise<ImportPlayerData | undefined>;
|
getSaveInfo: (base64Save: string) => Promise<ImportPlayerData | undefined>;
|
||||||
pushSaveData: (base64save: string, automatic?: boolean) => void;
|
pushSaveData: (base64Save: string, automatic?: boolean) => void;
|
||||||
};
|
};
|
||||||
electronBridge: {
|
electronBridge: {
|
||||||
send: (channel: string, data?: unknown) => void;
|
send: (channel: string, data?: unknown) => void;
|
||||||
@ -137,16 +138,17 @@ function initSaveFunctions(): void {
|
|||||||
fileName: saveObject.getSaveFileName(),
|
fileName: saveObject.getSaveFileName(),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
getSaveInfo: async (base64save: string): Promise<ImportPlayerData | undefined> => {
|
getSaveInfo: async (base64Save: string): Promise<ImportPlayerData | undefined> => {
|
||||||
try {
|
try {
|
||||||
const data = await saveObject.getImportDataFromString(base64save);
|
const data = await saveObject.getImportDataFromString(base64Save);
|
||||||
return data.playerData;
|
return data.playerData;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
pushSaveData: (base64save: string, automatic = false): void => Router.toImportSave(base64save, automatic),
|
pushSaveData: (base64Save: string, automatic = false): void =>
|
||||||
|
Router.toPage(Page.ImportSave, { base64Save, automatic }),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Will be consumed by the electron wrapper.
|
// Will be consumed by the electron wrapper.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Box, Button, Tooltip, Typography, Paper, Container } from "@mui/material";
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { Box, Button, Tooltip, Typography, Paper, Container } from "@mui/material";
|
||||||
|
|
||||||
import { Augmentations } from "../../Augmentation/Augmentations";
|
import { Augmentations } from "../../Augmentation/Augmentations";
|
||||||
import { getAugCost, getGenericAugmentationPriceMultiplier } from "../../Augmentation/AugmentationHelpers";
|
import { getAugCost, getGenericAugmentationPriceMultiplier } from "../../Augmentation/AugmentationHelpers";
|
||||||
@ -11,22 +11,18 @@ import { Player } from "@player";
|
|||||||
import { formatBigNumber } from "../../ui/formatNumber";
|
import { formatBigNumber } from "../../ui/formatNumber";
|
||||||
import { Favor } from "../../ui/React/Favor";
|
import { Favor } from "../../ui/React/Favor";
|
||||||
import { Reputation } from "../../ui/React/Reputation";
|
import { Reputation } from "../../ui/React/Reputation";
|
||||||
|
import { Router } from "../../ui/GameRoot";
|
||||||
import { Faction } from "../Faction";
|
import { Faction } from "../Faction";
|
||||||
import { getFactionAugmentationsFiltered, hasAugmentationPrereqs, purchaseAugmentation } from "../FactionHelpers";
|
import { getFactionAugmentationsFiltered, hasAugmentationPrereqs, purchaseAugmentation } from "../FactionHelpers";
|
||||||
import { CONSTANTS } from "../../Constants";
|
import { CONSTANTS } from "../../Constants";
|
||||||
import { useRerender } from "../../ui/React/hooks";
|
import { useRerender } from "../../ui/React/hooks";
|
||||||
|
|
||||||
interface IProps {
|
|
||||||
faction: Faction;
|
|
||||||
routeToMainPage: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Root React Component for displaying a faction's "Purchase Augmentations" page */
|
/** Root React Component for displaying a faction's "Purchase Augmentations" page */
|
||||||
export function AugmentationsPage(props: IProps): React.ReactElement {
|
export function AugmentationsPage({ faction }: { faction: Faction }): React.ReactElement {
|
||||||
const rerender = useRerender();
|
const rerender = useRerender();
|
||||||
|
|
||||||
function getAugs(): AugmentationName[] {
|
function getAugs(): AugmentationName[] {
|
||||||
return getFactionAugmentationsFiltered(props.faction);
|
return getFactionAugmentationsFiltered(faction);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAugsSorted(): AugmentationName[] {
|
function getAugsSorted(): AugmentationName[] {
|
||||||
@ -66,7 +62,7 @@ export function AugmentationsPage(props: IProps): React.ReactElement {
|
|||||||
const aug = Augmentations[augName];
|
const aug = Augmentations[augName];
|
||||||
const augCosts = getAugCost(aug);
|
const augCosts = getAugCost(aug);
|
||||||
const repCost = augCosts.repCost;
|
const repCost = augCosts.repCost;
|
||||||
const hasReq = props.faction.playerReputation >= repCost;
|
const hasReq = faction.playerReputation >= repCost;
|
||||||
const hasRep = hasAugmentationPrereqs(aug);
|
const hasRep = hasAugmentationPrereqs(aug);
|
||||||
const hasCost = augCosts.moneyCost !== 0 && Player.money > augCosts.moneyCost;
|
const hasCost = augCosts.moneyCost !== 0 && Player.money > augCosts.moneyCost;
|
||||||
return hasCost && hasReq && hasRep;
|
return hasCost && hasReq && hasRep;
|
||||||
@ -126,7 +122,7 @@ export function AugmentationsPage(props: IProps): React.ReactElement {
|
|||||||
const owned = augs.filter((aug) => !purchasable.includes(aug));
|
const owned = augs.filter((aug) => !purchasable.includes(aug));
|
||||||
|
|
||||||
const multiplierComponent =
|
const multiplierComponent =
|
||||||
props.faction.name !== FactionName.ShadowsOfAnarchy ? (
|
faction.name !== FactionName.ShadowsOfAnarchy ? (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
title={
|
title={
|
||||||
<Typography>
|
<Typography>
|
||||||
@ -171,27 +167,27 @@ export function AugmentationsPage(props: IProps): React.ReactElement {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Container disableGutters maxWidth="lg" sx={{ mx: 0 }}>
|
<Container disableGutters maxWidth="lg" sx={{ mx: 0 }}>
|
||||||
<Button onClick={props.routeToMainPage}>Back</Button>
|
<Button onClick={() => Router.back()}>Back</Button>
|
||||||
<Typography variant="h4">Faction Augmentations - {props.faction.name}</Typography>
|
<Typography variant="h4">Faction Augmentations - {faction.name}</Typography>
|
||||||
<Paper sx={{ p: 1, mb: 1 }}>
|
<Paper sx={{ p: 1, mb: 1 }}>
|
||||||
<Typography>
|
<Typography>
|
||||||
These are all of the Augmentations that are available to purchase from <b>{props.faction.name}</b>.
|
These are all of the Augmentations that are available to purchase from <b>{faction.name}</b>. Augmentations
|
||||||
Augmentations are powerful upgrades that will enhance your abilities.
|
are powerful upgrades that will enhance your abilities.
|
||||||
<br />
|
<br />
|
||||||
</Typography>
|
</Typography>
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
display: "grid",
|
display: "grid",
|
||||||
gridTemplateColumns: `repeat(${props.faction.name === FactionName.ShadowsOfAnarchy ? "2" : "3"}, 1fr)`,
|
gridTemplateColumns: `repeat(${faction.name === FactionName.ShadowsOfAnarchy ? "2" : "3"}, 1fr)`,
|
||||||
justifyItems: "center",
|
justifyItems: "center",
|
||||||
my: 1,
|
my: 1,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<>{multiplierComponent}</>
|
<>{multiplierComponent}</>
|
||||||
<Typography>
|
<Typography>
|
||||||
<b>Reputation:</b> <Reputation reputation={props.faction.playerReputation} />
|
<b>Reputation:</b> <Reputation reputation={faction.playerReputation} />
|
||||||
<br />
|
<br />
|
||||||
<b>Favor:</b> <Favor favor={Math.floor(props.faction.favor)} />
|
<b>Favor:</b> <Favor favor={Math.floor(faction.favor)} />
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
<Box sx={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)" }}>
|
<Box sx={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)" }}>
|
||||||
@ -216,7 +212,7 @@ export function AugmentationsPage(props: IProps): React.ReactElement {
|
|||||||
const costs = getAugCost(aug);
|
const costs = getAugCost(aug);
|
||||||
return (
|
return (
|
||||||
hasAugmentationPrereqs(aug) &&
|
hasAugmentationPrereqs(aug) &&
|
||||||
props.faction.playerReputation >= costs.repCost &&
|
faction.playerReputation >= costs.repCost &&
|
||||||
(costs.moneyCost === 0 || Player.money > costs.moneyCost)
|
(costs.moneyCost === 0 || Player.money > costs.moneyCost)
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
@ -224,12 +220,12 @@ export function AugmentationsPage(props: IProps): React.ReactElement {
|
|||||||
if (!Settings.SuppressBuyAugmentationConfirmation) {
|
if (!Settings.SuppressBuyAugmentationConfirmation) {
|
||||||
showModal(true);
|
showModal(true);
|
||||||
} else {
|
} else {
|
||||||
purchaseAugmentation(aug, props.faction);
|
purchaseAugmentation(aug, faction);
|
||||||
rerender();
|
rerender();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
rep={props.faction.playerReputation}
|
rep={faction.playerReputation}
|
||||||
faction={props.faction}
|
faction={faction}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
*/
|
*/
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
|
|
||||||
import { AugmentationsPage } from "./AugmentationsPage";
|
|
||||||
import { DonateOption } from "./DonateOption";
|
import { DonateOption } from "./DonateOption";
|
||||||
import { Info } from "./Info";
|
import { Info } from "./Info";
|
||||||
import { Option } from "./Option";
|
import { Option } from "./Option";
|
||||||
@ -24,10 +23,9 @@ import { FactionWork } from "../../Work/FactionWork";
|
|||||||
import { useRerender } from "../../ui/React/hooks";
|
import { useRerender } from "../../ui/React/hooks";
|
||||||
import { repNeededToDonate } from "../formulas/donation";
|
import { repNeededToDonate } from "../formulas/donation";
|
||||||
|
|
||||||
interface IProps {
|
type FactionRootProps = {
|
||||||
faction: Faction;
|
faction: Faction;
|
||||||
augPage: boolean;
|
};
|
||||||
}
|
|
||||||
|
|
||||||
// Info text for all options on the UI
|
// Info text for all options on the UI
|
||||||
const hackingContractsInfo =
|
const hackingContractsInfo =
|
||||||
@ -148,11 +146,8 @@ function MainPage({ faction, rerender, onAugmentations }: IMainProps): React.Rea
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function FactionRoot(props: IProps): React.ReactElement {
|
export function FactionRoot({ faction }: FactionRootProps): React.ReactElement {
|
||||||
const rerender = useRerender(200);
|
const rerender = useRerender(200);
|
||||||
const [purchasingAugs, setPurchasingAugs] = useState(props.augPage);
|
|
||||||
|
|
||||||
const faction = props.faction;
|
|
||||||
|
|
||||||
if (!Player.factions.includes(faction.name)) {
|
if (!Player.factions.includes(faction.name)) {
|
||||||
return (
|
return (
|
||||||
@ -165,9 +160,11 @@ export function FactionRoot(props: IProps): React.ReactElement {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return purchasingAugs ? (
|
return (
|
||||||
<AugmentationsPage faction={faction} routeToMainPage={() => setPurchasingAugs(false)} />
|
<MainPage
|
||||||
) : (
|
rerender={rerender}
|
||||||
<MainPage rerender={rerender} faction={faction} onAugmentations={() => setPurchasingAugs(true)} />
|
faction={faction}
|
||||||
|
onAugmentations={() => Router.toPage(Page.FactionAugmentations, { faction })}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,18 @@
|
|||||||
import type { Faction } from "../Faction";
|
|
||||||
|
|
||||||
import React, { useEffect } from "react";
|
import React, { useEffect } from "react";
|
||||||
import { Explore, Info, LastPage, LocalPolice, NewReleases, Report, SportsMma } from "@mui/icons-material";
|
import { Explore, Info, LastPage, LocalPolice, NewReleases, Report, SportsMma } from "@mui/icons-material";
|
||||||
import { Box, Button, Container, Paper, Tooltip, Typography, useTheme } from "@mui/material";
|
import { Box, Button, Container, Paper, Tooltip, Typography, useTheme } from "@mui/material";
|
||||||
|
|
||||||
import { Player } from "@player";
|
import { Player } from "@player";
|
||||||
|
import { FactionName } from "@enums";
|
||||||
|
|
||||||
import { Settings } from "../../Settings/Settings";
|
import { Settings } from "../../Settings/Settings";
|
||||||
import { formatFavor, formatReputation } from "../../ui/formatNumber";
|
import { formatFavor, formatReputation } from "../../ui/formatNumber";
|
||||||
import { Router } from "../../ui/GameRoot";
|
import { Router } from "../../ui/GameRoot";
|
||||||
import { FactionName } from "@enums";
|
import { Page } from "../../ui/Router";
|
||||||
|
import { useRerender } from "../../ui/React/hooks";
|
||||||
|
import { Faction } from "../Faction";
|
||||||
import { getFactionAugmentationsFiltered, joinFaction } from "../FactionHelpers";
|
import { getFactionAugmentationsFiltered, joinFaction } from "../FactionHelpers";
|
||||||
import { Factions } from "../Factions";
|
import { Factions } from "../Factions";
|
||||||
import { useRerender } from "../../ui/React/hooks";
|
|
||||||
|
|
||||||
export const InvitationsSeen: string[] = [];
|
export const InvitationsSeen: string[] = [];
|
||||||
|
|
||||||
@ -53,11 +55,11 @@ const FactionElement = (props: FactionElementProps): React.ReactElement => {
|
|||||||
const augsLeft = getFactionAugmentationsFiltered(props.faction).filter((aug) => !Player.hasAugmentation(aug)).length;
|
const augsLeft = getFactionAugmentationsFiltered(props.faction).filter((aug) => !Player.hasAugmentation(aug)).length;
|
||||||
|
|
||||||
function openFaction(faction: Faction): void {
|
function openFaction(faction: Faction): void {
|
||||||
Router.toFaction(faction);
|
Router.toPage(Page.Faction, { faction });
|
||||||
}
|
}
|
||||||
|
|
||||||
function openFactionAugPage(faction: Faction): void {
|
function openFactionAugPage(faction: Faction): void {
|
||||||
Router.toFaction(faction, true);
|
Router.toPage(Page.FactionAugmentations, { faction });
|
||||||
}
|
}
|
||||||
|
|
||||||
function acceptInvitation(event: React.MouseEvent<HTMLButtonElement>, faction: FactionName): void {
|
function acceptInvitation(event: React.MouseEvent<HTMLButtonElement>, faction: FactionName): void {
|
||||||
|
@ -95,7 +95,7 @@ export const GameOptionsSidebar = (props: IProps): React.ReactElement => {
|
|||||||
|
|
||||||
function compareSaveGame(): void {
|
function compareSaveGame(): void {
|
||||||
if (!importData) return;
|
if (!importData) return;
|
||||||
Router.toImportSave(importData.base64);
|
Router.toPage(Page.ImportSave, { base64Save: importData.base64 });
|
||||||
setImportSaveOpen(false);
|
setImportSaveOpen(false);
|
||||||
setImportData(null);
|
setImportData(null);
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ function toLocation(location: Location): void {
|
|||||||
} else if (location.name === LocationName.WorldStockExchange) {
|
} else if (location.name === LocationName.WorldStockExchange) {
|
||||||
Router.toPage(Page.StockMarket);
|
Router.toPage(Page.StockMarket);
|
||||||
} else {
|
} else {
|
||||||
Router.toLocation(location);
|
Router.toPage(Page.Location, { location });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,11 +151,10 @@ export function CompanyLocation(props: IProps): React.ReactElement {
|
|||||||
if (!e.isTrusted) {
|
if (!e.isTrusted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const loc = location;
|
if (!location.infiltrationData)
|
||||||
if (!loc.infiltrationData)
|
|
||||||
throw new Error(`trying to start infiltration at ${props.locName} but the infiltrationData is null`);
|
throw new Error(`trying to start infiltration at ${props.locName} but the infiltrationData is null`);
|
||||||
|
|
||||||
Router.toInfiltration(loc);
|
Router.toPage(Page.Infiltration, { location });
|
||||||
}
|
}
|
||||||
|
|
||||||
function work(e: React.MouseEvent<HTMLElement>): void {
|
function work(e: React.MouseEvent<HTMLElement>): void {
|
||||||
|
@ -23,8 +23,8 @@ import { findCrime } from "../Crime/CrimeHelpers";
|
|||||||
import { CompanyPositions } from "../Company/CompanyPositions";
|
import { CompanyPositions } from "../Company/CompanyPositions";
|
||||||
import { DarkWebItems } from "../DarkWeb/DarkWebItems";
|
import { DarkWebItems } from "../DarkWeb/DarkWebItems";
|
||||||
import { Router } from "../ui/GameRoot";
|
import { Router } from "../ui/GameRoot";
|
||||||
import { SpecialServers } from "../Server/data/SpecialServers";
|
|
||||||
import { Page } from "../ui/Router";
|
import { Page } from "../ui/Router";
|
||||||
|
import { SpecialServers } from "../Server/data/SpecialServers";
|
||||||
import { Locations } from "../Locations/Locations";
|
import { Locations } from "../Locations/Locations";
|
||||||
import { GetServer } from "../Server/AllServers";
|
import { GetServer } from "../Server/AllServers";
|
||||||
import { Programs } from "../Programs/Programs";
|
import { Programs } from "../Programs/Programs";
|
||||||
@ -231,7 +231,7 @@ export function NetscriptSingularity(): InternalAPI<ISingularity> {
|
|||||||
} else if (location.name === LocationName.WorldStockExchange) {
|
} else if (location.name === LocationName.WorldStockExchange) {
|
||||||
Router.toPage(Page.StockMarket);
|
Router.toPage(Page.StockMarket);
|
||||||
} else {
|
} else {
|
||||||
Router.toLocation(location);
|
Router.toPage(Page.Location, { location });
|
||||||
}
|
}
|
||||||
Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain / 50000);
|
Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain / 50000);
|
||||||
return true;
|
return true;
|
||||||
@ -559,7 +559,7 @@ export function NetscriptSingularity(): InternalAPI<ISingularity> {
|
|||||||
server.backdoorInstalled = true;
|
server.backdoorInstalled = true;
|
||||||
|
|
||||||
if (SpecialServers.WorldDaemon === server.hostname) {
|
if (SpecialServers.WorldDaemon === server.hostname) {
|
||||||
return Router.toBitVerse(false, false);
|
return Router.toPage(Page.BitVerse, { flume: false, quick: false });
|
||||||
}
|
}
|
||||||
// Manunally check for faction invites
|
// Manunally check for faction invites
|
||||||
Engine.Counters.checkFactionInvitations = 0;
|
Engine.Counters.checkFactionInvitations = 0;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import type { Augmentation } from "../../../Augmentation/Augmentation";
|
import type { Augmentation } from "../../../Augmentation/Augmentation";
|
||||||
|
|
||||||
import { Player } from "@player";
|
import { Player } from "@player";
|
||||||
import { AugmentationName, LocationName } from "@enums";
|
import { AugmentationName } from "@enums";
|
||||||
|
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { CheckBox, CheckBoxOutlineBlank, Construction } from "@mui/icons-material";
|
import { CheckBox, CheckBoxOutlineBlank, Construction } from "@mui/icons-material";
|
||||||
@ -11,7 +11,6 @@ import { GraftingWork } from "../../../Work/GraftingWork";
|
|||||||
import { Augmentations } from "../../../Augmentation/Augmentations";
|
import { Augmentations } from "../../../Augmentation/Augmentations";
|
||||||
import { CONSTANTS } from "../../../Constants";
|
import { CONSTANTS } from "../../../Constants";
|
||||||
import { hasAugmentationPrereqs } from "../../../Faction/FactionHelpers";
|
import { hasAugmentationPrereqs } from "../../../Faction/FactionHelpers";
|
||||||
import { Locations } from "../../../Locations/Locations";
|
|
||||||
import { PurchaseAugmentationsOrderSetting } from "../../../Settings/SettingEnums";
|
import { PurchaseAugmentationsOrderSetting } from "../../../Settings/SettingEnums";
|
||||||
import { Settings } from "../../../Settings/Settings";
|
import { Settings } from "../../../Settings/Settings";
|
||||||
import { Router } from "../../../ui/GameRoot";
|
import { Router } from "../../../ui/GameRoot";
|
||||||
@ -87,7 +86,7 @@ export const GraftingRoot = (): React.ReactElement => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Container disableGutters maxWidth="lg" sx={{ mx: 0 }}>
|
<Container disableGutters maxWidth="lg" sx={{ mx: 0 }}>
|
||||||
<Button onClick={() => Router.toLocation(Locations[LocationName.NewTokyoVitaLife])}>Back</Button>
|
<Button onClick={() => Router.back()}>Back</Button>
|
||||||
<Typography variant="h4">Grafting Laboratory</Typography>
|
<Typography variant="h4">Grafting Laboratory</Typography>
|
||||||
<Typography>
|
<Typography>
|
||||||
You find yourself in a secret laboratory, owned by a mysterious researcher.
|
You find yourself in a secret laboratory, owned by a mysterious researcher.
|
||||||
|
@ -41,7 +41,7 @@ import PublicIcon from "@mui/icons-material/Public";
|
|||||||
import LiveHelpIcon from "@mui/icons-material/LiveHelp";
|
import LiveHelpIcon from "@mui/icons-material/LiveHelp";
|
||||||
|
|
||||||
import { Router } from "../../ui/GameRoot";
|
import { Router } from "../../ui/GameRoot";
|
||||||
import { Page, SimplePage } from "../../ui/Router";
|
import { Page, isSimplePage } from "../../ui/Router";
|
||||||
import { SidebarAccordion } from "./SidebarAccordion";
|
import { SidebarAccordion } from "./SidebarAccordion";
|
||||||
import { Player } from "@player";
|
import { Player } from "@player";
|
||||||
import { CONSTANTS } from "../../Constants";
|
import { CONSTANTS } from "../../Constants";
|
||||||
@ -104,11 +104,7 @@ const useStyles = makeStyles((theme: Theme) =>
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
interface IProps {
|
export function SidebarRoot(props: { page: Page }): React.ReactElement {
|
||||||
page: Page;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function SidebarRoot(props: IProps): React.ReactElement {
|
|
||||||
useRerender(200);
|
useRerender(200);
|
||||||
|
|
||||||
let flash: Page | null = null;
|
let flash: Page | null = null;
|
||||||
@ -239,11 +235,11 @@ export function SidebarRoot(props: IProps): React.ReactElement {
|
|||||||
const clickPage = useCallback(
|
const clickPage = useCallback(
|
||||||
(page: Page) => {
|
(page: Page) => {
|
||||||
if (page === Page.Job) {
|
if (page === Page.Job) {
|
||||||
Router.toJob(Locations[Object.keys(Player.jobs)[0]]);
|
Router.toPage(page, { location: Locations[Object.keys(Player.jobs)[0]] });
|
||||||
} else if (page == Page.ScriptEditor) {
|
} else if (page == Page.ScriptEditor) {
|
||||||
Router.toScriptEditor();
|
Router.toPage(page, {});
|
||||||
} else if ((Object.values(SimplePage) as Page[]).includes(page)) {
|
} else if (isSimplePage(page)) {
|
||||||
Router.toPage(page as SimplePage);
|
Router.toPage(page);
|
||||||
} else {
|
} else {
|
||||||
throw new Error("Can't handle click on Page " + page);
|
throw new Error("Can't handle click on Page " + page);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { Output, Link, RawOutput, TTimer } from "./OutputTypes";
|
import { Output, Link, RawOutput, TTimer } from "./OutputTypes";
|
||||||
import { Router } from "../ui/GameRoot";
|
import { Router } from "../ui/GameRoot";
|
||||||
|
import { Page } from "../ui/Router";
|
||||||
import { Player } from "@player";
|
import { Player } from "@player";
|
||||||
import { HacknetServer } from "../Hacknet/HacknetServer";
|
import { HacknetServer } from "../Hacknet/HacknetServer";
|
||||||
import { BaseServer } from "../Server/BaseServer";
|
import { BaseServer } from "../Server/BaseServer";
|
||||||
@ -206,7 +207,7 @@ export class Terminal {
|
|||||||
// Success!
|
// Success!
|
||||||
server.backdoorInstalled = true;
|
server.backdoorInstalled = true;
|
||||||
if (SpecialServers.WorldDaemon === server.hostname) {
|
if (SpecialServers.WorldDaemon === server.hostname) {
|
||||||
Router.toBitVerse(false, false);
|
Router.toPage(Page.BitVerse, { flume: false, quick: false });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Manunally check for faction invites
|
// Manunally check for faction invites
|
||||||
@ -301,7 +302,7 @@ export class Terminal {
|
|||||||
if (Player.bitNodeN == null) {
|
if (Player.bitNodeN == null) {
|
||||||
Player.bitNodeN = 1;
|
Player.bitNodeN = 1;
|
||||||
}
|
}
|
||||||
Router.toBitVerse(false, false);
|
Router.toPage(Page.BitVerse, { flume: false, quick: false });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Manunally check for faction invites
|
// Manunally check for faction invites
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Terminal } from "../../../Terminal";
|
import { Terminal } from "../../../Terminal";
|
||||||
import { ScriptEditorRouteOptions } from "../../../ui/Router";
|
import { ScriptEditorRouteOptions, Page } from "../../../ui/Router";
|
||||||
import { Router } from "../../../ui/GameRoot";
|
import { Router } from "../../../ui/GameRoot";
|
||||||
import { BaseServer } from "../../../Server/BaseServer";
|
import { BaseServer } from "../../../Server/BaseServer";
|
||||||
import { CursorPositions } from "../../../ScriptEditor/CursorPositions";
|
import { CursorPositions } from "../../../ScriptEditor/CursorPositions";
|
||||||
@ -26,17 +26,17 @@ export async function main(ns) {
|
|||||||
export function commonEditor(
|
export function commonEditor(
|
||||||
command: string,
|
command: string,
|
||||||
{ args, server }: EditorParameters,
|
{ args, server }: EditorParameters,
|
||||||
scriptEditorRouteOptions?: ScriptEditorRouteOptions,
|
options?: ScriptEditorRouteOptions,
|
||||||
): void {
|
): void {
|
||||||
if (args.length < 1) return Terminal.error(`Incorrect usage of ${command} command. Usage: ${command} [scriptname]`);
|
if (args.length < 1) return Terminal.error(`Incorrect usage of ${command} command. Usage: ${command} [scriptname]`);
|
||||||
const filesToOpen = new Map<ScriptFilePath | TextFilePath, string>();
|
const files = new Map<ScriptFilePath | TextFilePath, string>();
|
||||||
for (const arg of args) {
|
for (const arg of args) {
|
||||||
const pattern = String(arg);
|
const pattern = String(arg);
|
||||||
|
|
||||||
// Glob of existing files
|
// Glob of existing files
|
||||||
if (pattern.includes("*") || pattern.includes("?")) {
|
if (pattern.includes("*") || pattern.includes("?")) {
|
||||||
for (const [path, file] of getGlobbedFileMap(pattern, server, Terminal.currDir)) {
|
for (const [path, file] of getGlobbedFileMap(pattern, server, Terminal.currDir)) {
|
||||||
filesToOpen.set(path, file.content);
|
files.set(path, file.content);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -49,8 +49,8 @@ export function commonEditor(
|
|||||||
}
|
}
|
||||||
const file = server.getContentFile(path);
|
const file = server.getContentFile(path);
|
||||||
const content = file ? file.content : isNs2(path) ? newNs2Template : "";
|
const content = file ? file.content : isNs2(path) ? newNs2Template : "";
|
||||||
filesToOpen.set(path, content);
|
files.set(path, content);
|
||||||
if (content === newNs2Template) CursorPositions.saveCursor(path, { row: 3, column: 5 });
|
if (content === newNs2Template) CursorPositions.saveCursor(path, { row: 3, column: 5 });
|
||||||
}
|
}
|
||||||
Router.toScriptEditor(filesToOpen, scriptEditorRouteOptions);
|
Router.toPage(Page.ScriptEditor, { files, options });
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Theme } from "@mui/material/styles";
|
||||||
|
|
||||||
import type { TextFilePath } from "../../Paths/TextFilePath";
|
import type { TextFilePath } from "../../Paths/TextFilePath";
|
||||||
import type { ContractFilePath } from "../../Paths/ContractFilePath";
|
import type { ContractFilePath } from "../../Paths/ContractFilePath";
|
||||||
import type { ProgramFilePath } from "../../Paths/ProgramFilePath";
|
import type { ProgramFilePath } from "../../Paths/ProgramFilePath";
|
||||||
import type { ContentFilePath } from "../../Paths/ContentFile";
|
import type { ContentFilePath } from "../../Paths/ContentFile";
|
||||||
import type { ScriptFilePath } from "../../Paths/ScriptFilePath";
|
import type { ScriptFilePath } from "../../Paths/ScriptFilePath";
|
||||||
|
|
||||||
import { Theme } from "@mui/material/styles";
|
|
||||||
import createStyles from "@mui/styles/createStyles";
|
import createStyles from "@mui/styles/createStyles";
|
||||||
import makeStyles from "@mui/styles/makeStyles";
|
import makeStyles from "@mui/styles/makeStyles";
|
||||||
import React from "react";
|
|
||||||
import { BaseServer } from "../../Server/BaseServer";
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
import { Router } from "../../ui/GameRoot";
|
import { Router } from "../../ui/GameRoot";
|
||||||
|
import { Page } from "../../ui/Router";
|
||||||
import { Terminal } from "../../Terminal";
|
import { Terminal } from "../../Terminal";
|
||||||
import libarg from "arg";
|
import libarg from "arg";
|
||||||
import { showLiterature } from "../../Literature/LiteratureHelpers";
|
import { showLiterature } from "../../Literature/LiteratureHelpers";
|
||||||
@ -133,9 +135,9 @@ export function ls(args: (string | number | boolean)[], server: BaseServer): voi
|
|||||||
const fullPath = combinePath(baseDirectory, props.path);
|
const fullPath = combinePath(baseDirectory, props.path);
|
||||||
function onClick() {
|
function onClick() {
|
||||||
const code = server.scripts.get(fullPath)?.content ?? "";
|
const code = server.scripts.get(fullPath)?.content ?? "";
|
||||||
const map = new Map<ContentFilePath, string>();
|
const files = new Map<ContentFilePath, string>();
|
||||||
map.set(fullPath, code);
|
files.set(fullPath, code);
|
||||||
Router.toScriptEditor(map);
|
Router.toPage(Page.ScriptEditor, { files });
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<span>
|
<span>
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
import type { ScriptFilePath } from "../Paths/ScriptFilePath";
|
|
||||||
import type { TextFilePath } from "../Paths/TextFilePath";
|
|
||||||
|
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { createStyles, makeStyles } from "@mui/styles";
|
import { createStyles, makeStyles } from "@mui/styles";
|
||||||
import { Box, Typography } from "@mui/material";
|
import { Box, Typography } from "@mui/material";
|
||||||
@ -11,19 +8,16 @@ import { installAugmentations } from "../Augmentation/AugmentationHelpers";
|
|||||||
import { saveObject } from "../SaveObject";
|
import { saveObject } from "../SaveObject";
|
||||||
import { onExport } from "../ExportBonus";
|
import { onExport } from "../ExportBonus";
|
||||||
import { LocationName } from "@enums";
|
import { LocationName } from "@enums";
|
||||||
import { Location } from "../Locations/Location";
|
|
||||||
import { ITutorial, iTutorialStart } from "../InteractiveTutorial";
|
import { ITutorial, iTutorialStart } from "../InteractiveTutorial";
|
||||||
import { InteractiveTutorialRoot } from "./InteractiveTutorial/InteractiveTutorialRoot";
|
import { InteractiveTutorialRoot } from "./InteractiveTutorial/InteractiveTutorialRoot";
|
||||||
import { ITutorialEvents } from "./InteractiveTutorial/ITutorialEvents";
|
import { ITutorialEvents } from "./InteractiveTutorial/ITutorialEvents";
|
||||||
|
|
||||||
import { Faction } from "../Faction/Faction";
|
|
||||||
import { prestigeAugmentation } from "../Prestige";
|
import { prestigeAugmentation } from "../Prestige";
|
||||||
import { dialogBoxCreate } from "./React/DialogBox";
|
import { dialogBoxCreate } from "./React/DialogBox";
|
||||||
import { GetAllServers } from "../Server/AllServers";
|
import { GetAllServers } from "../Server/AllServers";
|
||||||
import { Factions } from "../Faction/Factions";
|
|
||||||
import { StockMarket } from "../StockMarket/StockMarket";
|
import { StockMarket } from "../StockMarket/StockMarket";
|
||||||
|
|
||||||
import { Page, SimplePage, IRouter } from "./Router";
|
import { Page, PageWithContext, IRouter, ComplexPage, PageContext } from "./Router";
|
||||||
import { Overview } from "./React/Overview";
|
import { Overview } from "./React/Overview";
|
||||||
import { SidebarRoot } from "../Sidebar/ui/SidebarRoot";
|
import { SidebarRoot } from "../Sidebar/ui/SidebarRoot";
|
||||||
import { AugmentationsRoot } from "../Augmentation/ui/AugmentationsRoot";
|
import { AugmentationsRoot } from "../Augmentation/ui/AugmentationsRoot";
|
||||||
@ -47,6 +41,7 @@ import { TutorialRoot } from "../Tutorial/ui/TutorialRoot";
|
|||||||
import { ActiveScriptsRoot } from "./ActiveScripts/ActiveScriptsRoot";
|
import { ActiveScriptsRoot } from "./ActiveScripts/ActiveScriptsRoot";
|
||||||
import { FactionsRoot } from "../Faction/ui/FactionsRoot";
|
import { FactionsRoot } from "../Faction/ui/FactionsRoot";
|
||||||
import { FactionRoot } from "../Faction/ui/FactionRoot";
|
import { FactionRoot } from "../Faction/ui/FactionRoot";
|
||||||
|
import { AugmentationsPage as FactionAugmentations } from "../Faction/ui/AugmentationsPage";
|
||||||
import { CharacterStats } from "./CharacterStats";
|
import { CharacterStats } from "./CharacterStats";
|
||||||
import { TravelAgencyRoot } from "../Locations/ui/TravelAgencyRoot";
|
import { TravelAgencyRoot } from "../Locations/ui/TravelAgencyRoot";
|
||||||
import { StockMarketRoot } from "../StockMarket/ui/StockMarketRoot";
|
import { StockMarketRoot } from "../StockMarket/ui/StockMarketRoot";
|
||||||
@ -72,7 +67,6 @@ import { ImportSave } from "./React/ImportSave";
|
|||||||
import { BypassWrapper } from "./React/BypassWrapper";
|
import { BypassWrapper } from "./React/BypassWrapper";
|
||||||
|
|
||||||
import { Apr1 } from "./Apr1";
|
import { Apr1 } from "./Apr1";
|
||||||
import { isFactionWork } from "../Work/FactionWork";
|
|
||||||
import { V2Modal } from "../utils/V2Modal";
|
import { V2Modal } from "../utils/V2Modal";
|
||||||
import { MathJaxContext } from "better-react-mathjax";
|
import { MathJaxContext } from "better-react-mathjax";
|
||||||
import { useRerender } from "./React/hooks";
|
import { useRerender } from "./React/hooks";
|
||||||
@ -100,6 +94,8 @@ const uninitialized = (): void => {
|
|||||||
throw new Error("Router called before initialization");
|
throw new Error("Router called before initialization");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const MAX_PAGES_IN_HISTORY = 10;
|
||||||
|
|
||||||
export let Router: IRouter = {
|
export let Router: IRouter = {
|
||||||
isInitialized: false,
|
isInitialized: false,
|
||||||
page: () => {
|
page: () => {
|
||||||
@ -109,16 +105,12 @@ export let Router: IRouter = {
|
|||||||
toPage: () => {
|
toPage: () => {
|
||||||
throw new Error("Router called before initialization");
|
throw new Error("Router called before initialization");
|
||||||
},
|
},
|
||||||
toBitVerse: uninitialized,
|
back: () => {
|
||||||
toFaction: uninitialized,
|
throw new Error("Router called before initialization");
|
||||||
toInfiltration: uninitialized,
|
},
|
||||||
toJob: uninitialized,
|
|
||||||
toScriptEditor: uninitialized,
|
|
||||||
toLocation: uninitialized,
|
|
||||||
toImportSave: uninitialized,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function determineStartPage(): Page {
|
function determineStartPage() {
|
||||||
if (RecoveryMode) return Page.Recovery;
|
if (RecoveryMode) return Page.Recovery;
|
||||||
if (Player.currentWork !== null) return Page.Work;
|
if (Player.currentWork !== null) return Page.Work;
|
||||||
return Page.Terminal;
|
return Page.Terminal;
|
||||||
@ -126,36 +118,21 @@ function determineStartPage(): Page {
|
|||||||
|
|
||||||
export function GameRoot(): React.ReactElement {
|
export function GameRoot(): React.ReactElement {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const [{ files, vim }, setEditorOptions] = useState<{
|
|
||||||
files: Map<ScriptFilePath | TextFilePath, string>;
|
const [pages, setPages] = useState<PageWithContext[]>(() => [{ page: determineStartPage() }]);
|
||||||
vim: boolean;
|
const pageWithContext = pages[0];
|
||||||
}>({
|
|
||||||
files: new Map(),
|
const setNextPage = (pageWithContext: PageWithContext) =>
|
||||||
vim: false,
|
setPages((prev) => {
|
||||||
|
const next = [pageWithContext, ...prev];
|
||||||
|
next.length = Math.min(next.length, MAX_PAGES_IN_HISTORY);
|
||||||
|
return next;
|
||||||
});
|
});
|
||||||
const [page, setPage] = useState(determineStartPage());
|
|
||||||
const rerender = useRerender();
|
const rerender = useRerender();
|
||||||
const [augPage, setAugPage] = useState<boolean>(false);
|
|
||||||
const [faction, setFaction] = useState<Faction>(
|
|
||||||
isFactionWork(Player.currentWork) ? Factions[Player.currentWork.factionName] : (undefined as unknown as Faction),
|
|
||||||
);
|
|
||||||
if (faction === undefined && page === Page.Faction)
|
|
||||||
throw new Error("Trying to go to a page without the proper setup");
|
|
||||||
|
|
||||||
const [flume, setFlume] = useState<boolean>(false);
|
|
||||||
const [quick, setQuick] = useState<boolean>(false);
|
|
||||||
const [location, setLocation] = useState<Location>(undefined as unknown as Location);
|
|
||||||
if (location === undefined && (page === Page.Infiltration || page === Page.Location || page === Page.Job))
|
|
||||||
throw new Error("Trying to go to a page without the proper setup");
|
|
||||||
|
|
||||||
const [cinematicText, setCinematicText] = useState("");
|
|
||||||
const [errorBoundaryKey, setErrorBoundaryKey] = useState<number>(0);
|
const [errorBoundaryKey, setErrorBoundaryKey] = useState<number>(0);
|
||||||
|
|
||||||
const [importString, setImportString] = useState<string>(undefined as unknown as string);
|
|
||||||
const [importAutomatic, setImportAutomatic] = useState<boolean>(false);
|
|
||||||
if (importString === undefined && page === Page.ImportSave)
|
|
||||||
throw new Error("Trying to go to a page without the proper setup");
|
|
||||||
|
|
||||||
const [allowRoutingCalls, setAllowRoutingCalls] = useState(true);
|
const [allowRoutingCalls, setAllowRoutingCalls] = useState(true);
|
||||||
|
|
||||||
function resetErrorBoundary(): void {
|
function resetErrorBoundary(): void {
|
||||||
@ -180,67 +157,28 @@ export function GameRoot(): React.ReactElement {
|
|||||||
|
|
||||||
Router = {
|
Router = {
|
||||||
isInitialized: true,
|
isInitialized: true,
|
||||||
page: () => page,
|
page: () => pageWithContext.page,
|
||||||
allowRouting: (value: boolean) => setAllowRoutingCalls(value),
|
allowRouting: (value: boolean) => setAllowRoutingCalls(value),
|
||||||
toPage: (page: SimplePage) => {
|
toPage: (page: Page, context?: PageContext<ComplexPage>) => {
|
||||||
if (!allowRoutingCalls) return attemptedForbiddenRouting("toPage");
|
if (!allowRoutingCalls) return attemptedForbiddenRouting("toPage");
|
||||||
switch (page) {
|
switch (page) {
|
||||||
case Page.Travel:
|
case Page.Travel:
|
||||||
Player.gotoLocation(LocationName.TravelAgency);
|
Player.gotoLocation(LocationName.TravelAgency);
|
||||||
break;
|
break;
|
||||||
case Page.BladeburnerCinematic:
|
case Page.BitVerse:
|
||||||
setPage(page);
|
|
||||||
setCinematicText(cinematicText);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setPage(page);
|
|
||||||
},
|
|
||||||
toFaction: (faction: Faction, augPage = false) => {
|
|
||||||
if (!allowRoutingCalls) return attemptedForbiddenRouting("toFaction");
|
|
||||||
setAugPage(augPage);
|
|
||||||
setPage(Page.Faction);
|
|
||||||
if (faction) setFaction(faction);
|
|
||||||
},
|
|
||||||
toScriptEditor: (files = new Map(), options) => {
|
|
||||||
if (!allowRoutingCalls) return attemptedForbiddenRouting("toScriptEditor");
|
|
||||||
setEditorOptions({
|
|
||||||
files,
|
|
||||||
vim: !!options?.vim,
|
|
||||||
});
|
|
||||||
setPage(Page.ScriptEditor);
|
|
||||||
},
|
|
||||||
toJob: (location: Location) => {
|
|
||||||
if (!allowRoutingCalls) return attemptedForbiddenRouting("toJob");
|
|
||||||
setLocation(location);
|
|
||||||
setPage(Page.Job);
|
|
||||||
},
|
|
||||||
toBitVerse: (flume: boolean, quick: boolean) => {
|
|
||||||
if (!allowRoutingCalls) return attemptedForbiddenRouting("toBitVerse");
|
|
||||||
setFlume(flume);
|
|
||||||
setQuick(quick);
|
|
||||||
calculateAchievements();
|
calculateAchievements();
|
||||||
setPage(Page.BitVerse);
|
break;
|
||||||
|
}
|
||||||
|
setNextPage({ page, ...context } as PageWithContext);
|
||||||
},
|
},
|
||||||
toInfiltration: (location: Location) => {
|
back: () => {
|
||||||
if (!allowRoutingCalls) return attemptedForbiddenRouting("toInfiltration");
|
if (!allowRoutingCalls) return attemptedForbiddenRouting("back");
|
||||||
setLocation(location);
|
setPages((pages) => pages.slice(1));
|
||||||
setPage(Page.Infiltration);
|
|
||||||
},
|
|
||||||
toLocation: (location: Location) => {
|
|
||||||
if (!allowRoutingCalls) return attemptedForbiddenRouting("toLocation");
|
|
||||||
setLocation(location);
|
|
||||||
setPage(Page.Location);
|
|
||||||
},
|
|
||||||
toImportSave: (base64save: string, automatic = false) => {
|
|
||||||
if (!allowRoutingCalls) return attemptedForbiddenRouting("toImportSave");
|
|
||||||
setImportString(base64save);
|
|
||||||
setImportAutomatic(automatic);
|
|
||||||
setPage(Page.ImportSave);
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (page !== Page.Terminal) window.scrollTo(0, 0);
|
if (pageWithContext.page !== Page.Terminal) window.scrollTo(0, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
function softReset(): void {
|
function softReset(): void {
|
||||||
@ -254,7 +192,7 @@ export function GameRoot(): React.ReactElement {
|
|||||||
let withSidebar = true;
|
let withSidebar = true;
|
||||||
let withPopups = true;
|
let withPopups = true;
|
||||||
let bypassGame = false;
|
let bypassGame = false;
|
||||||
switch (page) {
|
switch (pageWithContext.page) {
|
||||||
case Page.Recovery: {
|
case Page.Recovery: {
|
||||||
mainPage = <RecoveryRoot softReset={softReset} />;
|
mainPage = <RecoveryRoot softReset={softReset} />;
|
||||||
withSidebar = false;
|
withSidebar = false;
|
||||||
@ -263,13 +201,13 @@ export function GameRoot(): React.ReactElement {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Page.BitVerse: {
|
case Page.BitVerse: {
|
||||||
mainPage = <BitverseRoot flume={flume} quick={quick} />;
|
mainPage = <BitverseRoot flume={pageWithContext.flume} quick={pageWithContext.quick} />;
|
||||||
withSidebar = false;
|
withSidebar = false;
|
||||||
withPopups = false;
|
withPopups = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Page.Infiltration: {
|
case Page.Infiltration: {
|
||||||
mainPage = <InfiltrationRoot location={location} />;
|
mainPage = <InfiltrationRoot location={pageWithContext.location} />;
|
||||||
withSidebar = false;
|
withSidebar = false;
|
||||||
withPopups = false;
|
withPopups = false;
|
||||||
break;
|
break;
|
||||||
@ -302,7 +240,13 @@ export function GameRoot(): React.ReactElement {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Page.ScriptEditor: {
|
case Page.ScriptEditor: {
|
||||||
mainPage = <ScriptEditorRoot files={files} hostname={Player.getCurrentServer().hostname} vim={vim} />;
|
mainPage = (
|
||||||
|
<ScriptEditorRoot
|
||||||
|
files={pageWithContext.files ?? new Map()}
|
||||||
|
hostname={Player.getCurrentServer().hostname}
|
||||||
|
vim={!!pageWithContext.options?.vim}
|
||||||
|
/>
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Page.ActiveScripts: {
|
case Page.ActiveScripts: {
|
||||||
@ -322,7 +266,11 @@ export function GameRoot(): React.ReactElement {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Page.Faction: {
|
case Page.Faction: {
|
||||||
mainPage = <FactionRoot faction={faction} augPage={augPage} />;
|
mainPage = <FactionRoot faction={pageWithContext.faction} />;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Page.FactionAugmentations: {
|
||||||
|
mainPage = <FactionAugmentations faction={pageWithContext.faction} />;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Page.Milestones: {
|
case Page.Milestones: {
|
||||||
@ -375,7 +323,7 @@ export function GameRoot(): React.ReactElement {
|
|||||||
}
|
}
|
||||||
case Page.Job:
|
case Page.Job:
|
||||||
case Page.Location: {
|
case Page.Location: {
|
||||||
mainPage = <GenericLocation loc={location} />;
|
mainPage = <GenericLocation loc={pageWithContext.location} />;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Page.Options: {
|
case Page.Options: {
|
||||||
@ -417,7 +365,7 @@ export function GameRoot(): React.ReactElement {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Page.ImportSave: {
|
case Page.ImportSave: {
|
||||||
mainPage = <ImportSave importString={importString} automatic={importAutomatic} />;
|
mainPage = <ImportSave importString={pageWithContext.base64Save} automatic={!!pageWithContext.automatic} />;
|
||||||
withSidebar = false;
|
withSidebar = false;
|
||||||
withPopups = false;
|
withPopups = false;
|
||||||
bypassGame = true;
|
bypassGame = true;
|
||||||
@ -444,7 +392,7 @@ export function GameRoot(): React.ReactElement {
|
|||||||
</Overview>
|
</Overview>
|
||||||
{withSidebar ? (
|
{withSidebar ? (
|
||||||
<Box display="flex" flexDirection="row" width="100%">
|
<Box display="flex" flexDirection="row" width="100%">
|
||||||
<SidebarRoot page={page} />
|
<SidebarRoot page={pageWithContext.page} />
|
||||||
<Box className={classes.root}>{mainPage}</Box>
|
<Box className={classes.root}>{mainPage}</Box>
|
||||||
</Box>
|
</Box>
|
||||||
) : (
|
) : (
|
||||||
|
@ -3,7 +3,7 @@ import type { TextFilePath } from "../Paths/TextFilePath";
|
|||||||
import type { Faction } from "../Faction/Faction";
|
import type { Faction } from "../Faction/Faction";
|
||||||
import type { Location } from "../Locations/Location";
|
import type { Location } from "../Locations/Location";
|
||||||
|
|
||||||
// These enums don't need enum helper support for now
|
// This enum doesn't need enum helper support for now
|
||||||
/**
|
/**
|
||||||
* The full-screen page the player is currently be on.
|
* The full-screen page the player is currently be on.
|
||||||
* These are "simple" pages that don't require any extra parameters to
|
* These are "simple" pages that don't require any extra parameters to
|
||||||
@ -38,14 +38,12 @@ export enum SimplePage {
|
|||||||
ThemeBrowser = "Theme Browser",
|
ThemeBrowser = "Theme Browser",
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* "Complex" pages that need a custom transition function.
|
|
||||||
*/
|
|
||||||
export enum ComplexPage {
|
export enum ComplexPage {
|
||||||
BitVerse = "BitVerse",
|
BitVerse = "BitVerse",
|
||||||
Faction = "Faction",
|
|
||||||
Infiltration = "Infiltration",
|
Infiltration = "Infiltration",
|
||||||
Job = "Job",
|
Job = "Job",
|
||||||
|
Faction = "Faction",
|
||||||
|
FactionAugmentations = "Faction Augmentations",
|
||||||
ScriptEditor = "Script Editor",
|
ScriptEditor = "Script Editor",
|
||||||
Location = "Location",
|
Location = "Location",
|
||||||
ImportSave = "Import Save",
|
ImportSave = "Import Save",
|
||||||
@ -56,6 +54,35 @@ export enum ComplexPage {
|
|||||||
export type Page = SimplePage | ComplexPage;
|
export type Page = SimplePage | ComplexPage;
|
||||||
export const Page = { ...SimplePage, ...ComplexPage };
|
export const Page = { ...SimplePage, ...ComplexPage };
|
||||||
|
|
||||||
|
export type PageContext<T extends Page> = T extends ComplexPage.BitVerse
|
||||||
|
? { flume: boolean; quick: boolean }
|
||||||
|
: T extends ComplexPage.Infiltration
|
||||||
|
? { location: Location }
|
||||||
|
: T extends ComplexPage.Job
|
||||||
|
? { location: Location }
|
||||||
|
: T extends ComplexPage.Faction
|
||||||
|
? { faction: Faction }
|
||||||
|
: T extends ComplexPage.FactionAugmentations
|
||||||
|
? { faction: Faction }
|
||||||
|
: T extends ComplexPage.ScriptEditor
|
||||||
|
? { files?: Map<ScriptFilePath | TextFilePath, string>; options?: ScriptEditorRouteOptions }
|
||||||
|
: T extends ComplexPage.Location
|
||||||
|
? { location: Location }
|
||||||
|
: T extends ComplexPage.ImportSave
|
||||||
|
? { base64Save: string; automatic?: boolean }
|
||||||
|
: never;
|
||||||
|
|
||||||
|
export type PageWithContext =
|
||||||
|
| ({ page: ComplexPage.BitVerse } & PageContext<ComplexPage.BitVerse>)
|
||||||
|
| ({ page: ComplexPage.Infiltration } & PageContext<ComplexPage.Infiltration>)
|
||||||
|
| ({ page: ComplexPage.Job } & PageContext<ComplexPage.Job>)
|
||||||
|
| ({ page: ComplexPage.Faction } & PageContext<ComplexPage.Faction>)
|
||||||
|
| ({ page: ComplexPage.FactionAugmentations } & PageContext<ComplexPage.FactionAugmentations>)
|
||||||
|
| ({ page: ComplexPage.ScriptEditor } & PageContext<ComplexPage.ScriptEditor>)
|
||||||
|
| ({ page: ComplexPage.Location } & PageContext<ComplexPage.Location>)
|
||||||
|
| ({ page: ComplexPage.ImportSave } & PageContext<ComplexPage.ImportSave>)
|
||||||
|
| { page: SimplePage };
|
||||||
|
|
||||||
export interface ScriptEditorRouteOptions {
|
export interface ScriptEditorRouteOptions {
|
||||||
vim: boolean;
|
vim: boolean;
|
||||||
}
|
}
|
||||||
@ -66,11 +93,10 @@ export interface IRouter {
|
|||||||
page(): Page;
|
page(): Page;
|
||||||
allowRouting(value: boolean): void;
|
allowRouting(value: boolean): void;
|
||||||
toPage(page: SimplePage): void;
|
toPage(page: SimplePage): void;
|
||||||
toBitVerse(flume: boolean, quick: boolean): void;
|
toPage<T extends ComplexPage>(page: T, context: PageContext<T>): void;
|
||||||
toFaction(faction: Faction, augPage?: boolean): void; // faction name
|
/** go to a preveious page (if any) */
|
||||||
toInfiltration(location: Location): void;
|
back(): void;
|
||||||
toJob(location: Location): void;
|
|
||||||
toScriptEditor(files?: Map<ScriptFilePath | TextFilePath, string>, options?: ScriptEditorRouteOptions): void;
|
|
||||||
toLocation(location: Location): void;
|
|
||||||
toImportSave(base64Save: string, automatic?: boolean): void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const simplePages = Object.values(SimplePage);
|
||||||
|
export const isSimplePage = (page: Page): page is SimplePage => simplePages.includes(page as SimplePage);
|
||||||
|
@ -206,7 +206,7 @@ export function WorkInProgressRoot(): React.ReactElement {
|
|||||||
workInfo = {
|
workInfo = {
|
||||||
buttons: {
|
buttons: {
|
||||||
cancel: () => {
|
cancel: () => {
|
||||||
Router.toLocation(Locations[LocationName.Slums]);
|
Router.toPage(Page.Location, { location: Locations[LocationName.Slums] });
|
||||||
Player.finishWork(true);
|
Player.finishWork(true);
|
||||||
},
|
},
|
||||||
unfocus: () => {
|
unfocus: () => {
|
||||||
@ -374,11 +374,11 @@ export function WorkInProgressRoot(): React.ReactElement {
|
|||||||
workInfo = {
|
workInfo = {
|
||||||
buttons: {
|
buttons: {
|
||||||
cancel: () => {
|
cancel: () => {
|
||||||
Router.toFaction(faction);
|
Router.toPage(Page.Faction, { faction });
|
||||||
Player.finishWork(true);
|
Player.finishWork(true);
|
||||||
},
|
},
|
||||||
unfocus: () => {
|
unfocus: () => {
|
||||||
Router.toFaction(faction);
|
Router.toPage(Page.Faction, { faction });
|
||||||
Player.stopFocusing();
|
Player.stopFocusing();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -426,11 +426,11 @@ export function WorkInProgressRoot(): React.ReactElement {
|
|||||||
buttons: {
|
buttons: {
|
||||||
cancel: () => {
|
cancel: () => {
|
||||||
Player.finishWork(true);
|
Player.finishWork(true);
|
||||||
Router.toJob(Locations[comp.name]);
|
Router.toPage(Page.Job, { location: Locations[comp.name] });
|
||||||
},
|
},
|
||||||
unfocus: () => {
|
unfocus: () => {
|
||||||
Player.stopFocusing();
|
Player.stopFocusing();
|
||||||
Router.toJob(Locations[comp.name]);
|
Router.toPage(Page.Job, { location: Locations[comp.name] });
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
title: (
|
title: (
|
||||||
|
Loading…
Reference in New Issue
Block a user