bitburner-src/src/ui/GameRoot.tsx

399 lines
15 KiB
TypeScript
Raw Normal View History

2021-09-20 05:29:02 +02:00
import React, { useState, useEffect } from "react";
2021-09-17 08:04:44 +02:00
import { IPlayer } from "../PersonObjects/IPlayer";
import { IEngine } from "../IEngine";
import { ITerminal } from "../Terminal/ITerminal";
import { installAugmentations } from "../Augmentation/AugmentationHelpers";
2021-09-20 00:04:12 +02:00
import { saveObject, openImportFileHandler } from "../SaveObject";
2021-09-17 08:04:44 +02:00
import { onExport } from "../ExportBonus";
import { LocationName } from "../Locations/data/LocationNames";
2021-09-18 10:01:07 +02:00
import { Location } from "../Locations/Location";
import { Locations } from "../Locations/Locations";
2021-09-19 06:46:39 +02:00
import { ITutorial } from "../InteractiveTutorial";
import { InteractiveTutorialRoot } from "./InteractiveTutorial/InteractiveTutorialRoot";
import { ITutorialEvents } from "./InteractiveTutorial/ITutorialEvents";
2021-09-18 10:01:07 +02:00
2021-09-17 08:04:44 +02:00
import { Faction } from "../Faction/Faction";
import { prestigeAugmentation } from "../Prestige";
import { dialogBoxCreate } from "../../utils/DialogBox";
import { AllServers } from "../Server/AllServers";
2021-09-18 01:43:08 +02:00
import { Factions } from "../Faction/Factions";
2021-09-17 08:31:19 +02:00
import { buyStock, sellStock, shortStock, sellShort } from "../StockMarket/BuyingAndSelling";
import {
cancelOrder,
eventEmitterForUiReset,
initStockMarketFnForReact,
placeOrder,
StockMarket,
} from "../StockMarket/StockMarket";
2021-09-17 08:04:44 +02:00
import { Theme } from "@mui/material/styles";
import makeStyles from "@mui/styles/makeStyles";
import createStyles from "@mui/styles/createStyles";
import Box from "@mui/material/Box";
import Typography from "@mui/material/Typography";
import { Page, IRouter } from "./Router";
2021-09-19 06:46:39 +02:00
import { Overview } from "./React/Overview";
2021-09-17 08:04:44 +02:00
import { SidebarRoot } from "../Sidebar/ui/SidebarRoot";
2021-09-18 01:43:08 +02:00
import { AugmentationsRoot } from "../Augmentation/ui/AugmentationsRoot";
2021-09-17 08:04:44 +02:00
import { DevMenuRoot } from "../DevMenu";
2021-09-18 01:43:08 +02:00
import { BladeburnerRoot } from "../Bladeburner/ui/BladeburnerRoot";
import { GangRoot } from "../Gang/ui/GangRoot";
2021-09-17 08:04:44 +02:00
import { CorporationRoot } from "../Corporation/ui/CorporationRoot";
2021-09-18 01:43:08 +02:00
import { InfiltrationRoot } from "../Infiltration/ui/InfiltrationRoot";
2021-09-17 08:04:44 +02:00
import { ResleeveRoot } from "../PersonObjects/Resleeving/ui/ResleeveRoot";
2021-09-18 01:43:08 +02:00
import { WorkInProgressRoot } from "./WorkInProgressRoot";
2021-09-17 08:04:44 +02:00
import { GameOptionsRoot } from "../ui/React/GameOptionsRoot";
import { SleeveRoot } from "../PersonObjects/Sleeve/ui/SleeveRoot";
import { HacknetRoot } from "../Hacknet/ui/HacknetRoot";
2021-09-18 10:01:07 +02:00
import { GenericLocation } from "../Locations/ui/GenericLocation";
import { LocationCity } from "../Locations/ui/City";
2021-09-17 08:04:44 +02:00
import { ProgramsRoot } from "../Programs/ui/ProgramsRoot";
import { Root as ScriptEditorRoot } from "../ScriptEditor/ui/Root";
import { MilestonesRoot } from "../Milestones/ui/MilestonesRoot";
import { TerminalRoot } from "../Terminal/ui/TerminalRoot";
import { TutorialRoot } from "../Tutorial/ui/TutorialRoot";
2021-09-18 01:43:08 +02:00
import { ActiveScriptsRoot } from "../ui/ActiveScripts/ActiveScriptsRoot";
2021-09-17 08:04:44 +02:00
import { FactionsRoot } from "../Faction/ui/FactionsRoot";
2021-09-19 23:05:27 +02:00
import { HackingMissionRoot } from "../HackingMission/ui/HackingMissionRoot";
2021-09-17 08:04:44 +02:00
import { FactionRoot } from "../Faction/ui/FactionRoot";
2021-09-18 18:13:20 +02:00
import { CharacterStats } from "./CharacterStats";
2021-09-17 08:04:44 +02:00
import { TravelAgencyRoot } from "../Locations/ui/TravelAgencyRoot";
2021-09-17 08:31:19 +02:00
import { StockMarketRoot } from "../StockMarket/ui/StockMarketRoot";
2021-09-18 01:43:08 +02:00
import { BitverseRoot } from "../BitNode/ui/BitverseRoot";
import { CharacterOverview } from "./React/CharacterOverview";
import { BladeburnerCinematic } from "../Bladeburner/ui/BladeburnerCinematic";
2021-09-17 08:04:44 +02:00
import { workerScripts } from "../Netscript/WorkerScripts";
2021-09-18 01:43:08 +02:00
import { enterBitNode } from "../RedPill";
import { Context } from "./Context";
2021-09-17 08:04:44 +02:00
interface IProps {
terminal: ITerminal;
player: IPlayer;
engine: IEngine;
}
const useStyles = makeStyles((theme: Theme) =>
createStyles({
root: {
"-ms-overflow-style": "none" /* for Internet Explorer, Edge */,
"scrollbar-width": "none" /* for Firefox */,
2021-09-18 01:43:08 +02:00
margin: theme.spacing(0),
2021-09-17 08:04:44 +02:00
},
}),
);
2021-09-17 08:58:02 +02:00
let filename = "";
let code = "";
2021-09-18 01:43:08 +02:00
export let Router: IRouter = {
page: () => {
throw new Error("Router called before initialization");
},
toActiveScripts: () => {
throw new Error("Router called before initialization");
},
toAugmentations: () => {
throw new Error("Router called before initialization");
},
toBitVerse: () => {
throw new Error("Router called before initialization");
},
toBladeburner: () => {
throw new Error("Router called before initialization");
},
2021-09-18 18:13:20 +02:00
toStats: () => {
2021-09-18 01:43:08 +02:00
throw new Error("Router called before initialization");
},
toCity: () => {
throw new Error("Router called before initialization");
},
toCorporation: () => {
throw new Error("Router called before initialization");
},
toCreateProgram: () => {
throw new Error("Router called before initialization");
},
toDevMenu: () => {
throw new Error("Router called before initialization");
},
toFaction: () => {
throw new Error("Router called before initialization");
},
toFactions: () => {
throw new Error("Router called before initialization");
},
toGameOptions: () => {
throw new Error("Router called before initialization");
},
toGang: () => {
throw new Error("Router called before initialization");
},
toHacknetNodes: () => {
throw new Error("Router called before initialization");
},
toInfiltration: () => {
throw new Error("Router called before initialization");
},
toJob: () => {
throw new Error("Router called before initialization");
},
toMilestones: () => {
throw new Error("Router called before initialization");
},
toResleeves: () => {
throw new Error("Router called before initialization");
},
toScriptEditor: () => {
throw new Error("Router called before initialization");
},
toSleeves: () => {
throw new Error("Router called before initialization");
},
toStockMarket: () => {
throw new Error("Router called before initialization");
},
toTerminal: () => {
throw new Error("Router called before initialization");
},
toTravel: () => {
throw new Error("Router called before initialization");
},
toTutorial: () => {
throw new Error("Router called before initialization");
},
toWork: () => {
throw new Error("Router called before initialization");
},
toBladeburnerCinematic: () => {
throw new Error("Router called before initialization");
},
2021-09-18 10:01:07 +02:00
toLocation: () => {
throw new Error("Router called before initialization");
},
2021-09-19 23:05:27 +02:00
toHackingMission: () => {
throw new Error("Router called before initialization");
},
2021-09-18 01:43:08 +02:00
};
function determineStartPage(player: IPlayer): Page {
if (player.isWorking) return Page.Work;
return Page.Terminal;
}
2021-09-17 08:04:44 +02:00
export function GameRoot({ player, engine, terminal }: IProps): React.ReactElement {
const classes = useStyles();
const [page, setPage] = useState(determineStartPage(player));
2021-09-19 06:46:39 +02:00
const setRerender = useState(0)[1];
2021-09-18 10:01:07 +02:00
const [faction, setFaction] = useState<Faction>(
player.currentWorkFactionName ? Factions[player.currentWorkFactionName] : (undefined as unknown as Faction),
2021-09-18 01:43:08 +02:00
);
2021-09-18 10:01:07 +02:00
if (faction === undefined && page === Page.Faction)
throw new Error("Trying to go to a page without the proper setup");
2021-09-17 08:04:44 +02:00
2021-09-18 01:43:08 +02:00
const [flume, setFlume] = useState<boolean>(false);
const [quick, setQuick] = useState<boolean>(false);
2021-09-18 10:01:07 +02:00
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");
2021-09-18 01:43:08 +02:00
const [cinematicText, setCinematicText] = useState("");
2021-09-19 06:46:39 +02:00
function rerender(): void {
setRerender((old) => old + 1);
}
useEffect(() => {
return ITutorialEvents.subscribe(rerender);
}, []);
2021-09-18 01:43:08 +02:00
Router = {
page: () => page,
2021-09-17 08:04:44 +02:00
toActiveScripts: () => setPage(Page.ActiveScripts),
toAugmentations: () => setPage(Page.Augmentations),
toBladeburner: () => setPage(Page.Bladeburner),
2021-09-18 18:13:20 +02:00
toStats: () => setPage(Page.Stats),
2021-09-17 08:04:44 +02:00
toCorporation: () => setPage(Page.Corporation),
toCreateProgram: () => setPage(Page.CreateProgram),
toDevMenu: () => setPage(Page.DevMenu),
2021-09-18 01:43:08 +02:00
toFaction: (faction?: Faction) => {
2021-09-17 08:04:44 +02:00
setPage(Page.Faction);
2021-09-18 01:43:08 +02:00
if (faction) setFaction(faction);
2021-09-17 08:04:44 +02:00
},
toFactions: () => setPage(Page.Factions),
toGameOptions: () => setPage(Page.Options),
toGang: () => setPage(Page.Gang),
toHacknetNodes: () => setPage(Page.Hacknet),
toMilestones: () => setPage(Page.Milestones),
toResleeves: () => setPage(Page.Resleeves),
2021-09-17 08:58:02 +02:00
toScriptEditor: (fn: string, c: string) => {
filename = fn;
code = c;
setPage(Page.CreateScript);
},
2021-09-17 08:04:44 +02:00
toSleeves: () => setPage(Page.Sleeves),
toStockMarket: () => setPage(Page.StockMarket),
toTerminal: () => setPage(Page.Terminal),
toTutorial: () => setPage(Page.Tutorial),
2021-09-17 08:31:19 +02:00
toJob: () => {
2021-09-18 10:01:07 +02:00
setLocation(Locations[player.companyName]);
2021-09-17 08:31:19 +02:00
setPage(Page.Job);
},
2021-09-17 08:04:44 +02:00
toCity: () => {
setPage(Page.City);
},
toTravel: () => {
player.gotoLocation(LocationName.TravelAgency);
setPage(Page.Travel);
},
2021-09-18 01:43:08 +02:00
toBitVerse: (flume: boolean, quick: boolean) => {
setFlume(flume);
setQuick(quick);
setPage(Page.BitVerse);
},
2021-09-18 10:01:07 +02:00
toInfiltration: (location: Location) => {
2021-09-18 01:43:08 +02:00
setLocation(location);
setPage(Page.Infiltration);
},
toWork: () => setPage(Page.Work),
toBladeburnerCinematic: () => {
setPage(Page.BladeburnerCinematic);
setCinematicText(cinematicText);
},
2021-09-18 10:01:07 +02:00
toLocation: (location: Location) => {
setLocation(location);
setPage(Page.Location);
},
2021-09-19 23:05:27 +02:00
toHackingMission: (faction: Faction) => {
setPage(Page.HackingMission);
setFaction(faction);
},
2021-09-17 08:04:44 +02:00
};
2021-09-17 08:58:02 +02:00
useEffect(() => {
filename = "";
code = "";
2021-09-19 06:46:39 +02:00
if (page !== Page.Terminal) window.scrollTo(0, 0);
2021-09-17 08:58:02 +02:00
});
2021-09-17 08:04:44 +02:00
return (
2021-09-18 01:43:08 +02:00
<Context.Player.Provider value={player}>
<Context.Router.Provider value={Router}>
2021-09-19 06:46:39 +02:00
<Overview>
{!ITutorial.isRunning ? (
<CharacterOverview save={() => saveObject.saveGame(engine.indexedDb)} />
) : (
<InteractiveTutorialRoot />
)}
</Overview>
{page === Page.BitVerse ? (
2021-09-18 01:43:08 +02:00
<BitverseRoot flume={flume} enter={enterBitNode} quick={quick} />
) : page === Page.Infiltration ? (
<InfiltrationRoot location={location} />
2021-09-19 23:05:27 +02:00
) : page === Page.HackingMission ? (
<HackingMissionRoot faction={faction} />
2021-09-18 01:43:08 +02:00
) : page === Page.BladeburnerCinematic ? (
<BladeburnerCinematic />
) : page === Page.Work ? (
<WorkInProgressRoot />
) : (
<Box display="flex" flexDirection="row" width="100%">
<SidebarRoot player={player} router={Router} page={page} />
2021-09-18 18:13:20 +02:00
<Box className={classes.root} flexGrow={1} display="block" width="100%" px={1} height="100vh">
2021-09-18 01:43:08 +02:00
{page === Page.Terminal ? (
<TerminalRoot terminal={terminal} router={Router} player={player} />
) : page === Page.Sleeves ? (
<SleeveRoot player={player} />
) : page === Page.Stats ? (
2021-09-18 18:13:20 +02:00
<CharacterStats />
2021-09-18 01:43:08 +02:00
) : page === Page.CreateScript ? (
<ScriptEditorRoot filename={filename} code={code} player={player} router={Router} />
) : page === Page.ActiveScripts ? (
2021-09-18 03:30:02 +02:00
<ActiveScriptsRoot workerScripts={workerScripts} />
2021-09-18 01:43:08 +02:00
) : page === Page.Hacknet ? (
<HacknetRoot player={player} />
) : page === Page.CreateProgram ? (
<ProgramsRoot />
) : page === Page.Factions ? (
<FactionsRoot player={player} router={Router} />
) : page === Page.Faction ? (
2021-09-19 23:05:27 +02:00
<FactionRoot faction={faction} />
2021-09-18 01:43:08 +02:00
) : page === Page.Milestones ? (
<MilestonesRoot player={player} />
) : page === Page.Tutorial ? (
<TutorialRoot />
) : page === Page.DevMenu ? (
<DevMenuRoot player={player} engine={engine} router={Router} />
) : page === Page.Gang ? (
<GangRoot gang={player.gang} />
) : page === Page.Corporation ? (
<CorporationRoot corp={player.corporation} player={player} />
) : page === Page.Bladeburner ? (
<BladeburnerRoot bladeburner={player.bladeburner} />
) : page === Page.Resleeves ? (
<ResleeveRoot player={player} />
) : page === Page.Travel ? (
<TravelAgencyRoot p={player} router={Router} />
) : page === Page.StockMarket ? (
<StockMarketRoot
buyStockLong={buyStock}
buyStockShort={shortStock}
cancelOrder={cancelOrder}
eventEmitterForReset={eventEmitterForUiReset}
initStockMarket={initStockMarketFnForReact}
p={player}
placeOrder={placeOrder}
sellStockLong={sellStock}
sellStockShort={sellShort}
stockMarket={StockMarket}
/>
) : page === Page.City ? (
2021-09-18 10:01:07 +02:00
<LocationCity />
2021-09-18 01:43:08 +02:00
) : page === Page.Job ? (
2021-09-18 10:01:07 +02:00
<GenericLocation loc={location} />
) : page === Page.Location ? (
<GenericLocation loc={location} />
2021-09-18 01:43:08 +02:00
) : page === Page.Options ? (
<GameOptionsRoot
player={player}
save={() => saveObject.saveGame(engine.indexedDb)}
delete={() => saveObject.deleteGame(engine.indexedDb)}
export={() => saveObject.exportGame()}
2021-09-20 00:04:12 +02:00
import={openImportFileHandler}
2021-09-18 01:43:08 +02:00
forceKill={() => {
for (const hostname of Object.keys(AllServers)) {
AllServers[hostname].runningScripts = [];
}
dialogBoxCreate("Forcefully deleted all running scripts. Please save and refresh page.");
}}
softReset={() => {
dialogBoxCreate("Soft Reset!");
prestigeAugmentation();
Router.toTerminal();
}}
/>
) : page === Page.Augmentations ? (
<AugmentationsRoot
exportGameFn={() => {
saveObject.exportGame();
onExport(player);
}}
installAugmentationsFn={() => {
installAugmentations();
Router.toTerminal();
}}
/>
) : (
<>
<Typography>Cannot load</Typography>
</>
)}
</Box>
</Box>
)}
</Context.Router.Provider>
</Context.Player.Provider>
2021-09-17 08:04:44 +02:00
);
}