diff --git a/src/Hacknet/HacknetHelpers.tsx b/src/Hacknet/HacknetHelpers.tsx index 0a90e8df4..92b3d5912 100644 --- a/src/Hacknet/HacknetHelpers.tsx +++ b/src/Hacknet/HacknetHelpers.tsx @@ -24,6 +24,7 @@ import { Server } from "../Server/Server"; import { Companies } from "../Company/Companies"; import { isMember } from "../utils/EnumHelper"; import { canAccessBitNodeFeature } from "../BitNode/BitNodeUtils"; +import { checkServerOwnership, ServerOwnershipType } from "../Server/ServerHelpers"; // Returns a boolean indicating whether the player has Hacknet Servers // (the upgraded form of Hacknet Nodes) @@ -491,7 +492,14 @@ export function purchaseHashUpgrade(upgName: string, upgTarget: string, count = console.error(`Invalid target specified in purchaseHashUpgrade(): ${upgTarget}`); throw new Error(`'${upgTarget}' is not a server.`); } - if (!(target instanceof Server)) throw new Error(`'${upgTarget}' is not a normal server.`); + if (!(target instanceof Server)) { + throw new Error(`'${upgTarget}' is not a normal server.`); + } + if (!checkServerOwnership(target, ServerOwnershipType.Foreign)) { + throw new Error( + `'${upgTarget}' is not a valid target. You can only perform this action on servers that you do not own.`, + ); + } target.changeMinimumSecurity(upg.value ** count, true); } catch (e) { @@ -507,7 +515,14 @@ export function purchaseHashUpgrade(upgName: string, upgTarget: string, count = console.error(`Invalid target specified in purchaseHashUpgrade(): ${upgTarget}`); throw new Error(`'${upgTarget}' is not a server.`); } - if (!(target instanceof Server)) throw new Error(`'${upgTarget}' is not a normal server.`); + if (!(target instanceof Server)) { + throw new Error(`'${upgTarget}' is not a normal server.`); + } + if (!checkServerOwnership(target, ServerOwnershipType.Foreign)) { + throw new Error( + `'${upgTarget}' is not a valid target. You can only perform this action on servers that you do not own.`, + ); + } //Manually loop the change so as to properly handle the softcap for (let i = 0; i < count; i++) { diff --git a/src/Hacknet/ui/HacknetUpgradeElem.tsx b/src/Hacknet/ui/HacknetUpgradeElem.tsx index 4728a75a7..05be64471 100644 --- a/src/Hacknet/ui/HacknetUpgradeElem.tsx +++ b/src/Hacknet/ui/HacknetUpgradeElem.tsx @@ -4,7 +4,7 @@ import { purchaseHashUpgrade } from "../HacknetHelpers"; import { HashManager } from "../HashManager"; import { HashUpgrade } from "../HashUpgrade"; -import { ServerDropdown, ServerType } from "../../ui/React/ServerDropdown"; +import { ServerDropdown } from "../../ui/React/ServerDropdown"; import { CompanyDropdown } from "../../ui/React/CompanyDropdown"; import { dialogBoxCreate } from "../../ui/React/DialogBox"; @@ -18,6 +18,7 @@ import { SelectChangeEvent } from "@mui/material/Select"; import { CompanyName, FactionName } from "@enums"; import { PartialRecord } from "../../Types/Record"; import { isMember } from "../../utils/EnumHelper"; +import { ServerOwnershipType } from "../../Server/ServerHelpers"; interface IProps { hashManager: HashManager; @@ -88,7 +89,7 @@ export function HacknetUpgradeElem(props: IProps): React.ReactElement { purchase={purchase} canPurchase={canPurchase} value={selectedServer} - serverType={ServerType.Foreign} + serverType={ServerOwnershipType.Foreign} onChange={changeTargetServer} /> )} diff --git a/src/Server/ServerHelpers.ts b/src/Server/ServerHelpers.ts index 959ea7bfb..4e0042de3 100644 --- a/src/Server/ServerHelpers.ts +++ b/src/Server/ServerHelpers.ts @@ -5,13 +5,23 @@ import { calculateGrowMoney, calculateServerGrowthLog } from "./formulas/grow"; import { currentNodeMults } from "../BitNode/BitNodeMultipliers"; import { ServerConstants } from "./data/Constants"; import { Player } from "@player"; -import { CompletedProgramName, LiteratureName } from "@enums"; +import { AugmentationName, CompletedProgramName, LiteratureName } from "@enums"; import { Person as IPerson } from "@nsdefs"; import { Server as IServer } from "@nsdefs"; import { workerScripts } from "../Netscript/WorkerScripts"; import { killWorkerScriptByPid } from "../Netscript/killWorkerScript"; import { serverMetadata } from "./data/servers"; import { exceptionAlert } from "../utils/helpers/exceptionAlert"; +import { HacknetServer } from "../Hacknet/HacknetServer"; +import { SpecialServers } from "./data/SpecialServers"; +import { throwIfReachable } from "../utils/helpers/throwIfReachable"; + +export enum ServerOwnershipType { + All = 0, + Foreign = 1, // Non-owned servers + Owned = 2, // Home Computer, Purchased Servers, and Hacknet Servers + Purchased = 3, // Everything from Owned except home computer +} /** * Constructs a new server, while also ensuring that the new server @@ -271,3 +281,32 @@ export function getWeakenEffect(threads: number, cores: number): number { const coreBonus = getCoreBonus(cores); return ServerConstants.ServerWeakenAmount * threads * coreBonus * currentNodeMults.ServerWeakenRate; } + +export function checkServerOwnership(baseServer: BaseServer, serverType: ServerOwnershipType): boolean { + /** + * isOwnedServer is true if baseServer is home, private servers, or hacknet servers. Note that, with home computer, + * baseServer.purchasedByPlayer is true. + */ + const isOwnedServer = + (baseServer instanceof Server && baseServer.purchasedByPlayer) || baseServer instanceof HacknetServer; + switch (serverType) { + case ServerOwnershipType.All: + return true; + case ServerOwnershipType.Foreign: + // Exclude home, private servers, hacknet servers. + if (isOwnedServer) { + return false; + } + // If the player has not installed TRP, exclude WD server. + return ( + Player.hasAugmentation(AugmentationName.TheRedPill, true) || baseServer.hostname !== SpecialServers.WorldDaemon + ); + case ServerOwnershipType.Owned: + return isOwnedServer; + case ServerOwnershipType.Purchased: + return isOwnedServer && baseServer.hostname !== SpecialServers.Home; + default: + throwIfReachable(serverType); + } + return false; +} diff --git a/src/ui/React/ServerDropdown.tsx b/src/ui/React/ServerDropdown.tsx index 75d3e2e1f..8b312d203 100644 --- a/src/ui/React/ServerDropdown.tsx +++ b/src/ui/React/ServerDropdown.tsx @@ -5,71 +5,23 @@ */ import React from "react"; import { GetAllServers } from "../../Server/AllServers"; -import { Server } from "../../Server/Server"; -import { BaseServer } from "../../Server/BaseServer"; -import { Player } from "@player"; -import { HacknetServer } from "../../Hacknet/HacknetServer"; import Select, { SelectChangeEvent } from "@mui/material/Select"; import MenuItem from "@mui/material/MenuItem"; import Button from "@mui/material/Button"; -import { AugmentationName } from "@enums"; -import { SpecialServers } from "../../Server/data/SpecialServers"; -import { throwIfReachable } from "../../utils/helpers/throwIfReachable"; - -export enum ServerType { - All = 0, - Foreign = 1, // Non-owned servers - Owned = 2, // Home Computer, Purchased Servers, and Hacknet Servers - Purchased = 3, // Everything from Owned except home computer -} +import { checkServerOwnership, ServerOwnershipType } from "../../Server/ServerHelpers"; interface IProps { purchase: () => void; canPurchase: boolean; - serverType: ServerType; + serverType: ServerOwnershipType; onChange: (event: SelectChangeEvent) => void; value: string; } export function ServerDropdown(props: IProps): React.ReactElement { - /** - * Checks if the server should be shown in the dropdown menu, based on the - * 'serverType' property - */ - function isValidServer(baseServer: BaseServer): boolean { - /** - * isOwnedServer is true if baseServer is home, private servers, or hacknet servers. Note that, with home computer, - * baseServer.purchasedByPlayer is true. - */ - const isOwnedServer = - (baseServer instanceof Server && baseServer.purchasedByPlayer) || baseServer instanceof HacknetServer; - const type = props.serverType; - switch (type) { - case ServerType.All: - return true; - case ServerType.Foreign: - // Exclude home, private servers, hacknet servers. - if (isOwnedServer) { - return false; - } - // If the player has not installed TRP, exclude WD server. - return ( - Player.hasAugmentation(AugmentationName.TheRedPill, true) || - baseServer.hostname !== SpecialServers.WorldDaemon - ); - case ServerType.Owned: - return isOwnedServer; - case ServerType.Purchased: - return isOwnedServer && baseServer.hostname !== SpecialServers.Home; - default: - throwIfReachable(type); - } - return false; - } - const servers = []; for (const server of GetAllServers().sort((a, b) => a.hostname.localeCompare(b.hostname))) { - if (isValidServer(server)) { + if (checkServerOwnership(server, props.serverType)) { servers.push( {server.hostname}