bitburner-src/src/Server/ServerPurchases.ts

167 lines
6.1 KiB
TypeScript
Raw Normal View History

/**
* Implements functions for purchasing servers or purchasing more RAM for
* the home computer
*/
2022-10-09 08:32:13 +02:00
import { AddToAllServers, createUniqueRandomIp, GetServer, renameServer } from "./AllServers";
2022-10-09 07:25:31 +02:00
import { safelyCreateUniqueServer } from "./ServerHelpers";
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
import { CONSTANTS } from "../Constants";
import { Player } from "@player";
2021-09-25 20:42:57 +02:00
import { dialogBoxCreate } from "../ui/React/DialogBox";
import { isPowerOfTwo } from "../utils/helpers/isPowerOfTwo";
import { WorkerScript } from "../Netscript/WorkerScript";
2022-10-09 08:32:13 +02:00
import { workerScripts } from "../Netscript/WorkerScripts";
// Returns the cost of purchasing a server with the given RAM
// Returns Infinity for invalid 'ram' arguments
/**
* @param ram Amount of RAM on purchased server (GB)
* @returns Cost of purchasing the given server. Returns infinity for invalid arguments
*/
2021-05-01 09:17:31 +02:00
export function getPurchaseServerCost(ram: number): number {
2021-09-05 01:09:30 +02:00
const sanitizedRam = Math.round(ram);
if (isNaN(sanitizedRam) || !isPowerOfTwo(sanitizedRam) || !(Math.sign(sanitizedRam) === 1)) {
2021-09-05 01:09:30 +02:00
return Infinity;
}
if (sanitizedRam > getPurchaseServerMaxRam()) {
return Infinity;
}
2021-10-27 04:03:34 +02:00
const upg = Math.max(0, Math.log(sanitizedRam) / Math.log(2) - 6);
2021-10-17 04:32:48 +02:00
2022-02-23 08:01:48 +01:00
return (
2021-10-17 04:32:48 +02:00
sanitizedRam *
CONSTANTS.BaseCostFor1GBOfRamServer *
BitNodeMultipliers.PurchasedServerCost *
Math.pow(BitNodeMultipliers.PurchasedServerSoftcap, upg)
);
}
2022-10-09 08:32:13 +02:00
export const getPurchasedServerUpgradeCost = (hostname: string, ram: number): number => {
const server = GetServer(hostname);
if (!server) throw new Error(`Server '${hostname}' not found.`);
if (!Player.purchasedServers.includes(hostname)) throw new Error(`Server '${hostname}' not a purchased server.`);
if (isNaN(ram) || !isPowerOfTwo(ram) || !(Math.sign(ram) === 1))
throw new Error(`${ram} is not a positive power of 2`);
if (server.maxRam >= ram)
throw new Error(`'${hostname}' current ram (${server.maxRam}) is not bigger than new ram (${ram})`);
return getPurchaseServerCost(ram) - getPurchaseServerCost(server.maxRam);
};
export const upgradePurchasedServer = (hostname: string, ram: number): void => {
const server = GetServer(hostname);
if (!server) throw new Error(`Server '${hostname}' not found.`);
const cost = getPurchasedServerUpgradeCost(hostname, ram);
if (!Player.canAfford(cost)) throw new Error(`You don't have enough money to upgrade '${hostname}'.`);
Player.loseMoney(cost, "servers");
server.maxRam = ram;
};
export const renamePurchasedServer = (hostname: string, newName: string): void => {
const server = GetServer(hostname);
if (!server) throw new Error(`Server '${hostname}' doesn't exists.`);
2022-10-09 08:32:13 +02:00
if (GetServer(newName)) throw new Error(`Server '${newName}' already exists.`);
if (!Player.purchasedServers.includes(hostname)) throw new Error(`Server '${hostname}' is not a player server.`);
const replace = (arr: string[], old: string, next: string): string[] => {
return arr.map((v) => (v === old ? next : v));
};
Player.purchasedServers = replace(Player.purchasedServers, hostname, newName);
if (Player.currentServer === hostname) Player.currentServer = newName;
2022-10-09 08:32:13 +02:00
const home = Player.getHomeComputer();
home.serversOnNetwork = replace(home.serversOnNetwork, hostname, newName);
server.serversOnNetwork = replace(server.serversOnNetwork, hostname, newName);
for (const byPid of server.runningScriptMap.values()) {
for (const r of byPid.values()) {
r.server = newName;
// Lookup can't fail.
const ws = workerScripts.get(r.pid) as WorkerScript;
ws.hostname = newName;
}
}
2022-10-09 08:32:13 +02:00
server.scripts.forEach((r) => (r.server = newName));
server.hostname = newName;
renameServer(hostname, newName);
};
2021-05-01 09:17:31 +02:00
export function getPurchaseServerLimit(): number {
2021-09-09 05:47:34 +02:00
return Math.round(CONSTANTS.PurchasedServerLimit * BitNodeMultipliers.PurchasedServerLimit);
}
2021-05-01 09:17:31 +02:00
export function getPurchaseServerMaxRam(): number {
2021-09-09 05:47:34 +02:00
const ram = Math.round(CONSTANTS.PurchasedServerMaxRam * BitNodeMultipliers.PurchasedServerMaxRam);
2021-09-05 01:09:30 +02:00
// Round this to the nearest power of 2
return 1 << (31 - Math.clz32(ram));
}
// Manually purchase a server (NOT through Netscript)
2022-09-06 15:07:12 +02:00
export function purchaseServer(hostname: string, ram: number, cost: number): void {
2021-09-05 01:09:30 +02:00
//Check if player has enough money
2022-09-06 15:07:12 +02:00
if (!Player.canAfford(cost)) {
dialogBoxCreate("You don't have enough money to purchase this server!");
2021-09-05 01:09:30 +02:00
return;
}
//Maximum server limit
2022-09-06 15:07:12 +02:00
if (Player.purchasedServers.length >= getPurchaseServerLimit()) {
2021-09-05 01:09:30 +02:00
dialogBoxCreate(
"You have reached the maximum limit of " +
getPurchaseServerLimit() +
" servers. " +
"You cannot purchase any more. You can " +
"delete some of your purchased servers using the deleteServer() Netscript function in a script",
);
return;
}
if (hostname == "") {
dialogBoxCreate("You must enter a hostname for your new server!");
return;
}
// Create server
2022-10-09 07:25:31 +02:00
const newServ = safelyCreateUniqueServer({
2021-09-05 01:09:30 +02:00
adminRights: true,
hostname: hostname,
ip: createUniqueRandomIp(),
isConnectedTo: false,
maxRam: ram,
organizationName: "",
purchasedByPlayer: true,
});
AddToAllServers(newServ);
// Add to Player's purchasedServers array
2022-09-06 15:07:12 +02:00
Player.purchasedServers.push(newServ.hostname);
2021-09-05 01:09:30 +02:00
// Connect new server to home computer
2022-09-06 15:07:12 +02:00
const homeComputer = Player.getHomeComputer();
2021-10-07 23:55:49 +02:00
homeComputer.serversOnNetwork.push(newServ.hostname);
newServ.serversOnNetwork.push(homeComputer.hostname);
2021-09-05 01:09:30 +02:00
2022-09-06 15:07:12 +02:00
Player.loseMoney(cost, "servers");
2021-09-05 01:09:30 +02:00
dialogBoxCreate("Server successfully purchased with hostname " + newServ.hostname);
}
// Manually upgrade RAM on home computer (NOT through Netscript)
2022-09-06 15:07:12 +02:00
export function purchaseRamForHomeComputer(): void {
const cost = Player.getUpgradeHomeRamCost();
if (!Player.canAfford(cost)) {
2021-09-09 05:47:34 +02:00
dialogBoxCreate("You do not have enough money to purchase additional RAM for your home computer");
2021-09-05 01:09:30 +02:00
return;
}
2022-09-06 15:07:12 +02:00
const homeComputer = Player.getHomeComputer();
2021-09-05 01:09:30 +02:00
if (homeComputer.maxRam >= CONSTANTS.HomeComputerMaxRam) {
2021-09-09 05:47:34 +02:00
dialogBoxCreate(`You cannot upgrade your home computer RAM because it is at its maximum possible value`);
2021-09-05 01:09:30 +02:00
return;
}
homeComputer.maxRam *= 2;
2022-09-06 15:07:12 +02:00
Player.loseMoney(cost, "servers");
}