import React, { useState, useEffect } from "react"; import { createStyles, makeStyles } from "@mui/styles"; import { Box, Typography } from "@mui/material"; import { Theme } from "@mui/material/styles"; import { Player } from "@player"; import { installAugmentations } from "../Augmentation/AugmentationHelpers"; import { saveObject } from "../SaveObject"; import { onExport } from "../ExportBonus"; import { LocationName } from "@enums"; import { ITutorial, iTutorialStart } from "../InteractiveTutorial"; import { InteractiveTutorialRoot } from "./InteractiveTutorial/InteractiveTutorialRoot"; import { ITutorialEvents } from "./InteractiveTutorial/ITutorialEvents"; import { prestigeAugmentation } from "../Prestige"; import { dialogBoxCreate } from "./React/DialogBox"; import { GetAllServers } from "../Server/AllServers"; import { StockMarket } from "../StockMarket/StockMarket"; import { Page, PageWithContext, IRouter, ComplexPage, PageContext } from "./Router"; import { Overview } from "./React/Overview"; import { SidebarRoot } from "../Sidebar/ui/SidebarRoot"; import { AugmentationsRoot } from "../Augmentation/ui/AugmentationsRoot"; import { DevMenuRoot } from "../DevMenu"; import { BladeburnerRoot } from "../Bladeburner/ui/BladeburnerRoot"; import { GangRoot } from "../Gang/ui/GangRoot"; import { CorporationRoot } from "../Corporation/ui/CorporationRoot"; import { InfiltrationRoot } from "../Infiltration/ui/InfiltrationRoot"; import { GraftingRoot } from "../PersonObjects/Grafting/ui/GraftingRoot"; import { WorkInProgressRoot } from "./WorkInProgressRoot"; import { GameOptionsRoot } from "../GameOptions/ui/GameOptionsRoot"; import { SleeveRoot } from "../PersonObjects/Sleeve/ui/SleeveRoot"; import { HacknetRoot } from "../Hacknet/ui/HacknetRoot"; import { GenericLocation } from "../Locations/ui/GenericLocation"; import { LocationCity } from "../Locations/ui/City"; import { ProgramsRoot } from "../Programs/ui/ProgramsRoot"; import { ScriptEditorRoot } from "../ScriptEditor/ui/ScriptEditorRoot"; import { MilestonesRoot } from "../Milestones/ui/MilestonesRoot"; import { TerminalRoot } from "../Terminal/ui/TerminalRoot"; import { TutorialRoot } from "../Tutorial/ui/TutorialRoot"; import { ActiveScriptsRoot } from "./ActiveScripts/ActiveScriptsRoot"; import { FactionsRoot } from "../Faction/ui/FactionsRoot"; import { FactionRoot } from "../Faction/ui/FactionRoot"; import { AugmentationsPage as FactionAugmentations } from "../Faction/ui/AugmentationsPage"; import { CharacterStats } from "./CharacterStats"; import { TravelAgencyRoot } from "../Locations/ui/TravelAgencyRoot"; import { StockMarketRoot } from "../StockMarket/ui/StockMarketRoot"; import { BitverseRoot } from "../BitNode/ui/BitverseRoot"; import { StaneksGiftRoot } from "../CotMG/ui/StaneksGiftRoot"; import { staneksGift } from "../CotMG/Helper"; import { CharacterOverview } from "./React/CharacterOverview"; import { BladeburnerCinematic } from "../Bladeburner/ui/BladeburnerCinematic"; import { workerScripts } from "../Netscript/WorkerScripts"; import { Unclickable } from "../Exploits/Unclickable"; import { Snackbar, SnackbarProvider } from "./React/Snackbar"; import { LogBoxManager } from "./React/LogBoxManager"; import { AlertManager } from "./React/AlertManager"; import { PromptManager } from "./React/PromptManager"; import { InvitationModal } from "../Faction/ui/InvitationModal"; import { calculateAchievements } from "../Achievements/Achievements"; import { RecoveryMode, RecoveryRoot } from "./React/RecoveryRoot"; import { AchievementsRoot } from "../Achievements/AchievementsRoot"; import { ErrorBoundary } from "./ErrorBoundary"; import { ThemeBrowser } from "../Themes/ui/ThemeBrowser"; import { ImportSave } from "./React/ImportSave"; import { BypassWrapper } from "./React/BypassWrapper"; import { Apr1 } from "./Apr1"; import { V2Modal } from "../utils/V2Modal"; import { MathJaxContext } from "better-react-mathjax"; import { useRerender } from "./React/hooks"; const htmlLocation = location; const useStyles = makeStyles( (theme: Theme) => createStyles({ root: { "-ms-overflow-style": "none" /* for Internet Explorer, Edge */, "scrollbar-width": "none" /* for Firefox */, margin: theme.spacing(0), flexGrow: 1, padding: "8px", minHeight: "100vh", boxSizing: "border-box", width: "1px", }, }), { name: "GameRoot" }, ); const uninitialized = (): void => { throw new Error("Router called before initialization"); }; const MAX_PAGES_IN_HISTORY = 10; export let Router: IRouter = { isInitialized: false, page: () => { throw new Error("Router called before initialization"); }, allowRouting: uninitialized, toPage: () => { throw new Error("Router called before initialization"); }, back: () => { throw new Error("Router called before initialization"); }, }; function determineStartPage() { if (RecoveryMode) return Page.Recovery; if (Player.currentWork !== null) return Page.Work; return Page.Terminal; } export function GameRoot(): React.ReactElement { const classes = useStyles(); const [pages, setPages] = useState(() => [{ page: determineStartPage() }]); const pageWithContext = pages[0]; const setNextPage = (pageWithContext: PageWithContext) => setPages((prev) => { const next = [pageWithContext, ...prev]; next.length = Math.min(next.length, MAX_PAGES_IN_HISTORY); return next; }); const rerender = useRerender(); const [errorBoundaryKey, setErrorBoundaryKey] = useState(0); const [allowRoutingCalls, setAllowRoutingCalls] = useState(true); function resetErrorBoundary(): void { setErrorBoundaryKey(errorBoundaryKey + 1); } useEffect(() => { return ITutorialEvents.subscribe(rerender); }, [rerender]); function killAllScripts(): void { for (const server of GetAllServers()) { server.runningScriptMap.clear(); } saveObject.saveGame(); setTimeout(() => htmlLocation.reload(), 2000); } function attemptedForbiddenRouting(name: string) { console.error(`Routing is currently disabled - Attempted router.${name}()`); } Router = { isInitialized: true, page: () => pageWithContext.page, allowRouting: (value: boolean) => setAllowRoutingCalls(value), toPage: (page: Page, context?: PageContext) => { if (!allowRoutingCalls) return attemptedForbiddenRouting("toPage"); switch (page) { case Page.Travel: Player.gotoLocation(LocationName.TravelAgency); break; case Page.BitVerse: calculateAchievements(); break; } setNextPage({ page, ...context } as PageWithContext); }, back: () => { if (!allowRoutingCalls) return attemptedForbiddenRouting("back"); setPages((pages) => pages.slice(1)); }, }; useEffect(() => { if (pageWithContext.page !== Page.Terminal) window.scrollTo(0, 0); }); function softReset(): void { dialogBoxCreate("Soft Reset!"); installAugmentations(true); resetErrorBoundary(); Router.toPage(Page.Terminal); } let mainPage = Cannot load; let withSidebar = true; let withPopups = true; let bypassGame = false; switch (pageWithContext.page) { case Page.Recovery: { mainPage = ; withSidebar = false; withPopups = false; bypassGame = true; break; } case Page.BitVerse: { mainPage = ; withSidebar = false; withPopups = false; break; } case Page.Infiltration: { mainPage = ; withSidebar = false; withPopups = false; break; } case Page.BladeburnerCinematic: { mainPage = ; withSidebar = false; withPopups = false; break; } case Page.Work: { mainPage = ; withSidebar = false; break; } case Page.Terminal: { mainPage = ; break; } case Page.Sleeves: { mainPage = ; break; } case Page.StaneksGift: { mainPage = ; break; } case Page.Stats: { mainPage = ; break; } case Page.ScriptEditor: { mainPage = ( ); break; } case Page.ActiveScripts: { mainPage = ; break; } case Page.Hacknet: { mainPage = ; break; } case Page.CreateProgram: { mainPage = ; break; } case Page.Factions: { mainPage = ; break; } case Page.Faction: { mainPage = ; break; } case Page.FactionAugmentations: { mainPage = ; break; } case Page.Milestones: { mainPage = ; break; } case Page.Tutorial: { mainPage = ( { prestigeAugmentation(); Router.toPage(Page.Terminal); iTutorialStart(); }} /> ); break; } case Page.DevMenu: { mainPage = ; break; } case Page.Gang: { mainPage = ; break; } case Page.Corporation: { mainPage = ; break; } case Page.Bladeburner: { mainPage = ; break; } case Page.Grafting: { mainPage = ; break; } case Page.Travel: { mainPage = ; break; } case Page.StockMarket: { mainPage = ; break; } case Page.City: { mainPage = ; break; } case Page.Job: case Page.Location: { mainPage = ; break; } case Page.Options: { mainPage = ( saveObject.saveGame()} export={() => { // Apply the export bonus before saving the game onExport(); saveObject.exportGame(); }} forceKill={killAllScripts} softReset={softReset} /> ); break; } case Page.Augmentations: { mainPage = ( { // Apply the export bonus before saving the game onExport(); saveObject.exportGame(); }} installAugmentationsFn={() => { installAugmentations(); }} /> ); break; } case Page.Achievements: { mainPage = ; break; } case Page.ThemeBrowser: { mainPage = ; break; } case Page.ImportSave: { mainPage = ; withSidebar = false; withPopups = false; bypassGame = true; } } return ( {(parentOpen) => !ITutorial.isRunning ? ( saveObject.saveGame()} killScripts={killAllScripts} /> ) : ( ) } {withSidebar ? ( {mainPage} ) : ( {mainPage} )} {withPopups && ( <> )} ); }