diff --git a/css/activescripts.scss b/css/activescripts.scss index 35e959558..f5f7593ba 100644 --- a/css/activescripts.scss +++ b/css/activescripts.scss @@ -6,7 +6,6 @@ .active-scripts-container { > p { - width: 70%; margin: 6px; padding: 4px; } diff --git a/css/augmentations.scss b/css/augmentations.scss index 2615aa4d6..53193ae1e 100644 --- a/css/augmentations.scss +++ b/css/augmentations.scss @@ -8,7 +8,6 @@ .augmentations-content { > p { font-size: $defaultFontSize * 0.875; - width: 70%; } } diff --git a/css/hacknetnodes.scss b/css/hacknetnodes.scss index f06b0b79a..97bf22122 100644 --- a/css/hacknetnodes.scss +++ b/css/hacknetnodes.scss @@ -7,7 +7,6 @@ .hacknet-general-info { margin: 10px; - width: 70vw; } #hacknet-nodes-container li { diff --git a/src/Augmentation/AugmentationHelpers.d.ts b/src/Augmentation/AugmentationHelpers.d.ts index 9e2bb7935..c20c69364 100644 --- a/src/Augmentation/AugmentationHelpers.d.ts +++ b/src/Augmentation/AugmentationHelpers.d.ts @@ -1 +1,2 @@ export declare function isRepeatableAug(aug: Augmentation): boolean; +export declare function installAugmentations(): void; diff --git a/src/Faction/FactionHelpers.d.ts b/src/Faction/FactionHelpers.d.ts index be7642c9a..a4a952b31 100644 --- a/src/Faction/FactionHelpers.d.ts +++ b/src/Faction/FactionHelpers.d.ts @@ -6,3 +6,4 @@ export declare function hasAugmentationPrereqs(aug: Augmentation): boolean; export declare function purchaseAugmentation(aug: Augmentation, fac: Faction, sing?: boolean): void; export declare function displayFactionContent(factionName: string, initiallyOnAugmentationsPage: boolean = false); export declare function joinFaction(faction: Faction): void; +export declare function startHackingMission(faction: Faction): void; diff --git a/src/Faction/FactionHelpers.jsx b/src/Faction/FactionHelpers.jsx index 772444402..1e5f0e166 100644 --- a/src/Faction/FactionHelpers.jsx +++ b/src/Faction/FactionHelpers.jsx @@ -1,7 +1,7 @@ import React from "react"; import ReactDOM from "react-dom"; -import { FactionRoot } from "./ui/Root"; +import { FactionRoot } from "./ui/FactionRoot"; import { Augmentations } from "../Augmentation/Augmentations"; import { PlayerOwnedAugmentation } from "../Augmentation/PlayerOwnedAugmentation"; diff --git a/src/Faction/ui/Root.tsx b/src/Faction/ui/FactionRoot.tsx similarity index 92% rename from src/Faction/ui/Root.tsx rename to src/Faction/ui/FactionRoot.tsx index 694fa9059..50655ea62 100644 --- a/src/Faction/ui/Root.tsx +++ b/src/Faction/ui/FactionRoot.tsx @@ -24,8 +24,7 @@ import { CreateGangPopup } from "./CreateGangPopup"; type IProps = { engine: IEngine; - initiallyOnAugmentationsPage?: boolean; - faction: Faction; + faction: Faction | null; p: IPlayer; startHackingMissionFn: (faction: Faction) => void; }; @@ -33,6 +32,7 @@ type IProps = { type IState = { rerenderFlag: boolean; purchasingAugs: boolean; + faction: Faction; }; // Info text for all options on the UI @@ -74,11 +74,13 @@ const GangNames = [ export class FactionRoot extends React.Component { constructor(props: IProps) { + if (props.faction === null) throw new Error("Trying to render the Faction page with null faction"); super(props); this.state = { rerenderFlag: false, - purchasingAugs: props.initiallyOnAugmentationsPage ? props.initiallyOnAugmentationsPage : false, + purchasingAugs: false, + faction: props.faction, }; this.manageGang = this.manageGang.bind(this); @@ -101,7 +103,7 @@ export class FactionRoot extends React.Component { const popupId = "create-gang-popup"; createPopup(popupId, CreateGangPopup, { popupId: popupId, - facName: this.props.faction.name, + facName: this.state.faction.name, p: this.props.p, engine: this.props.engine, }); @@ -130,22 +132,22 @@ export class FactionRoot extends React.Component { } startFieldWork(): void { - this.props.p.startFactionFieldWork(this.props.faction); + this.props.p.startFactionFieldWork(this.state.faction); } startHackingContracts(): void { - this.props.p.startFactionHackWork(this.props.faction); + this.props.p.startFactionHackWork(this.state.faction); } startHackingMission(): void { - const fac = this.props.faction; + const fac = this.state.faction; this.props.p.singularityStopWork(); this.props.engine.loadMissionContent(); this.props.startHackingMissionFn(fac); } startSecurityWork(): void { - this.props.p.startFactionSecurityWork(this.props.faction); + this.props.p.startFactionSecurityWork(this.state.faction); } render(): React.ReactNode { @@ -154,7 +156,7 @@ export class FactionRoot extends React.Component { renderMainPage(): React.ReactNode { const p = this.props.p; - const faction = this.props.faction; + const faction = this.state.faction; const factionInfo = faction.getInfo(); // We have a special flag for whether the player this faction is the player's @@ -200,7 +202,7 @@ export class FactionRoot extends React.Component { )} {!isPlayersGang && factionInfo.offersWork() && ( { renderAugmentationsPage(): React.ReactNode { return ( <> - + ); } diff --git a/src/Faction/ui/FactionList.tsx b/src/Faction/ui/FactionsRoot.tsx similarity index 81% rename from src/Faction/ui/FactionList.tsx rename to src/Faction/ui/FactionsRoot.tsx index 358771ed2..fbed0ae67 100644 --- a/src/Faction/ui/FactionList.tsx +++ b/src/Faction/ui/FactionsRoot.tsx @@ -1,20 +1,20 @@ import React, { useState } from "react"; import { IPlayer } from "../../PersonObjects/IPlayer"; -import { IEngine } from "../../IEngine"; +import { IRouter } from "../../ui/Router"; import { Factions } from "../Factions"; -import { displayFactionContent, joinFaction } from "../FactionHelpers"; +import { Faction } from "../Faction"; +import { joinFaction } from "../FactionHelpers"; interface IProps { player: IPlayer; - engine: IEngine; + router: IRouter; } -export function FactionList(props: IProps): React.ReactElement { +export function FactionsRoot(props: IProps): React.ReactElement { const setRerender = useState(false)[1]; - function openFaction(faction: string): void { - props.engine.loadFactionContent(); - displayFactionContent(faction); + function openFaction(faction: Faction): void { + props.router.toFaction(faction); } function acceptInvitation(event: React.MouseEvent, faction: string): void { @@ -33,7 +33,7 @@ export function FactionList(props: IProps): React.ReactElement {
  • openFaction(faction)} + onClick={() => openFaction(Factions[faction])} style={{ padding: "4px", margin: "4px", display: "inline-block" }} > {faction} diff --git a/src/Gang/IGang.ts b/src/Gang/IGang.ts index b99f52f1d..00d7911cc 100644 --- a/src/Gang/IGang.ts +++ b/src/Gang/IGang.ts @@ -2,6 +2,7 @@ import { GangMemberUpgrade } from "./GangMemberUpgrade"; import { GangMember } from "./GangMember"; import { WorkerScript } from "../Netscript/WorkerScript"; import { IPlayer } from "../PersonObjects/IPlayer"; +import { IAscensionResult } from "./IAscensionResult"; export interface IGang { facName: string; @@ -37,8 +38,9 @@ export interface IGang { getWantedPenalty(): number; calculatePower(): number; killMember(member: GangMember): void; - ascendMember(member: GangMember, workerScript: WorkerScript): void; + ascendMember(member: GangMember, workerScript: WorkerScript): IAscensionResult; getDiscount(): number; getAllTaskNames(): string[]; getUpgradeCost(upg: GangMemberUpgrade): number; + toJSON(): any; } diff --git a/src/Locations/ui/GenericLocation.tsx b/src/Locations/ui/GenericLocation.tsx index 3d6fa9168..f5f345483 100644 --- a/src/Locations/ui/GenericLocation.tsx +++ b/src/Locations/ui/GenericLocation.tsx @@ -12,7 +12,7 @@ import { HospitalLocation } from "./HospitalLocation"; import { SlumsLocation } from "./SlumsLocation"; import { SpecialLocation } from "./SpecialLocation"; import { TechVendorLocation } from "./TechVendorLocation"; -import { TravelAgencyLocation } from "./TravelAgencyLocation"; +import { TravelAgencyRoot } from "./TravelAgencyRoot"; import { UniversityLocation } from "./UniversityLocation"; import { CasinoLocation } from "./CasinoLocation"; @@ -21,6 +21,7 @@ import { LocationType } from "../LocationTypeEnum"; import { CityName } from "../data/CityNames"; import { IEngine } from "../../IEngine"; +import { IRouter } from "../../ui/Router"; import { IPlayer } from "../../PersonObjects/IPlayer"; import { Settings } from "../../Settings/Settings"; @@ -32,6 +33,7 @@ import { CorruptableText } from "../../ui/React/CorruptableText"; type IProps = { engine: IEngine; + router: IRouter; loc: Location; p: IPlayer; returnToCity: () => void; @@ -91,7 +93,7 @@ export class GenericLocation extends React.Component { } if (this.props.loc.types.includes(LocationType.TravelAgency)) { - content.push(); + content.push(); } if (this.props.loc.types.includes(LocationType.University)) { diff --git a/src/Locations/ui/Root.tsx b/src/Locations/ui/Root.tsx index f554e7e06..ec7e5c58b 100644 --- a/src/Locations/ui/Root.tsx +++ b/src/Locations/ui/Root.tsx @@ -15,6 +15,7 @@ import { LocationName } from "../data/LocationNames"; import { CONSTANTS } from "../../Constants"; import { IEngine } from "../../IEngine"; +import { IRouter } from "../../ui/Router"; import { IPlayer } from "../../PersonObjects/IPlayer"; import { dialogBoxCreate } from "../../../utils/DialogBox"; @@ -22,6 +23,7 @@ import { dialogBoxCreate } from "../../../utils/DialogBox"; type IProps = { initiallyInCity?: boolean; engine: IEngine; + router: IRouter; p: IPlayer; }; @@ -47,6 +49,10 @@ export class LocationRoot extends React.Component { } enterLocation(to: LocationName): void { + if (to == LocationName.TravelAgency) { + this.props.router.toTravel(); + return; + } this.props.p.gotoLocation(to); this.setState({ inCity: false, @@ -98,6 +104,7 @@ export class LocationRoot extends React.Component { return ( void; + router: IRouter; }; -function createTravelPopup(p: IPlayer, city: string, travel: () => void): void { +function travel(p: IPlayer, router: IRouter, to: CityName): void { + const cost = CONSTANTS.TravelCost; + if (!p.canAfford(cost)) { + dialogBoxCreate(`You cannot afford to travel to ${to}`); + return; + } + + p.loseMoney(cost); + p.travel(to); + dialogBoxCreate(You are now in {to}!); + router.toCity(); +} + +function createTravelPopup(p: IPlayer, router: IRouter, city: CityName): void { if (Settings.SuppressTravelConfirmation) { - travel(); + travel(p, router, city); return; } const popupId = `travel-confirmation`; createPopup(popupId, TravelConfirmationPopup, { player: p, city: city, - travel: travel, + travel: () => travel(p, router, city), popupId: popupId, }); } @@ -45,7 +60,7 @@ function ASCIIWorldMap(props: IProps): React.ReactElement {

    createTravelPopup(props.p, city, () => props.travel(city))} + onTravel={(city: CityName) => createTravelPopup(props.p, props.router, city)} /> ); @@ -66,7 +81,7 @@ function ListWorldMap(props: IProps): React.ReactElement { return ( createTravelPopup(props.p, city, () => props.travel(match[1]))} + onClick={() => createTravelPopup(props.p, props.router, city as CityName)} style={{ display: "block" }} text={`Travel to ${city}`} /> @@ -76,10 +91,15 @@ function ListWorldMap(props: IProps): React.ReactElement { ); } -export function TravelAgencyLocation(props: IProps): React.ReactElement { - if (Settings.DisableASCIIArt) { - return ; - } else { - return ; - } +export function TravelAgencyRoot(props: IProps): React.ReactElement { + return ( + <> +

    Travel Agency

    + {Settings.DisableASCIIArt ? ( + + ) : ( + + )} + + ); } diff --git a/src/PersonObjects/Sleeve/ui/SleeveRoot.tsx b/src/PersonObjects/Sleeve/ui/SleeveRoot.tsx index 9df9c22e6..b7e33961d 100644 --- a/src/PersonObjects/Sleeve/ui/SleeveRoot.tsx +++ b/src/PersonObjects/Sleeve/ui/SleeveRoot.tsx @@ -20,7 +20,7 @@ export function SleeveRoot(props: IProps): React.ReactElement { }, []); return ( -
    + <>

    Sleeves

    Duplicate Sleeves are MK-V Synthoids (synthetic androids) into which your consciousness has been copied. In @@ -50,6 +50,6 @@ export function SleeveRoot(props: IProps): React.ReactElement {

  • ))} - + ); } diff --git a/src/Prestige.d.ts b/src/Prestige.d.ts new file mode 100644 index 000000000..61d353ba4 --- /dev/null +++ b/src/Prestige.d.ts @@ -0,0 +1,2 @@ +export declare function prestigeAugmentation(): void; +export declare function prestigeSourceFile(flume: boolean): void; diff --git a/src/ScriptEditor/ui/Root.tsx b/src/ScriptEditor/ui/Root.tsx index 543ebf9d6..b1eb01bef 100644 --- a/src/ScriptEditor/ui/Root.tsx +++ b/src/ScriptEditor/ui/Root.tsx @@ -308,7 +308,7 @@ export function Root(props: IProps): React.ReactElement { } return ( - + ); } diff --git a/src/Sidebar/ui/SidebarRoot.tsx b/src/Sidebar/ui/SidebarRoot.tsx index b3a27cd94..50086ceab 100644 --- a/src/Sidebar/ui/SidebarRoot.tsx +++ b/src/Sidebar/ui/SidebarRoot.tsx @@ -44,7 +44,7 @@ import LiveHelpIcon from "@mui/icons-material/LiveHelp"; import ExpandLessIcon from "@mui/icons-material/ExpandLess"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; -import { IEngine } from "../../IEngine"; +import { IRouter, Page } from "../../ui/Router"; import { IPlayer } from "../../PersonObjects/IPlayer"; import { CONSTANTS } from "../../Constants"; import { iTutorialSteps, iTutorialNextStep, ITutorial } from "../../InteractiveTutorial"; @@ -56,7 +56,6 @@ import { inMission } from "../../Missions"; import { cinematicTextFlag } from "../../CinematicText"; import { KEY } from "../../../utils/helpers/keyCodes"; import { FconfSettings } from "../../Fconf/FconfSettings"; -import { Page, routing } from "../../ui/navigationTracking"; const drawerWidth = 240; @@ -83,7 +82,6 @@ const closedMixin = (theme: Theme): CSSObject => ({ const Drawer = styled(MuiDrawer, { shouldForwardProp: (prop) => prop !== "open" })(({ theme, open }) => ({ width: theme.spacing(31), - flexShrink: 0, whiteSpace: "nowrap", boxSizing: "border-box", ...(open && { @@ -110,7 +108,8 @@ const useStyles = makeStyles((theme: Theme) => interface IProps { player: IPlayer; - engine: IEngine; + router: IRouter; + page: Page; } export function SidebarRoot(props: IProps): React.ReactElement { @@ -124,7 +123,6 @@ export function SidebarRoot(props: IProps): React.ReactElement { return () => clearInterval(id); }, []); - const [activeTab, setActiveTab] = useState("Terminal"); const [hackingOpen, setHackingOpen] = useState(true); const [characterOpen, setCharacterOpen] = useState(true); const [worldOpen, setWorldOpen] = useState(true); @@ -176,108 +174,88 @@ export function SidebarRoot(props: IProps): React.ReactElement { const canBladeburner = !!(props.player.bladeburner as any); function clickTerminal(): void { - setActiveTab("Terminal"); - props.engine.loadTerminalContent(); + props.router.toTerminal(); if (flashTerminal) iTutorialNextStep(); } function clickCreateScripts(): void { - setActiveTab("CreateScripts"); - props.engine.loadScriptEditorContent(); + props.router.toScriptEditor(); } function clickStats(): void { - setActiveTab("Stats"); - props.engine.loadCharacterContent(); + props.router.toCharacterInfo(); if (flashStats) iTutorialNextStep(); } function clickActiveScripts(): void { - setActiveTab("ActiveScripts"); - props.engine.loadActiveScriptsContent(); + props.router.toActiveScripts(); if (flashActiveScripts) iTutorialNextStep(); } function clickCreateProgram(): void { - setActiveTab("CreateProgram"); - props.engine.loadCreateProgramContent(); + props.router.toCreateProgram(); } function clickFactions(): void { - setActiveTab("Factions"); - props.engine.loadFactionsContent(); + props.router.toFactions(); } function clickAugmentations(): void { - setActiveTab("Augmentations"); - props.engine.loadAugmentationsContent(); + props.router.toAugmentations(); } function clickSleeves(): void { - setActiveTab("Sleeves"); - props.engine.loadSleevesContent(); + props.router.toSleeves(); } function clickHacknet(): void { - setActiveTab("Hacknet"); - props.engine.loadHacknetNodesContent(); + props.router.toHacknetNodes(); if (flashHacknet) iTutorialNextStep(); } function clickCity(): void { - setActiveTab("City"); - props.engine.loadLocationContent(); + props.router.toCity(); if (flashCity) iTutorialNextStep(); } function clickTravel(): void { - setActiveTab("Travel"); - props.engine.loadTravelContent(); + props.router.toTravel(); } function clickJob(): void { - setActiveTab("Job"); - props.engine.loadJobContent(); + props.router.toJob(); } function clickStockMarket(): void { - setActiveTab("StockMarket"); - props.engine.loadStockMarketContent(); + props.router.toStockMarket(); } function clickBladeburner(): void { - setActiveTab("Bladeburner"); - props.engine.loadBladeburnerContent(); + props.router.toBladeburner(); } function clickCorp(): void { - setActiveTab("Corp"); - props.engine.loadCorporationContent(); + props.router.toCorporation(); } function clickGang(): void { - setActiveTab("Gang"); - props.engine.loadGangContent(); + props.router.toGang(); } function clickTutorial(): void { - setActiveTab("Tutorial"); - props.engine.loadTutorialContent(); + props.router.toTutorial(); if (flashTutorial) iTutorialNextStep(); } function clickMilestones(): void { - setActiveTab("Milestones"); - props.engine.loadMilestonesContent(); + props.router.toMilestones(); } function clickOptions(): void { - setActiveTab("Options"); - props.engine.loadGameOptionsContent(); + props.router.toGameOptions(); } function clickDev(): void { - setActiveTab("Dev"); - props.engine.loadDevMenuContent(); + props.router.toDevMenu(); } useEffect(() => { @@ -327,7 +305,7 @@ export function SidebarRoot(props: IProps): React.ReactElement { clickCreateProgram(); } else if (event.keyCode === KEY.F && event.altKey) { // Overriden by Fconf - if (routing.isOn(Page.Terminal) && FconfSettings.ENABLE_BASH_HOTKEYS) { + if (props.page == Page.Terminal && FconfSettings.ENABLE_BASH_HOTKEYS) { return; } event.preventDefault(); @@ -359,421 +337,427 @@ export function SidebarRoot(props: IProps): React.ReactElement { const [open, setOpen] = useState(true); const toggleDrawer = (): void => setOpen((old) => !old); return ( - - - + + + + {!open ? : } + + Bitburner v{CONSTANTS.Version}} /> + + + + setHackingOpen((old) => !old)}> - {!open ? : } + - Bitburner v{CONSTANTS.Version}} /> + Hacking} /> + {hackingOpen ? : } - - - setHackingOpen((old) => !old)}> - - - - Hacking} /> - {hackingOpen ? : } - - - - - - - - - - Terminal - - - - - - - - - Create Script - - - - - - - - - Active Scripts - - - - {canCreateProgram && ( - + + + + + + + + Terminal + + + + + + + + + + Create Script + + + + + + + + + - - 0 ? programCount : undefined} color="error"> - - - - - - Create Program - - - - )} - - - - - setCharacterOpen((old) => !old)}> - - - - Character} /> - {characterOpen ? : } - - - - - - - - - Stats + Active Scripts - {canOpenFactions && ( + {canCreateProgram && ( - - + 0 ? programCount : undefined} color="error"> + - Factions + + Create Program + )} - {canOpenAugmentations && ( - - - - - - - - Augmentations - - - )} - - - - - - - Hacknet - - - - {canOpenSleeves && ( - - - - - - Sleeves - - - )} - + + - - setWorldOpen((old) => !old)}> + + setCharacterOpen((old) => !old)}> + + + + Character} /> + {characterOpen ? : } + + + - + - World} /> - {worldOpen ? : } + + + Stats + + - + {canOpenFactions && ( - + + + - - City + + Factions + )} + {canOpenAugmentations && ( - + + + - Travel + + Augmentations + - {canJob && ( - - - - - - Job - - - )} - {canStockMarket && ( - - - - - - Stock Market - - - )} - {canBladeburner && ( - - - - - - Bladeburner - - - )} - {canCorporation && ( - - - - - - Corp - - - )} - {canGang && ( - - - - - - Gang - - - )} - + )} + + + + + + + Hacknet + + + + {canOpenSleeves && ( + + + + + + Sleeves + + + )} + - - setHelpOpen((old) => !old)}> + + setWorldOpen((old) => !old)}> + + + + World} /> + {worldOpen ? : } + + + - + - Help} /> - {helpOpen ? : } + + + City + + - + + + + + + Travel + + + {canJob && ( - + - Milestones + Job + )} + {canStockMarket && ( - + - - Tutorial - + Stock Market + )} + {canBladeburner && ( - + - Options + Bladeburner - {process.env.NODE_ENV === "development" && ( - - - - - - Dev - - - )} - - - - + )} + {canCorporation && ( + + + + + + Corp + + + )} + {canGang && ( + + + + + + Gang + + + )} + + + + setHelpOpen((old) => !old)}> + + + + Help} /> + {helpOpen ? : } + + + + + + + + Milestones + + + + + + + + + Tutorial + + + + + + + + + Options + + + {process.env.NODE_ENV === "development" && ( + + + + + + Dev + + + )} + + + ); } diff --git a/src/StockMarket/StockMarket.tsx b/src/StockMarket/StockMarket.tsx index 3846e1889..dbb62e2e7 100644 --- a/src/StockMarket/StockMarket.tsx +++ b/src/StockMarket/StockMarket.tsx @@ -9,7 +9,7 @@ import { InitStockMetadata } from "./data/InitStockMetadata"; import { OrderTypes } from "./data/OrderTypes"; import { PositionTypes } from "./data/PositionTypes"; import { StockSymbols } from "./data/StockSymbols"; -import { StockMarketRoot } from "./ui/Root"; +import { StockMarketRoot } from "./ui/StockMarketRoot"; import { CONSTANTS } from "../Constants"; import { WorkerScript } from "../Netscript/WorkerScript"; diff --git a/src/StockMarket/ui/Root.tsx b/src/StockMarket/ui/StockMarketRoot.tsx similarity index 100% rename from src/StockMarket/ui/Root.tsx rename to src/StockMarket/ui/StockMarketRoot.tsx diff --git a/src/Terminal/ui/TerminalRoot.tsx b/src/Terminal/ui/TerminalRoot.tsx index 3cc00a346..cc4de1e29 100644 --- a/src/Terminal/ui/TerminalRoot.tsx +++ b/src/Terminal/ui/TerminalRoot.tsx @@ -76,7 +76,7 @@ export function TerminalRoot({ terminal, engine, player }: IProps): React.ReactE const classes = useStyles(); return ( <> - + {terminal.outputHistory.map((item, i) => { if (item instanceof Output) @@ -105,7 +105,7 @@ export function TerminalRoot({ terminal, engine, player }: IProps): React.ReactE {terminal.action !== null && }
    - + diff --git a/src/engine.jsx b/src/engine.jsx index 25ab34d64..ec3856841 100644 --- a/src/engine.jsx +++ b/src/engine.jsx @@ -19,13 +19,14 @@ import { CONSTANTS } from "./Constants"; import { DevMenuRoot } from "./DevMenu"; import { Factions, initFactions } from "./Faction/Factions"; import { processPassiveFactionRepGain, inviteToFaction } from "./Faction/FactionHelpers"; -import { FactionList } from "./Faction/ui/FactionList"; +import { FactionsRoot } from "./Faction/ui/FactionsRoot"; import { Root as BladeburnerRoot } from "./Bladeburner/ui/Root"; import { Root as GangRoot } from "./Gang/ui/Root"; import { SidebarRoot } from "./Sidebar/ui/SidebarRoot"; import { CorporationRoot } from "./Corporation/ui/CorporationRoot"; import { ResleeveRoot } from "./PersonObjects/Resleeving/ui/ResleeveRoot"; import { GameOptionsRoot } from "./ui/React/GameOptionsRoot"; +import { GameRoot } from "./ui/GameRoot"; import { TTheme as Theme } from "./ui/React/Theme"; import { SleeveRoot } from "./PersonObjects/Sleeve/ui/SleeveRoot"; import { displayInfiltrationContent } from "./Infiltration/Helper"; @@ -106,16 +107,16 @@ const Engine = { _idleSpeed: 200, // Speed (in ms) at which the main loop is updated loadTerminalContent: function () { - Engine.hideAllContent(); - Engine.Display.content.style.display = "block"; - routing.navigateTo(Page.CharacterInfo); - ReactDOM.render( - - - , - Engine.Display.content, - ); - MainMenuLinks.Stats.classList.add("active"); + // Engine.hideAllContent(); + // Engine.Display.content.style.display = "block"; + // routing.navigateTo(Page.CharacterInfo); + // ReactDOM.render( + // + // + // , + // Engine.Display.content, + // ); + // MainMenuLinks.Stats.classList.add("active"); }, loadCharacterContent: function () { @@ -171,7 +172,7 @@ const Engine = { Engine.Display.content.style.display = "block"; routing.navigateTo(Page.Factions); MainMenuLinks.Factions.classList.add("active"); - ReactDOM.render(, Engine.Display.content); + ReactDOM.render(, Engine.Display.content); }, // TODO reactify @@ -394,9 +395,9 @@ const Engine = { // Helper function that hides all content hideAllContent: function () { - Engine.Display.content.style.display = "none"; - Engine.Display.content.scrollTop = 0; - ReactDOM.unmountComponentAtNode(Engine.Display.content); + // Engine.Display.content.style.display = "none"; + // Engine.Display.content.scrollTop = 0; + // ReactDOM.unmountComponentAtNode(Engine.Display.content); Engine.Display.infiltrationContent.style.display = "none"; ReactDOM.unmountComponentAtNode(Engine.Display.infiltrationContent); @@ -408,7 +409,6 @@ const Engine = { }, displayCharacterOverviewInfo: function () { - console.log("rendering"); ReactDOM.render( saveObject.saveGame(Engine.indexedDb)} /> @@ -806,15 +806,15 @@ const Engine = { ReactDOM.render( - + , - document.getElementById("sidebar"), + document.getElementById("mainmenu-container"), ); }, setDisplayElements: function () { - Engine.Display.content = document.getElementById("generic-react-container"); - Engine.Display.content.style.display = "none"; + // Engine.Display.content = document.getElementById("generic-react-container"); + // Engine.Display.content.style.display = "none"; Engine.Display.missionContent = document.getElementById("mission-container"); Engine.Display.missionContent.style.display = "none"; diff --git a/src/ui/GameRoot.tsx b/src/ui/GameRoot.tsx new file mode 100644 index 000000000..b8c27ca85 --- /dev/null +++ b/src/ui/GameRoot.tsx @@ -0,0 +1,194 @@ +import React, { useState, useEffect, useRef } from "react"; + +import { IPlayer } from "../PersonObjects/IPlayer"; +import { IEngine } from "../IEngine"; +import { ITerminal } from "../Terminal/ITerminal"; +import { installAugmentations } from "../Augmentation/AugmentationHelpers"; +import { saveObject } from "../SaveObject"; +import { onExport } from "../ExportBonus"; +import { LocationName } from "../Locations/data/LocationNames"; +import { CityName } from "../Locations/data/CityNames"; +import { Faction } from "../Faction/Faction"; +import { prestigeAugmentation } from "../Prestige"; +import { dialogBoxCreate } from "../../utils/DialogBox"; +import { AllServers } from "../Server/AllServers"; + +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"; +import { SidebarRoot } from "../Sidebar/ui/SidebarRoot"; +import { AugmentationsRoot } from "../Augmentation/ui/Root"; +import { DevMenuRoot } from "../DevMenu"; +import { Root as BladeburnerRoot } from "../Bladeburner/ui/Root"; +import { Root as GangRoot } from "../Gang/ui/Root"; +import { CorporationRoot } from "../Corporation/ui/CorporationRoot"; +import { ResleeveRoot } from "../PersonObjects/Resleeving/ui/ResleeveRoot"; +import { GameOptionsRoot } from "../ui/React/GameOptionsRoot"; +import { SleeveRoot } from "../PersonObjects/Sleeve/ui/SleeveRoot"; +import { HacknetRoot } from "../Hacknet/ui/HacknetRoot"; +import { LocationRoot } from "../Locations/ui/Root"; +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"; +import { ActiveScriptsRoot } from "../ui/ActiveScripts/Root"; +import { FactionsRoot } from "../Faction/ui/FactionsRoot"; +import { FactionRoot } from "../Faction/ui/FactionRoot"; +import { CharacterInfo } from "./CharacterInfo"; +import { TravelAgencyRoot } from "../Locations/ui/TravelAgencyRoot"; +import { StockMarketRoot } from "../Locations/ui/StockMarketRoot"; +import { workerScripts } from "../Netscript/WorkerScripts"; + +import { startHackingMission } from "../Faction/FactionHelpers"; + +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 */, + }, + }), +); + +export function GameRoot({ player, engine, terminal }: IProps): React.ReactElement { + const contentRef = useRef(null); + const [faction, setFaction] = useState(null); + const [page, setPage] = useState(Page.Terminal); + const classes = useStyles(); + + const router = { + toActiveScripts: () => setPage(Page.ActiveScripts), + toAugmentations: () => setPage(Page.Augmentations), + toBladeburner: () => setPage(Page.Bladeburner), + toCharacterInfo: () => setPage(Page.Stats), + toCorporation: () => setPage(Page.Corporation), + toCreateProgram: () => setPage(Page.CreateProgram), + toDevMenu: () => setPage(Page.DevMenu), + toFaction: (faction: Faction) => { + setPage(Page.Faction); + setFaction(faction); + }, + toFactions: () => setPage(Page.Factions), + toGameOptions: () => setPage(Page.Options), + toGang: () => setPage(Page.Gang), + toHacknetNodes: () => setPage(Page.Hacknet), + toMilestones: () => setPage(Page.Milestones), + toResleeves: () => setPage(Page.Resleeves), + toScriptEditor: () => setPage(Page.CreateScript), + toSleeves: () => setPage(Page.Sleeves), + toStockMarket: () => setPage(Page.StockMarket), + toTerminal: () => setPage(Page.Terminal), + toTutorial: () => setPage(Page.Tutorial), + toJob: () => setPage(Page.Job), + toCity: () => { + // TODO This is bad. + player.gotoLocation(player.city as unknown as LocationName); + setPage(Page.City); + }, + toTravel: () => { + player.gotoLocation(LocationName.TravelAgency); + setPage(Page.Travel); + }, + }; + + return ( + <> + + + + {page === Page.Terminal ? ( + + ) : page === Page.Sleeves ? ( + + ) : page === Page.Stats ? ( + + ) : page === Page.CreateScript ? ( + + ) : page === Page.ActiveScripts ? ( + + ) : page === Page.Hacknet ? ( + + ) : page === Page.CreateProgram ? ( + + ) : page === Page.Factions ? ( + + ) : page === Page.Faction ? ( + + ) : page === Page.Milestones ? ( + + ) : page === Page.Tutorial ? ( + + ) : page === Page.DevMenu ? ( + + ) : page === Page.Gang ? ( + + ) : page === Page.Corporation ? ( + + ) : page === Page.Bladeburner ? ( + + ) : page === Page.Resleeves ? ( + + ) : page === Page.Travel ? ( + + ) : page === Page.City ? ( + + ) : page === Page.StockMarket ? ( + + ) : page === Page.Options ? ( + saveObject.saveGame(engine.indexedDb)} + delete={() => saveObject.deleteGame(engine.indexedDb)} + export={() => saveObject.exportGame()} + import={() => saveObject.importGame()} + 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(); + }} + /> + ) : page === Page.Augmentations ? ( + { + saveObject.exportGame(); + onExport(player); + }} + installAugmentationsFn={installAugmentations} + /> + ) : ( + <> + Cannot load + + )} + + + + ); +} diff --git a/src/ui/Router.ts b/src/ui/Router.ts new file mode 100644 index 000000000..58ad8732b --- /dev/null +++ b/src/ui/Router.ts @@ -0,0 +1,62 @@ +import { Faction } from "../Faction/Faction"; +/** + * The full-screen page the player is currently be on. + * These pages are mutually exclusive. + */ +export enum Page { + ActiveScripts, + Augmentations, + Bladeburner, + Stats, + City, + Corporation, + CreateProgram, + DevMenu, + Faction, + Factions, + Options, + Gang, + Hacknet, + Job, + Milestones, + Resleeves, + CreateScript, + Sleeves, + StockMarket, + Terminal, + Travel, + Tutorial, +} + +/** + * This class keeps track of player navigation/routing within the game. + */ +export interface IRouter { + // toCinematicText(): void; + // toInfiltration(): void; + // toMission(): void; + // toRedPill(): void; + // toworkInProgress(): void; + toActiveScripts(): void; + toAugmentations(): void; + toBladeburner(): void; + toCharacterInfo(): void; + toCorporation(): void; + toCreateProgram(): void; + toDevMenu(): void; + toFaction(faction: Faction): void; // faction name + toFactions(): void; + toGameOptions(): void; + toGang(): void; + toHacknetNodes(): void; + toCity(): void; // travel ? city ? + toJob(): void; + toMilestones(): void; + toResleeves(): void; + toScriptEditor(filename?: string, code?: string): void; + toSleeves(): void; + toStockMarket(): void; + toTerminal(): void; + toTravel(): void; + toTutorial(): void; +}