fixed v3.0.0 api breaks

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
Vomitblood 2026-05-03 18:27:06 +08:00
parent d5e9028750
commit f8c8a07f44
13 changed files with 2426 additions and 1501 deletions

File diff suppressed because it is too large Load diff

View file

@ -200,6 +200,7 @@ export const defaultMultipliers = (): Multipliers => {
work_money: 1,
crime_success: 1,
crime_money: 1,
dnet_money: 1,
bladeburner_max_stamina: 1,
bladeburner_stamina_gain: 1,
bladeburner_analysis: 1,

View file

@ -1,4 +1,4 @@
import { clampNumber } from "@/utils/utils";
import { utils } from "@/utils/utils";
import { getRecordEntries } from "./constants";
export type PartialRecord<K extends string, V> = Partial<Record<K, V>>;
@ -176,7 +176,7 @@ export class BitNodeMultipliers {
WorldDaemonDifficulty = 1;
constructor(a: PartialRecord<keyof BitNodeMultipliers, number> = {}) {
for (const [key, value] of getRecordEntries(a)) this[key] = clampNumber(value);
for (const [key, value] of getRecordEntries(a)) this[key] = utils.clampNumber(value);
}
}

View file

@ -1,8 +1,8 @@
import { clampNumber, isValidNumber } from "@/utils/utils";
import { Player as IPerson, Server as IServer } from "@ns";
import { ServerConstants } from "./constants";
import { currentNodeMults } from "./exports";
import { Player } from "./player";
import { utils } from "@/utils/utils";
export const hacking = {
growAmount: calculateGrowMoney,
@ -21,11 +21,7 @@ export const hacking = {
};
function calculateIntelligenceBonus(intelligence: number, weight = 1): number {
const effectiveIntelligence =
Player.bitNodeOptions.intelligenceOverride !== undefined
? Math.min(Player.bitNodeOptions.intelligenceOverride, intelligence)
: intelligence;
return 1 + (weight * Math.pow(effectiveIntelligence, 0.8)) / 600;
return 1 + (weight * Math.pow(intelligence, 0.8)) / 600;
}
/** Returns the chance the person has to successfully hack a server */
@ -36,14 +32,14 @@ function calculateHackingChance(server: IServer, person: IPerson): number {
if (!server.hasAdminRights || hackDifficulty >= 100) return 0;
const hackFactor = 1.75;
const difficultyMult = (100 - hackDifficulty) / 100;
const skillMult = clampNumber(hackFactor * person.skills.hacking, 1);
const skillMult = utils.clampNumber(hackFactor * person.skills.hacking, 1);
const skillChance = (skillMult - requiredHackingSkill) / skillMult;
const chance =
skillChance *
difficultyMult *
person.mults.hacking_chance *
calculateIntelligenceBonus(person.skills.intelligence, 1);
return clampNumber(chance, 0, 1);
return utils.clampNumber(chance, 0, 1);
}
/**
@ -79,8 +75,9 @@ function calculatePercentMoneyHacked(server: IServer, person: IPerson): number {
return Math.min(1, Math.max(percentMoneyHacked, 0));
}
/** Returns time it takes to complete a hack on a server, in seconds */
/** Returns time it takes to complete a hack on a server, in milliseconds */
function calculateHackingTime(server: IServer, person: IPerson): number {
if (utils.isDarknetServer(server)) return 16;
const { hackDifficulty, requiredHackingSkill } = server;
if (typeof hackDifficulty !== "number" || typeof requiredHackingSkill !== "number") return Infinity;
const difficultyMult = requiredHackingSkill * hackDifficulty;
@ -98,17 +95,17 @@ function calculateHackingTime(server: IServer, person: IPerson): number {
currentNodeMults.HackingSpeedMultiplier *
calculateIntelligenceBonus(person.skills.intelligence, 1));
return hackingTime;
return hackingTime * 1000;
}
/** Returns time it takes to complete a grow operation on a server, in seconds */
/** Returns time it takes to complete a grow operation on a server, in milliseconds */
function calculateGrowTime(server: IServer, person: IPerson): number {
const growTimeMultiplier = 3.2; // Relative to hacking time. 16/5 = 3.2
return growTimeMultiplier * calculateHackingTime(server, person);
}
/** Returns time it takes to complete a weaken operation on a server, in seconds */
/** Returns time it takes to complete a weaken operation on a server, in milliseconds */
function calculateWeakenTime(server: IServer, person: IPerson): number {
const weakenTimeMultiplier = 4; // Relative to hacking time
@ -160,7 +157,7 @@ function calculateGrowMoney(server: IServer, p: IPerson, threads: number, cores
// cap at max (or data corruption)
if (
server.moneyMax !== undefined &&
isValidNumber(server.moneyMax) &&
utils.isValidNumber(server.moneyMax) &&
(moneyAvailable > server.moneyMax || isNaN(moneyAvailable))
) {
moneyAvailable = server.moneyMax;

View file

@ -1,8 +1,8 @@
import { utils } from "@/utils/utils";
import { Person as IPerson } from "@ns";
import { currentNodeMults } from "./exports";
import { CONSTANTS, log1point02, MaxFavor } from "./constants";
import { currentNodeMults } from "./exports";
import { Player } from "./player";
import { clampNumber } from "@/utils/utils";
export const reputation = {
favorToRep,
@ -16,12 +16,12 @@ export const reputation = {
function favorToRep(f: number): number {
// expm1 is e^x - 1, which is more accurate for small x than doing it the obvious way.
return clampNumber(25000 * Math.expm1(log1point02 * f), 0);
return utils.clampNumber(25000 * Math.expm1(log1point02 * f), 0);
}
function repToFavor(r: number): number {
// log1p is log(x + 1), which is more accurate for small x than doing it the obvious way.
return clampNumber(Math.log1p(r / 25000) / log1point02, 0, MaxFavor);
return utils.clampNumber(Math.log1p(r / 25000) / log1point02, 0, MaxFavor);
}
function calculateFavorAfterResetting(favor: number, playerReputation: number) {

View file

@ -1,4 +1,4 @@
import { clampNumber } from "@/utils/utils";
import { utils } from "@/utils/utils";
export const skills = {
calculateSkill,
@ -18,7 +18,7 @@ export function calculateSkill(exp: number, mult = 1): number {
return 1;
}
const value = Math.floor(mult * (32 * Math.log(exp + 534.6) - 200));
return clampNumber(value, 1);
return utils.clampNumber(value, 1);
}
function calculateExp(skill: number, mult = 1): number {
@ -37,7 +37,7 @@ function calculateExp(skill: number, mult = 1): number {
}
value = newValue;
}
return clampNumber(value, 0);
return utils.clampNumber(value, 0);
}
function calculateSkillProgress(exp: number, mult = 1): ISkillProgress {
@ -50,10 +50,10 @@ function calculateSkillProgress(exp: number, mult = 1): ISkillProgress {
const normalize = (value: number): number => ((value - baseExperience) * 100) / (nextExperience - baseExperience);
const rawProgress = nextExperience - baseExperience !== 0 ? normalize(exp) : 99.99;
const progress = clampNumber(rawProgress, 0, 100);
const progress = utils.clampNumber(rawProgress, 0, 100);
const currentExperience = clampNumber(exp - baseExperience, 0);
const remainingExperience = clampNumber(nextExperience - exp, 0);
const currentExperience = utils.clampNumber(exp - baseExperience, 0);
const remainingExperience = utils.clampNumber(nextExperience - exp, 0);
return {
currentSkill,

View file

@ -1,5 +1,6 @@
import { ezgame } from "@/ezgame";
import { randomNumber } from "@/utils/utils";
import { getNormalServer } from "@/utils/get-normal-server";
import { utils } from "@/utils/utils";
import { NS } from "@ns";
interface TestCase {
@ -7,6 +8,12 @@ interface TestCase {
fn: (ns: NS, serverName: string) => void;
}
// the actual result sometimes has 1 - 2 extra decimal places compared to my implementation,
// which causes tests to fail, so we round both results to 5 decimal places before comparing
function roundTo5Decimals(num: number): number {
return Math.round(num * 100000) / 100000;
}
// add servers to be tested against here
const serverNames: string[] = ["n00dles", "foodnstuff", "joesguns", "sigma-cosmetics", "max-hardware"];
@ -15,9 +22,9 @@ const gangTests = (ns: NS, serverName: string): TestCase[] => [
{
name: "gang.ascensionMultiplier",
fn: (ns, serverName) => {
const points = randomNumber(0, 1e9);
const testResult = ezgame.formulas.gang.ascensionMultiplier(points);
const actualResult = ns.formulas.gang.ascensionMultiplier(points);
const points = utils.randomNumber(0, 1e9);
const testResult = roundTo5Decimals(ezgame.formulas.gang.ascensionMultiplier(points));
const actualResult = roundTo5Decimals(ns.formulas.gang.ascensionMultiplier(points));
if (testResult !== actualResult) {
throw new Error(`expected ${actualResult}, got ${testResult}`);
}
@ -26,9 +33,9 @@ const gangTests = (ns: NS, serverName: string): TestCase[] => [
{
name: "gang.ascensionPointsGain",
fn: (ns, serverName) => {
const exp = randomNumber(0, 1e9);
const testResult = ezgame.formulas.gang.ascensionPointsGain(exp);
const actualResult = ns.formulas.gang.ascensionPointsGain(exp);
const exp = utils.randomNumber(0, 1e9);
const testResult = roundTo5Decimals(ezgame.formulas.gang.ascensionPointsGain(exp));
const actualResult = roundTo5Decimals(ns.formulas.gang.ascensionPointsGain(exp));
if (testResult !== actualResult) {
throw new Error(`expected ${actualResult}, got ${testResult}`);
}
@ -45,12 +52,12 @@ const hackingTests = (ns: NS, serverName: string): TestCase[] => [
{
name: "hacking.growAmount",
fn: (ns, serverName) => {
const server = ns.getServer(serverName);
const server = getNormalServer(ns, serverName);
const player = ns.getPlayer();
const threads = randomNumber(1, 100);
const cores = randomNumber(1, 16);
const testResult = ezgame.formulas.hacking.growAmount(server, player, threads, cores);
const actualResult = ns.formulas.hacking.growAmount(server, player, threads, cores);
const threads = utils.randomNumber(1, 100);
const cores = utils.randomNumber(1, 16);
const testResult = roundTo5Decimals(ezgame.formulas.hacking.growAmount(server, player, threads, cores));
const actualResult = roundTo5Decimals(ns.formulas.hacking.growAmount(server, player, threads, cores));
if (testResult !== actualResult) {
throw new Error(`expected ${actualResult}, got ${testResult}`);
}
@ -59,12 +66,12 @@ const hackingTests = (ns: NS, serverName: string): TestCase[] => [
{
name: "hacking.growPercent",
fn: (ns, serverName) => {
const server = ns.getServer(serverName);
const threads = randomNumber(1, 100);
const server = getNormalServer(ns, serverName);
const threads = utils.randomNumber(1, 100);
const player = ns.getPlayer();
const cores = randomNumber(1, 16);
const testResult = ezgame.formulas.hacking.growPercent(server, threads, player, cores);
const actualResult = ns.formulas.hacking.growPercent(server, threads, player, cores);
const cores = utils.randomNumber(1, 16);
const testResult = roundTo5Decimals(ezgame.formulas.hacking.growPercent(server, threads, player, cores));
const actualResult = roundTo5Decimals(ns.formulas.hacking.growPercent(server, threads, player, cores));
if (testResult !== actualResult) {
throw new Error(`expected ${actualResult}, got ${testResult}`);
}
@ -73,14 +80,14 @@ const hackingTests = (ns: NS, serverName: string): TestCase[] => [
{
name: "hacking.growThreads",
fn: (ns, serverName) => {
const server = ns.getServer(serverName);
const server = getNormalServer(ns, serverName);
const player = ns.getPlayer();
// if moneyMax is not set, use a large number to ensure growThreads returns a valid number of threads
// anyways if it is above moneyMax, the function should clamp it to the max (hopefully)
const targetMoney = server.moneyMax ?? 1e120;
const cores = randomNumber(1, 16);
const testResult = ezgame.formulas.hacking.growThreads(server, player, targetMoney, cores);
const actualResult = ns.formulas.hacking.growThreads(server, player, targetMoney, cores);
const cores = utils.randomNumber(1, 16);
const testResult = roundTo5Decimals(ezgame.formulas.hacking.growThreads(server, player, targetMoney, cores));
const actualResult = roundTo5Decimals(ns.formulas.hacking.growThreads(server, player, targetMoney, cores));
if (testResult !== actualResult) {
throw new Error(`expected ${actualResult}, got ${testResult}`);
}
@ -89,10 +96,10 @@ const hackingTests = (ns: NS, serverName: string): TestCase[] => [
{
name: "hacking.growTime",
fn: (ns, serverName) => {
const server = ns.getServer(serverName);
const server = getNormalServer(ns, serverName);
const player = ns.getPlayer();
const testResult = ezgame.formulas.hacking.growTime(server, player);
const actualResult = ns.formulas.hacking.growTime(server, player);
const testResult = roundTo5Decimals(ezgame.formulas.hacking.growTime(server, player));
const actualResult = roundTo5Decimals(ns.formulas.hacking.growTime(server, player));
if (testResult !== actualResult) {
throw new Error(`expected ${actualResult}, got ${testResult}`);
}
@ -101,10 +108,10 @@ const hackingTests = (ns: NS, serverName: string): TestCase[] => [
{
name: "hacking.hackChance",
fn: (ns, serverName) => {
const server = ns.getServer(serverName);
const server = getNormalServer(ns, serverName);
const player = ns.getPlayer();
const testResult = ezgame.formulas.hacking.hackChance(server, player);
const actualResult = ns.formulas.hacking.hackChance(server, player);
const testResult = roundTo5Decimals(ezgame.formulas.hacking.hackChance(server, player));
const actualResult = roundTo5Decimals(ns.formulas.hacking.hackChance(server, player));
if (testResult !== actualResult) {
throw new Error(`expected ${actualResult}, got ${testResult}`);
}
@ -113,10 +120,10 @@ const hackingTests = (ns: NS, serverName: string): TestCase[] => [
{
name: "hacking.hackExp",
fn: (ns, serverName) => {
const server = ns.getServer(serverName);
const server = getNormalServer(ns, serverName);
const player = ns.getPlayer();
const testResult = ezgame.formulas.hacking.hackExp(server, player);
const actualResult = ns.formulas.hacking.hackExp(server, player);
const testResult = roundTo5Decimals(ezgame.formulas.hacking.hackExp(server, player));
const actualResult = roundTo5Decimals(ns.formulas.hacking.hackExp(server, player));
if (testResult !== actualResult) {
throw new Error(`expected ${actualResult}, got ${testResult}`);
}
@ -125,10 +132,10 @@ const hackingTests = (ns: NS, serverName: string): TestCase[] => [
{
name: "hacking.hackPercent",
fn: (ns, serverName) => {
const server = ns.getServer(serverName);
const server = getNormalServer(ns, serverName);
const player = ns.getPlayer();
const testResult = ezgame.formulas.hacking.hackPercent(server, player);
const actualResult = ns.formulas.hacking.hackPercent(server, player);
const testResult = roundTo5Decimals(ezgame.formulas.hacking.hackPercent(server, player));
const actualResult = roundTo5Decimals(ns.formulas.hacking.hackPercent(server, player));
if (testResult !== actualResult) {
throw new Error(`expected ${actualResult}, got ${testResult}`);
}
@ -137,10 +144,10 @@ const hackingTests = (ns: NS, serverName: string): TestCase[] => [
{
name: "hacking.hackTime",
fn: (ns, serverName) => {
const server = ns.getServer(serverName);
const server = getNormalServer(ns, serverName);
const player = ns.getPlayer();
const testResult = ezgame.formulas.hacking.hackTime(server, player);
const actualResult = ns.formulas.hacking.hackTime(server, player);
const testResult = roundTo5Decimals(ezgame.formulas.hacking.hackTime(server, player));
const actualResult = roundTo5Decimals(ns.formulas.hacking.hackTime(server, player));
if (testResult !== actualResult) {
throw new Error(`expected ${actualResult}, got ${testResult}`);
}
@ -149,10 +156,10 @@ const hackingTests = (ns: NS, serverName: string): TestCase[] => [
{
name: "hacking.weakenTime",
fn: (ns, serverName) => {
const server = ns.getServer(serverName);
const server = getNormalServer(ns, serverName);
const player = ns.getPlayer();
const testResult = ezgame.formulas.hacking.weakenTime(server, player);
const actualResult = ns.formulas.hacking.weakenTime(server, player);
const testResult = roundTo5Decimals(ezgame.formulas.hacking.weakenTime(server, player));
const actualResult = roundTo5Decimals(ns.formulas.hacking.weakenTime(server, player));
if (testResult !== actualResult) {
throw new Error(`expected ${actualResult}, got ${testResult}`);
}

View file

@ -1,11 +1,9 @@
import { NS } from "@ns";
import { NS, Server } from "@ns";
import { ezgame } from "./ezgame";
import { scan } from "./utils/scan";
import { getNormalServer } from "./utils/get-normal-server";
export const main = (ns: NS) => {
const server = ns.getServer("n00dles");
const player = ns.getPlayer();
const testResult = ezgame.formulas.hacking.growTime(server, player);
const actualResult = ns.formulas.hacking.growTime(server, player);
console.log(testResult);
console.log(actualResult);
// console.log(ns.formulas.hacking.growTime(getNormalServer(ns, "n00dles"), ns.getPlayer()));
console.log(ns.getServer("n00dles"));
};

View file

@ -11,8 +11,15 @@ interface ServerAnalysis {
export const analyze = (ns: NS, hostnames: string[]) => {
hostnames.forEach((hostname) => {
// skip darknet servers
if (ns.dnet.isDarknetServer(hostname)) {
ns.tprint(`Skipping darknet server: ${hostname}`);
return;
}
// get the server object for the hostname
const server: Server = ns.getServer(hostname);
const server = ns.getServer(hostname) as Server;
// create a new object that matches the ServerAnalysis interface
const analysis: ServerAnalysis = {
hostname: server.hostname,
@ -21,6 +28,8 @@ export const analyze = (ns: NS, hostnames: string[]) => {
portsRequiredForNuke: server.numOpenPortsRequired ?? 0,
maxRam: server.maxRam,
};
ns.tprint(analysis);
});
};

View file

@ -0,0 +1,9 @@
import { NS, Server } from "@ns";
export function getNormalServer(ns: NS, hostname: string): Server {
if (ns.dnet.isDarknetServer(hostname)) {
throw new Error(`Server ${hostname} is a darknet server`);
}
return ns.getServer(hostname) as Server;
}

View file

@ -1,29 +1,23 @@
import { NS } from '@ns';
import { NS } from "@ns";
export const serverBuyMax = (ns: NS, serverNamePrefix: string) => {
// get the maximum number of servers that can be purchased
const maxServers = ns.getPurchasedServerLimit();
const maxServers = ns.cloud.getServerLimit();
// get the number of servers currently owned
const currentServers = ns.getPurchasedServers().length;
const currentServers = ns.cloud.getServerNames().length;
// calculate the number of servers that can still be purchased
const serversToPurchase = maxServers - currentServers;
// if we can't buy any more servers, return
if (serversToPurchase <= 0) {
ns.tprint('Cannot purchase any more servers. Maximum limit reached.');
ns.tprint("Cannot purchase any more servers. Maximum limit reached.");
return;
}
// get current money available
const moneyAvailable = ns.getServerMoneyAvailable('home');
// smallest ram we can buy is 2gb, check if can even afford that
if (moneyAvailable < ns.getPurchasedServerCost(2)) {
ns.tprint('Nigga you broke, not enough money to buy the smallest server');
return;
}
const moneyAvailable = ns.getServerMoneyAvailable("home");
// find the maximum ram we can afford spread out over the number of servers we can buy
// the ram amount that can be bought is in power of 2
@ -35,7 +29,7 @@ export const serverBuyMax = (ns: NS, serverNamePrefix: string) => {
// calculate the ram based on power
const ram = Math.pow(2, pow);
// get the cost of the server with the ram
const totalCost = ns.getPurchasedServerCost(ram) * serversToPurchase;
const totalCost = ns.cloud.getServerCost(ram) * serversToPurchase;
// check if can buy
if (totalCost <= moneyAvailable) {
@ -47,13 +41,19 @@ export const serverBuyMax = (ns: NS, serverNamePrefix: string) => {
}
}
// check if we found a valid target ram amount
if (targetRam < 2) {
ns.tprint("Unable to find affordable server configuration. Try buying fewer servers.");
return;
}
// now buy the servers with the target ram
let serversPurchased = 0;
while (serversPurchased < serversToPurchase) {
const serverName = `${serverNamePrefix}-${currentServers + serversPurchased + 1}`;
if (!ns.serverExists(serverName)) {
ns.purchaseServer(serverName, targetRam);
ns.cloud.purchaseServer(serverName, targetRam);
serversPurchased++;
}
}
@ -63,6 +63,6 @@ export const serverBuyMax = (ns: NS, serverNamePrefix: string) => {
};
export const main = (ns: NS) => {
const serverNamePrefix = 'worker';
const serverNamePrefix = "worker";
serverBuyMax(ns, serverNamePrefix);
};

View file

@ -1,9 +1,9 @@
import { NS } from '@ns';
import { kill } from '../kill';
import { NS } from "@ns";
import { kill } from "../kill";
export const serverDeleteAll = (ns: NS) => {
// get a list of all the purchased servers
const serverNames: string[] = ns.getPurchasedServers();
const serverNames: string[] = ns.cloud.getServerNames();
// initialize a counter for total cost of all the servers
let totalCost = 0;
@ -14,14 +14,14 @@ export const serverDeleteAll = (ns: NS) => {
const ram = ns.getServerMaxRam(serverName);
// calculate the cost of the server and add it to the total cost
const cost = ns.getPurchasedServerCost(ram);
const cost = ns.cloud.getServerCost(ram);
totalCost += cost;
// kill all the processes running on the server before removing it
kill(ns, serverName);
// remove the server
ns.deleteServer(serverName);
ns.cloud.deleteServer(serverName);
});
ns.tprint(`Purchased servers deleted: ${serverNames.length}`);

View file

@ -1,10 +1,25 @@
import { Server } from "@ns";
export const utils = {
utilityFormatDate,
utilityFormatSize,
utilityUnformatSize,
utilityExtractFilename,
clampNumber,
clampInteger,
isValidNumber,
randomNumber,
randomInteger,
isDarknetServer,
};
/**
* Format the date/time.
* If the date is today, show the time. Otherwise, show the date in "day month year" format.
* @param dateString The date string to format
* @returns Formatted date/time string
*/
export const utilityFormatDate = (dateString: string): string => {
function utilityFormatDate(dateString: string): string {
const date = new Date(dateString);
const today = new Date();
@ -22,14 +37,14 @@ export const utilityFormatDate = (dateString: string): string => {
// "day month year" format
return date.toLocaleDateString(undefined, { day: "numeric", month: "long", year: "numeric" });
}
};
}
/**
* Format bytes into human-readable size
* @param bytes Number of bytes to format
* @returns Formatted size string
*/
export const utilityFormatSize = (bytes: number): string => {
function utilityFormatSize(bytes: number): string {
if (bytes === 0) return "0 Bytes";
const k = 1024;
@ -38,19 +53,19 @@ export const utilityFormatSize = (bytes: number): string => {
// tf is pow
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
};
}
/**
* Convert a formatted size string back to bytes
* @param formattedSize Formatted size string (must be in the same format produced by `utilityFormatSize()`)
* @returns Number of bytes
*/
export const utilityUnformatSize = (formattedSize: string): number => {
function utilityUnformatSize(formattedSize: string): number {
const sizes = ["Bytes", "KB", "MB", "GB"];
const [value, unit] = formattedSize.split(" ");
const index = sizes.indexOf(unit);
return parseFloat(value) * Math.pow(1024, index);
};
}
/**
* Extract filename stem and extension from a file path
@ -58,7 +73,7 @@ export const utilityUnformatSize = (formattedSize: string): number => {
* @returns Object containing `fileStem` and `fileExtension`. `fileStem` is the filename without the extension, and `fileExtension` is the extension in lowercase (or an empty string if there is no extension).
* @throws Error if the file path is invalid
*/
export const utilityExtractFilename = (filePath: string): { fileStem: string; fileExtension: string } | null => {
function utilityExtractFilename(filePath: string): { fileStem: string; fileExtension: string } | null {
const lastSlashIndex = filePath.lastIndexOf("/");
const lastDotIndex = filePath.lastIndexOf(".");
@ -86,7 +101,7 @@ export const utilityExtractFilename = (filePath: string): { fileStem: string; fi
}
return { fileStem: fileStem, fileExtension: fileExtension };
};
}
/**
* Clamps a value to a lower and upper bound
@ -95,7 +110,7 @@ export const utilityExtractFilename = (filePath: string): { fileStem: string; fi
* @param max Upper bound, defaults to `Number.MAX_VALUE`
* @returns Clamped value
*/
export function clampNumber(value: number, min: number = -Number.MAX_VALUE, max: number = Number.MAX_VALUE): number {
function clampNumber(value: number, min: number = -Number.MAX_VALUE, max: number = Number.MAX_VALUE): number {
if (isNaN(value)) {
// if (CONSTANTS.isDevBranch) throw new Error("NaN passed into clampNumber()");
return min;
@ -110,7 +125,7 @@ export function clampNumber(value: number, min: number = -Number.MAX_VALUE, max:
* @param max Upper bound, defaults to `Number.MAX_SAFE_INTEGER`
* @returns Clamped integer value
*/
export function clampInteger(
function clampInteger(
value: number,
min: number = -Number.MAX_SAFE_INTEGER,
max: number = Number.MAX_SAFE_INTEGER,
@ -128,7 +143,7 @@ export function clampInteger(
* @param n The number to check
* @returns True if n is a valid number, false otherwise
*/
export function isValidNumber(n: number): boolean {
function isValidNumber(n: number): boolean {
return typeof n === "number" && !isNaN(n);
}
@ -138,7 +153,7 @@ export function isValidNumber(n: number): boolean {
* @param max Maximum value (inclusive)
* @returns Random number between min and max
*/
export function randomNumber(min: number, max: number): number {
function randomNumber(min: number, max: number): number {
if (min > max) throw new Error("min cannot be greater than max");
return Math.random() * (max - min) + min;
}
@ -149,6 +164,10 @@ export function randomNumber(min: number, max: number): number {
* @param max Maximum value (inclusive)
* @returns Random integer between min and max
*/
export function randomInteger(min: number, max: number): number {
function randomInteger(min: number, max: number): number {
return Math.floor(randomNumber(min, max + 1));
}
function isDarknetServer(server: Server): server is Server & { isStationary: boolean } {
return "isStationary" in server;
}