NETSCRIPT: Type correctness for getServer (#476)

This commit is contained in:
Snarling 2023-04-11 15:12:55 -04:00 committed by GitHub
parent 561b5cbf75
commit f761eed377
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 189 additions and 179 deletions

@ -88,7 +88,7 @@
| [ReputationFormulas](./bitburner.reputationformulas.md) | Reputation formulas | | [ReputationFormulas](./bitburner.reputationformulas.md) | Reputation formulas |
| [RunningScript](./bitburner.runningscript.md) | | | [RunningScript](./bitburner.runningscript.md) | |
| [RunOptions](./bitburner.runoptions.md) | | | [RunOptions](./bitburner.runoptions.md) | |
| [Server](./bitburner.server.md) | A single server. | | [Server](./bitburner.server.md) | A server. Not all servers have all of these properties - optional properties are missing on certain servers. |
| [Singularity](./bitburner.singularity.md) | Singularity API | | [Singularity](./bitburner.singularity.md) | Singularity API |
| [Skills](./bitburner.skills.md) | | | [Skills](./bitburner.skills.md) | |
| [SkillsFormulas](./bitburner.skillsformulas.md) | Skills formulas | | [SkillsFormulas](./bitburner.skillsformulas.md) | Skills formulas |

@ -9,5 +9,5 @@ Flag indicating whether this server has a backdoor installed by a player
**Signature:** **Signature:**
```typescript ```typescript
backdoorInstalled: boolean; backdoorInstalled?: boolean;
``` ```

@ -4,10 +4,10 @@
## Server.baseDifficulty property ## Server.baseDifficulty property
Initial server security level (i.e. security level when the server was created) Server's initial server security level at creation.
**Signature:** **Signature:**
```typescript ```typescript
baseDifficulty: number; baseDifficulty?: number;
``` ```

@ -4,7 +4,7 @@
## Server.cpuCores property ## Server.cpuCores property
How many CPU cores this server has. Maximum of 8. Affects magnitude of grow and weaken. How many CPU cores this server has. Affects magnitude of grow and weaken ran from this server.
**Signature:** **Signature:**

@ -4,7 +4,7 @@
## Server.ftpPortOpen property ## Server.ftpPortOpen property
Flag indicating whether the FTP port is open Whether or not the FTP port is open
**Signature:** **Signature:**

@ -9,5 +9,5 @@ Server Security Level
**Signature:** **Signature:**
```typescript ```typescript
hackDifficulty: number; hackDifficulty?: number;
``` ```

@ -4,7 +4,7 @@
## Server.httpPortOpen property ## Server.httpPortOpen property
Flag indicating whether HTTP Port is open Whether or not the HTTP Port is open
**Signature:** **Signature:**

@ -4,40 +4,40 @@
## Server interface ## Server interface
A single server. A server. Not all servers have all of these properties - optional properties are missing on certain servers.
**Signature:** **Signature:**
```typescript ```typescript
interface Server export interface Server
``` ```
## Properties ## Properties
| Property | Modifiers | Type | Description | | Property | Modifiers | Type | Description |
| --- | --- | --- | --- | | --- | --- | --- | --- |
| [backdoorInstalled](./bitburner.server.backdoorinstalled.md) | | boolean | Flag indicating whether this server has a backdoor installed by a player | | [backdoorInstalled?](./bitburner.server.backdoorinstalled.md) | | boolean | _(Optional)_ Flag indicating whether this server has a backdoor installed by a player |
| [baseDifficulty](./bitburner.server.basedifficulty.md) | | number | Initial server security level (i.e. security level when the server was created) | | [baseDifficulty?](./bitburner.server.basedifficulty.md) | | number | _(Optional)_ Server's initial server security level at creation. |
| [cpuCores](./bitburner.server.cpucores.md) | | number | How many CPU cores this server has. Maximum of 8. Affects magnitude of grow and weaken. | | [cpuCores](./bitburner.server.cpucores.md) | | number | How many CPU cores this server has. Affects magnitude of grow and weaken ran from this server. |
| [ftpPortOpen](./bitburner.server.ftpportopen.md) | | boolean | Flag indicating whether the FTP port is open | | [ftpPortOpen](./bitburner.server.ftpportopen.md) | | boolean | Whether or not the FTP port is open |
| [hackDifficulty](./bitburner.server.hackdifficulty.md) | | number | Server Security Level | | [hackDifficulty?](./bitburner.server.hackdifficulty.md) | | number | _(Optional)_ Server Security Level |
| [hasAdminRights](./bitburner.server.hasadminrights.md) | | boolean | Flag indicating whether player has admin/root access to this server | | [hasAdminRights](./bitburner.server.hasadminrights.md) | | boolean | Flag indicating whether player has admin/root access to this server |
| [hostname](./bitburner.server.hostname.md) | | string | Hostname. Must be unique | | [hostname](./bitburner.server.hostname.md) | | string | Hostname. Must be unique |
| [httpPortOpen](./bitburner.server.httpportopen.md) | | boolean | Flag indicating whether HTTP Port is open | | [httpPortOpen](./bitburner.server.httpportopen.md) | | boolean | Whether or not the HTTP Port is open |
| [ip](./bitburner.server.ip.md) | | string | IP Address. Must be unique | | [ip](./bitburner.server.ip.md) | | string | IP Address. Must be unique |
| [isConnectedTo](./bitburner.server.isconnectedto.md) | | boolean | Flag indicating whether player is currently connected to this server | | [isConnectedTo](./bitburner.server.isconnectedto.md) | | boolean | Flag indicating whether player is currently connected to this server |
| [maxRam](./bitburner.server.maxram.md) | | number | RAM (GB) available on this server | | [maxRam](./bitburner.server.maxram.md) | | number | RAM (GB) available on this server |
| [minDifficulty](./bitburner.server.mindifficulty.md) | | number | Minimum server security level that this server can be weakened to | | [minDifficulty?](./bitburner.server.mindifficulty.md) | | number | _(Optional)_ Minimum server security level that this server can be weakened to |
| [moneyAvailable](./bitburner.server.moneyavailable.md) | | number | How much money currently resides on the server and can be hacked | | [moneyAvailable?](./bitburner.server.moneyavailable.md) | | number | _(Optional)_ How much money currently resides on the server and can be hacked |
| [moneyMax](./bitburner.server.moneymax.md) | | number | Maximum amount of money that this server can hold | | [moneyMax?](./bitburner.server.moneymax.md) | | number | _(Optional)_ Maximum amount of money that this server can hold |
| [numOpenPortsRequired](./bitburner.server.numopenportsrequired.md) | | number | Number of open ports required in order to gain admin/root access | | [numOpenPortsRequired?](./bitburner.server.numopenportsrequired.md) | | number | _(Optional)_ Number of open ports required in order to gain admin/root access |
| [openPortCount](./bitburner.server.openportcount.md) | | number | How many ports are currently opened on the server | | [openPortCount?](./bitburner.server.openportcount.md) | | number | _(Optional)_ How many ports are currently opened on the server |
| [organizationName](./bitburner.server.organizationname.md) | | string | Name of company/faction/etc. that this server belongs to. Optional, not applicable to all Servers | | [organizationName](./bitburner.server.organizationname.md) | | string | Name of company/faction/etc. that this server belongs to, not applicable to all Servers |
| [purchasedByPlayer](./bitburner.server.purchasedbyplayer.md) | | boolean | Flag indicating whether this is a purchased server | | [purchasedByPlayer](./bitburner.server.purchasedbyplayer.md) | | boolean | Flag indicating whether this is a purchased server |
| [ramUsed](./bitburner.server.ramused.md) | | number | RAM (GB) used. i.e. unavailable RAM | | [ramUsed](./bitburner.server.ramused.md) | | number | RAM (GB) used. i.e. unavailable RAM |
| [requiredHackingSkill](./bitburner.server.requiredhackingskill.md) | | number | Hacking level required to hack this server | | [requiredHackingSkill?](./bitburner.server.requiredhackingskill.md) | | number | _(Optional)_ Hacking level required to hack this server |
| [serverGrowth](./bitburner.server.servergrowth.md) | | number | Parameter that affects how effectively this server's money can be increased using the grow() Netscript function | | [serverGrowth?](./bitburner.server.servergrowth.md) | | number | _(Optional)_ Growth effectiveness statistic. Higher values produce more growth with ns.grow() |
| [smtpPortOpen](./bitburner.server.smtpportopen.md) | | boolean | Flag indicating whether SMTP Port is open | | [smtpPortOpen](./bitburner.server.smtpportopen.md) | | boolean | Whether or not the SMTP Port is open |
| [sqlPortOpen](./bitburner.server.sqlportopen.md) | | boolean | Flag indicating whether SQL Port is open | | [sqlPortOpen](./bitburner.server.sqlportopen.md) | | boolean | Whether or not the SQL Port is open |
| [sshPortOpen](./bitburner.server.sshportopen.md) | | boolean | Flag indicating whether the SSH Port is open | | [sshPortOpen](./bitburner.server.sshportopen.md) | | boolean | Whether or not the SSH Port is open |

@ -9,5 +9,5 @@ Minimum server security level that this server can be weakened to
**Signature:** **Signature:**
```typescript ```typescript
minDifficulty: number; minDifficulty?: number;
``` ```

@ -9,5 +9,5 @@ How much money currently resides on the server and can be hacked
**Signature:** **Signature:**
```typescript ```typescript
moneyAvailable: number; moneyAvailable?: number;
``` ```

@ -9,5 +9,5 @@ Maximum amount of money that this server can hold
**Signature:** **Signature:**
```typescript ```typescript
moneyMax: number; moneyMax?: number;
``` ```

@ -9,5 +9,5 @@ Number of open ports required in order to gain admin/root access
**Signature:** **Signature:**
```typescript ```typescript
numOpenPortsRequired: number; numOpenPortsRequired?: number;
``` ```

@ -9,5 +9,5 @@ How many ports are currently opened on the server
**Signature:** **Signature:**
```typescript ```typescript
openPortCount: number; openPortCount?: number;
``` ```

@ -4,7 +4,7 @@
## Server.organizationName property ## Server.organizationName property
Name of company/faction/etc. that this server belongs to. Optional, not applicable to all Servers Name of company/faction/etc. that this server belongs to, not applicable to all Servers
**Signature:** **Signature:**

@ -9,5 +9,5 @@ Hacking level required to hack this server
**Signature:** **Signature:**
```typescript ```typescript
requiredHackingSkill: number; requiredHackingSkill?: number;
``` ```

@ -4,10 +4,10 @@
## Server.serverGrowth property ## Server.serverGrowth property
Parameter that affects how effectively this server's money can be increased using the grow() Netscript function Growth effectiveness statistic. Higher values produce more growth with ns.grow()
**Signature:** **Signature:**
```typescript ```typescript
serverGrowth: number; serverGrowth?: number;
``` ```

@ -4,7 +4,7 @@
## Server.smtpPortOpen property ## Server.smtpPortOpen property
Flag indicating whether SMTP Port is open Whether or not the SMTP Port is open
**Signature:** **Signature:**

@ -4,7 +4,7 @@
## Server.sqlPortOpen property ## Server.sqlPortOpen property
Flag indicating whether SQL Port is open Whether or not the SQL Port is open
**Signature:** **Signature:**

@ -4,7 +4,7 @@
## Server.sshPortOpen property ## Server.sshPortOpen property
Flag indicating whether the SSH Port is open Whether or not the SSH Port is open
**Signature:** **Signature:**

@ -1,42 +1,37 @@
import { BitNodeMultipliers } from "./BitNode/BitNodeMultipliers"; import { BitNodeMultipliers } from "./BitNode/BitNodeMultipliers";
import { Person as IPerson } from "@nsdefs"; import { Person as IPerson } from "@nsdefs";
import { calculateIntelligenceBonus } from "./PersonObjects/formulas/intelligence"; import { calculateIntelligenceBonus } from "./PersonObjects/formulas/intelligence";
import { Server } from "./Server/Server"; import { Server as IServer } from "@nsdefs";
/** Returns the chance the person has to successfully hack a server */ /** Returns the chance the person has to successfully hack a server */
export function calculateHackingChance(server: Server, person: IPerson): number { export function calculateHackingChance(server: IServer, person: IPerson): number {
const hackDifficulty = server.hackDifficulty ?? 100;
const requiredHackingSkill = server.requiredHackingSkill ?? 1e9;
// Unrooted or unhackable server
if (!server.hasAdminRights || hackDifficulty >= 100) return 0;
const hackFactor = 1.75; const hackFactor = 1.75;
const difficultyMult = (100 - server.hackDifficulty) / 100; const difficultyMult = (100 - hackDifficulty) / 100;
const skillMult = hackFactor * person.skills.hacking; const skillMult = hackFactor * person.skills.hacking;
const skillChance = (skillMult - server.requiredHackingSkill) / skillMult; const skillChance = (skillMult - requiredHackingSkill) / skillMult;
const chance = const chance =
skillChance * skillChance *
difficultyMult * difficultyMult *
person.mults.hacking_chance * person.mults.hacking_chance *
calculateIntelligenceBonus(person.skills.intelligence, 1); calculateIntelligenceBonus(person.skills.intelligence, 1);
if (chance > 1) { return Math.min(1, Math.max(chance, 0));
return 1;
}
if (chance < 0) {
return 0;
}
return chance;
} }
/** /**
* Returns the amount of hacking experience the person will gain upon * Returns the amount of hacking experience the person will gain upon
* successfully hacking a server * successfully hacking a server
*/ */
export function calculateHackingExpGain(server: Server, person: IPerson): number { export function calculateHackingExpGain(server: IServer, person: IPerson): number {
const baseDifficulty = server.baseDifficulty;
if (!baseDifficulty) return 0;
const baseExpGain = 3; const baseExpGain = 3;
const diffFactor = 0.3; const diffFactor = 0.3;
if (server.baseDifficulty == null) {
server.baseDifficulty = server.hackDifficulty;
}
let expGain = baseExpGain; let expGain = baseExpGain;
expGain += server.baseDifficulty * diffFactor; expGain += baseDifficulty * diffFactor;
return expGain * person.mults.hacking_exp * BitNodeMultipliers.HackExpGain; return expGain * person.mults.hacking_exp * BitNodeMultipliers.HackExpGain;
} }
@ -44,27 +39,27 @@ export function calculateHackingExpGain(server: Server, person: IPerson): number
* Returns the percentage of money that will be stolen from a server if * Returns the percentage of money that will be stolen from a server if
* it is successfully hacked (returns the decimal form, not the actual percent value) * it is successfully hacked (returns the decimal form, not the actual percent value)
*/ */
export function calculatePercentMoneyHacked(server: Server, person: IPerson): number { export function calculatePercentMoneyHacked(server: IServer, person: IPerson): number {
const hackDifficulty = server.hackDifficulty ?? 100;
if (hackDifficulty >= 100) return 0;
const requiredHackingSkill = server.requiredHackingSkill ?? 1e9;
// Adjust if needed for balancing. This is the divisor for the final calculation // Adjust if needed for balancing. This is the divisor for the final calculation
const balanceFactor = 240; const balanceFactor = 240;
const difficultyMult = (100 - server.hackDifficulty) / 100; const difficultyMult = (100 - hackDifficulty) / 100;
const skillMult = (person.skills.hacking - (server.requiredHackingSkill - 1)) / person.skills.hacking; const skillMult = (person.skills.hacking - (requiredHackingSkill - 1)) / person.skills.hacking;
const percentMoneyHacked = const percentMoneyHacked =
(difficultyMult * skillMult * person.mults.hacking_money * BitNodeMultipliers.ScriptHackMoney) / balanceFactor; (difficultyMult * skillMult * person.mults.hacking_money * BitNodeMultipliers.ScriptHackMoney) / balanceFactor;
if (percentMoneyHacked < 0) {
return 0;
}
if (percentMoneyHacked > 1) {
return 1;
}
return percentMoneyHacked; 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 seconds */
export function calculateHackingTime(server: Server, person: IPerson): number { export function calculateHackingTime(server: IServer, person: IPerson): number {
const difficultyMult = server.requiredHackingSkill * server.hackDifficulty; const hackDifficulty = server.hackDifficulty;
const requiredHackingSkill = server.requiredHackingSkill;
if (!hackDifficulty || !requiredHackingSkill) return Infinity;
const difficultyMult = requiredHackingSkill * hackDifficulty;
const baseDiff = 500; const baseDiff = 500;
const baseSkill = 50; const baseSkill = 50;
@ -82,14 +77,14 @@ export function calculateHackingTime(server: Server, person: IPerson): number {
} }
/** 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 seconds */
export function calculateGrowTime(server: Server, person: IPerson): number { export function calculateGrowTime(server: IServer, person: IPerson): number {
const growTimeMultiplier = 3.2; // Relative to hacking time. 16/5 = 3.2 const growTimeMultiplier = 3.2; // Relative to hacking time. 16/5 = 3.2
return growTimeMultiplier * calculateHackingTime(server, person); 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 seconds */
export function calculateWeakenTime(server: Server, person: IPerson): number { export function calculateWeakenTime(server: IServer, person: IPerson): number {
const weakenTimeMultiplier = 4; // Relative to hacking time const weakenTimeMultiplier = 4; // Relative to hacking time
return weakenTimeMultiplier * calculateHackingTime(server, person); return weakenTimeMultiplier * calculateHackingTime(server, person);

@ -6,7 +6,7 @@ import { ScriptDeath } from "./ScriptDeath";
import { formatExp, formatMoney, formatRam, formatThreads } from "../ui/formatNumber"; import { formatExp, formatMoney, formatRam, formatThreads } from "../ui/formatNumber";
import { ScriptArg } from "./ScriptArg"; import { ScriptArg } from "./ScriptArg";
import { CityName } from "../Enums"; import { CityName } from "../Enums";
import { BasicHGWOptions, RunningScript as IRunningScript, Person as IPerson } from "@nsdefs"; import { BasicHGWOptions, RunningScript as IRunningScript, Person as IPerson, Server as IServer } from "@nsdefs";
import { Server } from "../Server/Server"; import { Server } from "../Server/Server";
import { import {
calculateHackingChance, calculateHackingChance,
@ -597,36 +597,26 @@ function person(ctx: NetscriptContext, p: unknown): IPerson {
return p as IPerson; return p as IPerson;
} }
function server(ctx: NetscriptContext, s: unknown): Server { function server(ctx: NetscriptContext, s: unknown): IServer {
const fakeServer = { const fakeServer = {
cpuCores: undefined,
ftpPortOpen: undefined,
hasAdminRights: undefined,
hostname: undefined, hostname: undefined,
httpPortOpen: undefined,
ip: undefined, ip: undefined,
sshPortOpen: undefined,
ftpPortOpen: undefined,
smtpPortOpen: undefined,
httpPortOpen: undefined,
sqlPortOpen: undefined,
hasAdminRights: undefined,
cpuCores: undefined,
isConnectedTo: undefined, isConnectedTo: undefined,
ramUsed: undefined,
maxRam: undefined, maxRam: undefined,
organizationName: undefined, organizationName: undefined,
ramUsed: undefined,
smtpPortOpen: undefined,
sqlPortOpen: undefined,
sshPortOpen: undefined,
purchasedByPlayer: undefined, purchasedByPlayer: undefined,
backdoorInstalled: undefined,
baseDifficulty: undefined,
hackDifficulty: undefined,
minDifficulty: undefined,
moneyAvailable: undefined,
moneyMax: undefined,
numOpenPortsRequired: undefined,
openPortCount: undefined,
requiredHackingSkill: undefined,
serverGrowth: undefined,
}; };
const error = missingKey(fakeServer, s); const error = missingKey(fakeServer, s);
if (error) throw makeRuntimeErrorMsg(ctx, `server should be a hackable Server.\n${error}`, "TYPE"); if (error) throw makeRuntimeErrorMsg(ctx, `server should be a Server.\n${error}`, "TYPE");
return s as Server; return s as IServer;
} }
function missingKey(expect: object, actual: unknown): string | false { function missingKey(expect: object, actual: unknown): string | false {

@ -985,31 +985,56 @@ export const ns: InternalAPI<NSFull> = {
return Object.assign({}, getBitNodeMultipliers(n, lvl)); return Object.assign({}, getBitNodeMultipliers(n, lvl));
}, },
getServer: getServer: (ctx) => (_hostname) => {
(ctx) => const hostname = helpers.string(ctx, "hostname", _hostname ?? ctx.workerScript.hostname);
(_hostname = ctx.workerScript.hostname) => { const server = helpers.getServer(ctx, hostname);
const hostname = helpers.string(ctx, "hostname", _hostname); return {
const server = helpers.getServer(ctx, hostname); hostname: server.hostname,
const copy = Object.assign({}, server) as Server; ip: server.ip,
// These fields should be hidden. sshPortOpen: server.sshPortOpen,
copy.contracts = []; ftpPortOpen: server.ftpPortOpen,
copy.messages = []; smtpPortOpen: server.smtpPortOpen,
copy.runningScripts = []; httpPortOpen: server.httpPortOpen,
copy.scripts = []; sqlPortOpen: server.sqlPortOpen,
copy.textFiles = []; hasAdminRights: server.hasAdminRights,
copy.programs = []; cpuCores: server.cpuCores,
copy.serversOnNetwork = []; isConnectedTo: server.isConnectedTo,
if (!copy.baseDifficulty) copy.baseDifficulty = 0; ramUsed: server.ramUsed,
if (!copy.hackDifficulty) copy.hackDifficulty = 0; maxRam: server.maxRam,
if (!copy.minDifficulty) copy.minDifficulty = 0; organizationName: server.organizationName,
if (!copy.moneyAvailable) copy.moneyAvailable = 0; purchasedByPlayer: server.purchasedByPlayer,
if (!copy.moneyMax) copy.moneyMax = 0; backdoorInstalled: server.backdoorInstalled,
if (!copy.numOpenPortsRequired) copy.numOpenPortsRequired = 0; baseDifficulty: server.baseDifficulty,
if (!copy.openPortCount) copy.openPortCount = 0; hackDifficulty: server.hackDifficulty,
if (!copy.requiredHackingSkill) copy.requiredHackingSkill = 0; minDifficulty: server.minDifficulty,
if (!copy.serverGrowth) copy.serverGrowth = 0; moneyAvailable: server.moneyAvailable,
return copy; moneyMax: server.moneyMax,
}, numOpenPortsRequired: server.numOpenPortsRequired,
openPortCount: server.openPortCount,
requiredHackingSkill: server.requiredHackingSkill,
serverGrowth: server.serverGrowth,
};
const copy = Object.assign({}, server) as Server;
// These fields should be hidden.
copy.contracts = [];
copy.messages = [];
copy.runningScripts = [];
copy.scripts = [];
copy.textFiles = [];
copy.programs = [];
copy.serversOnNetwork = [];
if (!copy.baseDifficulty) copy.baseDifficulty = 0;
if (!copy.hackDifficulty) copy.hackDifficulty = 0;
if (!copy.minDifficulty) copy.minDifficulty = 0;
if (!copy.moneyAvailable) copy.moneyAvailable = 0;
if (!copy.moneyMax) copy.moneyMax = 0;
if (!copy.numOpenPortsRequired) copy.numOpenPortsRequired = 0;
if (!copy.openPortCount) copy.openPortCount = 0;
if (!copy.requiredHackingSkill) copy.requiredHackingSkill = 0;
if (!copy.serverGrowth) copy.serverGrowth = 0;
return copy;
},
getServerMoneyAvailable: (ctx) => (_hostname) => { getServerMoneyAvailable: (ctx) => (_hostname) => {
const hostname = helpers.string(ctx, "hostname", _hostname); const hostname = helpers.string(ctx, "hostname", _hostname);
const server = helpers.getServer(ctx, hostname); const server = helpers.getServer(ctx, hostname);

@ -454,93 +454,75 @@ interface HacknetServerConstants {
} }
/** /**
* A single server. * A server. Not all servers have all of these properties - optional properties are missing on certain servers.
* @public * @public
*/ */
interface Server { export interface Server {
/** /** Hostname. Must be unique */
* How many CPU cores this server has. Maximum of 8. hostname: string;
* Affects magnitude of grow and weaken. /** IP Address. Must be unique */
*/ ip: string;
cpuCores: number;
/** Flag indicating whether the FTP port is open */ /** Whether or not the SSH Port is open */
sshPortOpen: boolean;
/** Whether or not the FTP port is open */
ftpPortOpen: boolean; ftpPortOpen: boolean;
/** Whether or not the SMTP Port is open */
smtpPortOpen: boolean;
/** Whether or not the HTTP Port is open */
httpPortOpen: boolean;
/** Whether or not the SQL Port is open */
sqlPortOpen: boolean;
/** Flag indicating whether player has admin/root access to this server */ /** Flag indicating whether player has admin/root access to this server */
hasAdminRights: boolean; hasAdminRights: boolean;
/** Hostname. Must be unique */ /** How many CPU cores this server has. Affects magnitude of grow and weaken ran from this server. */
hostname: string; cpuCores: number;
/** Flag indicating whether HTTP Port is open */
httpPortOpen: boolean;
/** IP Address. Must be unique */
ip: string;
/** Flag indicating whether player is currently connected to this server */ /** Flag indicating whether player is currently connected to this server */
isConnectedTo: boolean; isConnectedTo: boolean;
/** RAM (GB) used. i.e. unavailable RAM */
ramUsed: number;
/** RAM (GB) available on this server */ /** RAM (GB) available on this server */
maxRam: number; maxRam: number;
/** /** Name of company/faction/etc. that this server belongs to, not applicable to all Servers */
* Name of company/faction/etc. that this server belongs to.
* Optional, not applicable to all Servers
*/
organizationName: string; organizationName: string;
/** RAM (GB) used. i.e. unavailable RAM */
ramUsed: number;
/** Flag indicating whether SMTP Port is open */
smtpPortOpen: boolean;
/** Flag indicating whether SQL Port is open */
sqlPortOpen: boolean;
/** Flag indicating whether the SSH Port is open */
sshPortOpen: boolean;
/** Flag indicating whether this is a purchased server */ /** Flag indicating whether this is a purchased server */
purchasedByPlayer: boolean; purchasedByPlayer: boolean;
/** Flag indicating whether this server has a backdoor installed by a player */ /** Flag indicating whether this server has a backdoor installed by a player */
backdoorInstalled: boolean; backdoorInstalled?: boolean;
/** /** Server's initial server security level at creation. */
* Initial server security level baseDifficulty?: number;
* (i.e. security level when the server was created)
*/
baseDifficulty: number;
/** Server Security Level */ /** Server Security Level */
hackDifficulty: number; hackDifficulty?: number;
/** Minimum server security level that this server can be weakened to */ /** Minimum server security level that this server can be weakened to */
minDifficulty: number; minDifficulty?: number;
/** How much money currently resides on the server and can be hacked */ /** How much money currently resides on the server and can be hacked */
moneyAvailable: number; moneyAvailable?: number;
/** Maximum amount of money that this server can hold */ /** Maximum amount of money that this server can hold */
moneyMax: number; moneyMax?: number;
/** Number of open ports required in order to gain admin/root access */ /** Number of open ports required in order to gain admin/root access */
numOpenPortsRequired: number; numOpenPortsRequired?: number;
/** How many ports are currently opened on the server */ /** How many ports are currently opened on the server */
openPortCount: number; openPortCount?: number;
/** Hacking level required to hack this server */ /** Hacking level required to hack this server */
requiredHackingSkill: number; requiredHackingSkill?: number;
/** /** Growth effectiveness statistic. Higher values produce more growth with ns.grow() */
* Parameter that affects how effectively this server's money can serverGrowth?: number;
* be increased using the grow() Netscript function
*/
serverGrowth: number;
} }
/** /**

@ -1,3 +1,4 @@
import type { Server as IServer } from "@nsdefs";
import { CodingContract } from "../CodingContracts"; import { CodingContract } from "../CodingContracts";
import { RunningScript } from "../Script/RunningScript"; import { RunningScript } from "../Script/RunningScript";
import { Script } from "../Script/Script"; import { Script } from "../Script/Script";
@ -26,7 +27,7 @@ interface writeResult {
} }
/** Abstract Base Class for any Server object */ /** Abstract Base Class for any Server object */
export abstract class BaseServer { export abstract class BaseServer implements IServer {
// Coding Contract files on this server // Coding Contract files on this server
contracts: CodingContract[] = []; contracts: CodingContract[] = [];
@ -93,8 +94,17 @@ export abstract class BaseServer {
// Flag indicating whether this is a purchased server // Flag indicating whether this is a purchased server
purchasedByPlayer = false; purchasedByPlayer = false;
// Variables that exist only on some types of servers can just be optional. // Optional, listed just so they can be accessed on a BaseServer. These will be undefined for HacknetServers.
backdoorInstalled?: boolean; backdoorInstalled?: boolean;
baseDifficulty?: number;
hackDifficulty?: number;
minDifficulty?: number;
moneyAvailable?: number;
moneyMax?: number;
numOpenPortsRequired?: number;
openPortCount?: number;
requiredHackingSkill?: number;
serverGrowth?: number;
constructor(params: IConstructorParams = { hostname: "", ip: createRandomIp() }) { constructor(params: IConstructorParams = { hostname: "", ip: createRandomIp() }) {
this.ip = params.ip ? params.ip : createRandomIp(); this.ip = params.ip ? params.ip : createRandomIp();

@ -10,6 +10,7 @@ import { Programs } from "../Programs/Programs";
import { LiteratureNames } from "../Literature/data/LiteratureNames"; import { LiteratureNames } from "../Literature/data/LiteratureNames";
import { Person as IPerson } from "@nsdefs"; import { Person as IPerson } from "@nsdefs";
import { isValidNumber } from "../utils/helpers/isValidNumber"; import { isValidNumber } from "../utils/helpers/isValidNumber";
import { Server as IServer } from "@nsdefs";
/** /**
* Constructs a new server, while also ensuring that the new server * Constructs a new server, while also ensuring that the new server
@ -48,8 +49,10 @@ export function safelyCreateUniqueServer(params: IConstructorParams): Server {
* @param p - Reference to Player object * @param p - Reference to Player object
* @returns Number of "growth cycles" needed * @returns Number of "growth cycles" needed
*/ */
export function numCycleForGrowth(server: Server, growth: number, cores = 1): number { export function numCycleForGrowth(server: IServer, growth: number, cores = 1): number {
let ajdGrowthRate = 1 + (CONSTANTS.ServerBaseGrowthRate - 1) / server.hackDifficulty; if (!server.serverGrowth) return Infinity;
const hackDifficulty = server.hackDifficulty ?? 100;
let ajdGrowthRate = 1 + (CONSTANTS.ServerBaseGrowthRate - 1) / hackDifficulty;
if (ajdGrowthRate > CONSTANTS.ServerMaxGrowthRate) { if (ajdGrowthRate > CONSTANTS.ServerMaxGrowthRate) {
ajdGrowthRate = CONSTANTS.ServerMaxGrowthRate; ajdGrowthRate = CONSTANTS.ServerMaxGrowthRate;
} }
@ -79,18 +82,22 @@ export function numCycleForGrowth(server: Server, growth: number, cores = 1): nu
* @returns Integer threads needed by a single ns.grow call to reach targetMoney from startMoney. * @returns Integer threads needed by a single ns.grow call to reach targetMoney from startMoney.
*/ */
export function numCycleForGrowthCorrected( export function numCycleForGrowthCorrected(
server: Server, server: IServer,
targetMoney: number, targetMoney: number,
startMoney: number, startMoney: number,
cores = 1, cores = 1,
person: IPerson = Player, person: IPerson = Player,
): number { ): number {
if (!server.serverGrowth) return Infinity;
const moneyMax = server.moneyMax ?? 1;
const hackDifficulty = server.hackDifficulty ?? 100;
if (startMoney < 0) startMoney = 0; // servers "can't" have less than 0 dollars on them if (startMoney < 0) startMoney = 0; // servers "can't" have less than 0 dollars on them
if (targetMoney > server.moneyMax) targetMoney = server.moneyMax; // can't grow a server to more than its moneyMax if (targetMoney > moneyMax) targetMoney = moneyMax; // can't grow a server to more than its moneyMax
if (targetMoney <= startMoney) return 0; // no growth --> no threads if (targetMoney <= startMoney) return 0; // no growth --> no threads
// exponential base adjusted by security // exponential base adjusted by security
const adjGrowthRate = 1 + (CONSTANTS.ServerBaseGrowthRate - 1) / server.hackDifficulty; const adjGrowthRate = 1 + (CONSTANTS.ServerBaseGrowthRate - 1) / hackDifficulty;
const exponentialBase = Math.min(adjGrowthRate, CONSTANTS.ServerMaxGrowthRate); // cap growth rate const exponentialBase = Math.min(adjGrowthRate, CONSTANTS.ServerMaxGrowthRate); // cap growth rate
// total of all grow thread multipliers // total of all grow thread multipliers

@ -1,14 +1,15 @@
import { CONSTANTS } from "../../Constants"; import { CONSTANTS } from "../../Constants";
import { Server } from "../Server";
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers"; import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
import { Person as IPerson } from "@nsdefs"; import { Person as IPerson, Server as IServer } from "@nsdefs";
export function calculateServerGrowth(server: Server, threads: number, p: IPerson, cores = 1): number { export function calculateServerGrowth(server: IServer, threads: number, p: IPerson, cores = 1): number {
if (!server.serverGrowth) return 0;
const hackDifficulty = server.hackDifficulty ?? 100;
const numServerGrowthCycles = Math.max(Math.floor(threads), 0); const numServerGrowthCycles = Math.max(Math.floor(threads), 0);
//Get adjusted growth rate, which accounts for server security //Get adjusted growth rate, which accounts for server security
const growthRate = CONSTANTS.ServerBaseGrowthRate; const growthRate = CONSTANTS.ServerBaseGrowthRate;
let adjGrowthRate = 1 + (growthRate - 1) / server.hackDifficulty; let adjGrowthRate = 1 + (growthRate - 1) / hackDifficulty;
if (adjGrowthRate > CONSTANTS.ServerMaxGrowthRate) { if (adjGrowthRate > CONSTANTS.ServerMaxGrowthRate) {
adjGrowthRate = CONSTANTS.ServerMaxGrowthRate; adjGrowthRate = CONSTANTS.ServerMaxGrowthRate;
} }