mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2026-04-16 06:18:42 +02:00
BUG: Fix missed cases in offline server handling (#2495)
There were two large holes in the existing offline server handling: 1. It didn't include IPs, so scripts that used IPs instead of hostnames would get exceptions thrown for "server not found." 2. Coverage was very low for non-Darknet APIs. Maybe most of them don't need to be covered, but many obvious ones like "ps", "killall" and "hasRootAccess" were missing. IMO the only reliable answer is one that enforces *all* are covered via the type system. To accomplish the second part, helpers.getServer() was changed to return null when a server is offline. This intentionally breaks a lot of its utility, which was to return a server unconditionally. To compensate, its utility was increased - it now also does unknown argument processing, allowing it to subsume a common line that all callers were repeating. Some callers switched to ctx.workerScript.getServer(), because they didn't actually need to be using helpers.getServer(). Similarly, a few callsites switched to GetServerOrThrow(), for the cases where it should be guaranteed that the server is valid. The rest are returning a default/failure response when the server is offline. (Except for contracts, which threw on failure already anyway.)
This commit is contained in:
@@ -76,5 +76,5 @@ RAM cost: 2 GB
|
||||
|
||||
Generate a dummy contract on the current server with no reward. Used to test various algorithms.
|
||||
|
||||
This function will return null and not generate a contract if the randomized contract name is the same as another contract's name.
|
||||
This function will return null and not generate a contract if the randomized contract name is the same as another contract's name or the host is offline.
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ Runs BruteSSH.exe on a server.
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
brutessh(host: string): boolean;
|
||||
brutessh(host?: string): boolean;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@@ -42,7 +42,7 @@ string
|
||||
|
||||
</td><td>
|
||||
|
||||
Hostname/IP of the target server.
|
||||
_(Optional)_ Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
|
||||
|
||||
</td></tr>
|
||||
|
||||
@@ -9,7 +9,7 @@ Given a hostname, returns its IP address; or given an IP address, returns its ho
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
dnsLookup(host: string): string;
|
||||
dnsLookup(host?: string): string;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@@ -42,7 +42,7 @@ string
|
||||
|
||||
</td><td>
|
||||
|
||||
Hostname/IP of target server.
|
||||
_(Optional)_ Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
|
||||
|
||||
</td></tr>
|
||||
|
||||
@@ -58,7 +58,7 @@ string
|
||||
|
||||
</td><td>
|
||||
|
||||
Hostname/IP of the `target server` on which to execute the script.
|
||||
Hostname/IP of the target server on which to execute the script.
|
||||
|
||||
|
||||
</td></tr>
|
||||
|
||||
@@ -9,7 +9,7 @@ Runs FTPCrack.exe on a server.
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
ftpcrack(host: string): boolean;
|
||||
ftpcrack(host?: string): boolean;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@@ -42,7 +42,7 @@ string
|
||||
|
||||
</td><td>
|
||||
|
||||
Hostname/IP of the target server.
|
||||
_(Optional)_ Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
|
||||
|
||||
</td></tr>
|
||||
|
||||
@@ -9,7 +9,7 @@ Get the execution time of a grow() call.
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
getGrowTime(host: string): number;
|
||||
getGrowTime(host?: string): number;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@@ -42,7 +42,7 @@ string
|
||||
|
||||
</td><td>
|
||||
|
||||
Hostname/IP of target server.
|
||||
_(Optional)_ Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
|
||||
|
||||
</td></tr>
|
||||
|
||||
@@ -9,7 +9,7 @@ Get the execution time of a hack() call.
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
getHackTime(host: string): number;
|
||||
getHackTime(host?: string): number;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@@ -42,7 +42,7 @@ string
|
||||
|
||||
</td><td>
|
||||
|
||||
Hostname/IP of target server.
|
||||
_(Optional)_ Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
|
||||
|
||||
</td></tr>
|
||||
|
||||
@@ -9,7 +9,7 @@ Get the exp gain of a script.
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
getScriptExpGain(script: string, host: string, ...args: ScriptArg[]): number;
|
||||
getScriptExpGain(script: string, host?: string, ...args: ScriptArg[]): number;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@@ -58,7 +58,7 @@ string
|
||||
|
||||
</td><td>
|
||||
|
||||
Hostname/IP of the server on which script is running.
|
||||
_(Optional)_ Hostname/IP of the server on which the script is running. Optional. Defaults to current server if not provided.
|
||||
|
||||
|
||||
</td></tr>
|
||||
|
||||
@@ -9,7 +9,7 @@ Get the income of a script.
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
getScriptIncome(script: string, host: string, ...args: ScriptArg[]): number;
|
||||
getScriptIncome(script: string, host?: string, ...args: ScriptArg[]): number;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@@ -58,7 +58,7 @@ string
|
||||
|
||||
</td><td>
|
||||
|
||||
Hostname/IP of the server on which script is running.
|
||||
_(Optional)_ Hostname/IP of the server on which the script is running. Optional. Defaults to current server if not provided.
|
||||
|
||||
|
||||
</td></tr>
|
||||
|
||||
@@ -9,7 +9,7 @@ Get the base security level of a server.
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
getServerBaseSecurityLevel(host: string): number;
|
||||
getServerBaseSecurityLevel(host?: string): number;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@@ -42,7 +42,7 @@ string
|
||||
|
||||
</td><td>
|
||||
|
||||
Hostname/IP of target server.
|
||||
_(Optional)_ Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
|
||||
|
||||
</td></tr>
|
||||
|
||||
@@ -9,7 +9,7 @@ Get a server growth parameter.
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
getServerGrowth(host: string): number;
|
||||
getServerGrowth(host?: string): number;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@@ -42,7 +42,7 @@ string
|
||||
|
||||
</td><td>
|
||||
|
||||
Hostname/IP of target server.
|
||||
_(Optional)_ Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
|
||||
|
||||
</td></tr>
|
||||
|
||||
@@ -9,7 +9,7 @@ Get the maximum money available on a server.
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
getServerMaxMoney(host: string): number;
|
||||
getServerMaxMoney(host?: string): number;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@@ -42,7 +42,7 @@ string
|
||||
|
||||
</td><td>
|
||||
|
||||
Hostname/IP of target server.
|
||||
_(Optional)_ Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
|
||||
|
||||
</td></tr>
|
||||
|
||||
@@ -9,7 +9,7 @@ Get the maximum amount of RAM on a server.
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
getServerMaxRam(host: string): number;
|
||||
getServerMaxRam(host?: string): number;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@@ -42,7 +42,7 @@ string
|
||||
|
||||
</td><td>
|
||||
|
||||
Hostname/IP of the target server.
|
||||
_(Optional)_ Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
|
||||
|
||||
</td></tr>
|
||||
|
||||
@@ -9,7 +9,7 @@ Returns the minimum security level of the target server.
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
getServerMinSecurityLevel(host: string): number;
|
||||
getServerMinSecurityLevel(host?: string): number;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@@ -42,7 +42,7 @@ string
|
||||
|
||||
</td><td>
|
||||
|
||||
Hostname/IP of target server.
|
||||
_(Optional)_ Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
|
||||
|
||||
</td></tr>
|
||||
|
||||
@@ -9,7 +9,7 @@ Get money available on a server.
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
getServerMoneyAvailable(host: string): number;
|
||||
getServerMoneyAvailable(host?: string): number;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@@ -42,7 +42,7 @@ string
|
||||
|
||||
</td><td>
|
||||
|
||||
Hostname/IP of target server.
|
||||
_(Optional)_ Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
|
||||
|
||||
</td></tr>
|
||||
|
||||
@@ -9,7 +9,7 @@ Returns the number of open ports required to successfully run NUKE.exe on the sp
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
getServerNumPortsRequired(host: string): number;
|
||||
getServerNumPortsRequired(host?: string): number;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@@ -42,7 +42,7 @@ string
|
||||
|
||||
</td><td>
|
||||
|
||||
Hostname/IP of target server.
|
||||
_(Optional)_ Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
|
||||
|
||||
</td></tr>
|
||||
|
||||
@@ -9,7 +9,7 @@ Returns the required hacking level of the target server.
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
getServerRequiredHackingLevel(host: string): number;
|
||||
getServerRequiredHackingLevel(host?: string): number;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@@ -42,7 +42,7 @@ string
|
||||
|
||||
</td><td>
|
||||
|
||||
Hostname/IP of target server.
|
||||
_(Optional)_ Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
|
||||
|
||||
</td></tr>
|
||||
|
||||
@@ -9,7 +9,7 @@ Get server security level.
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
getServerSecurityLevel(host: string): number;
|
||||
getServerSecurityLevel(host?: string): number;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@@ -42,7 +42,7 @@ string
|
||||
|
||||
</td><td>
|
||||
|
||||
Hostname/IP of target server.
|
||||
_(Optional)_ Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
|
||||
|
||||
</td></tr>
|
||||
|
||||
@@ -9,7 +9,7 @@ Get the used RAM on a server.
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
getServerUsedRam(host: string): number;
|
||||
getServerUsedRam(host?: string): number;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@@ -42,7 +42,7 @@ string
|
||||
|
||||
</td><td>
|
||||
|
||||
Hostname/IP of the target server.
|
||||
_(Optional)_ Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
|
||||
|
||||
</td></tr>
|
||||
|
||||
@@ -9,7 +9,7 @@ Get the execution time of a weaken() call.
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
getWeakenTime(host: string): number;
|
||||
getWeakenTime(host?: string): number;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@@ -42,7 +42,7 @@ string
|
||||
|
||||
</td><td>
|
||||
|
||||
Hostname/IP of target server.
|
||||
_(Optional)_ Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
|
||||
|
||||
</td></tr>
|
||||
|
||||
@@ -9,7 +9,7 @@ Spoof money in a server's bank account, increasing the amount available.
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
grow(host: string, opts?: BasicHGWOptions): Promise<number>;
|
||||
grow(host?: string, opts?: BasicHGWOptions): Promise<number>;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@@ -42,7 +42,7 @@ string
|
||||
|
||||
</td><td>
|
||||
|
||||
Hostname/IP of the target server to grow.
|
||||
_(Optional)_ Hostname/IP of the target server to grow. Optional. Defaults to current server if not provided.
|
||||
|
||||
|
||||
</td></tr>
|
||||
|
||||
@@ -9,7 +9,7 @@ Steal a server's money.
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
hack(host: string, opts?: BasicHGWOptions): Promise<number>;
|
||||
hack(host?: string, opts?: BasicHGWOptions): Promise<number>;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@@ -42,7 +42,7 @@ string
|
||||
|
||||
</td><td>
|
||||
|
||||
Hostname/IP of the target server to hack.
|
||||
_(Optional)_ Hostname/IP of the target server to hack. Optional. Defaults to current server if not provided.
|
||||
|
||||
|
||||
</td></tr>
|
||||
|
||||
@@ -9,7 +9,7 @@ Get the chance of successfully hacking a server.
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
hackAnalyzeChance(host: string): number;
|
||||
hackAnalyzeChance(host?: string): number;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@@ -42,7 +42,7 @@ string
|
||||
|
||||
</td><td>
|
||||
|
||||
Hostname/IP of the target server.
|
||||
_(Optional)_ Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
|
||||
|
||||
</td></tr>
|
||||
|
||||
@@ -58,7 +58,7 @@ string
|
||||
|
||||
</td><td>
|
||||
|
||||
_(Optional)_ Hostname/IP of the target server. The number of threads is limited to the number needed to hack the server's maximum amount of money.
|
||||
_(Optional)_ Hostname/IP of the target server. Optional. If unspecified, the threads are not capped.
|
||||
|
||||
|
||||
</td></tr>
|
||||
@@ -74,5 +74,5 @@ The security increase.
|
||||
|
||||
RAM cost: 1 GB
|
||||
|
||||
Returns the security increase that would occur if a hack with this many threads happened.
|
||||
Returns the security increase that would occur if a hack with this many threads happened. The number of threads is limited to the number needed to hack the server's maximum amount of money.
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ string
|
||||
|
||||
</td><td>
|
||||
|
||||
Hostname of the target server to analyze.
|
||||
Hostname/IP of the target server to analyze.
|
||||
|
||||
|
||||
</td></tr>
|
||||
|
||||
@@ -9,7 +9,7 @@ Check if you have root access on a server.
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
hasRootAccess(host: string): boolean;
|
||||
hasRootAccess(host?: string): boolean;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@@ -42,7 +42,7 @@ string
|
||||
|
||||
</td><td>
|
||||
|
||||
Hostname/IP of the target server.
|
||||
_(Optional)_ Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
|
||||
|
||||
</td></tr>
|
||||
|
||||
@@ -9,7 +9,7 @@ Runs HTTPWorm.exe on a server.
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
httpworm(host: string): boolean;
|
||||
httpworm(host?: string): boolean;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@@ -42,7 +42,7 @@ string
|
||||
|
||||
</td><td>
|
||||
|
||||
Hostname/IP of the target server.
|
||||
_(Optional)_ Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
|
||||
|
||||
</td></tr>
|
||||
|
||||
@@ -42,7 +42,7 @@ string
|
||||
|
||||
</td><td>
|
||||
|
||||
_(Optional)_ Hostname/IP of the server on which to kill all scripts.
|
||||
_(Optional)_ Hostname/IP of the server on which to kill all scripts. Optional. Defaults to current server if not provided.
|
||||
|
||||
|
||||
</td></tr>
|
||||
|
||||
@@ -9,7 +9,7 @@ Runs NUKE.exe on a server.
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
nuke(host: string): boolean;
|
||||
nuke(host?: string): boolean;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@@ -42,7 +42,7 @@ string
|
||||
|
||||
</td><td>
|
||||
|
||||
Hostname/IP of the target server.
|
||||
_(Optional)_ Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
|
||||
|
||||
</td></tr>
|
||||
|
||||
@@ -9,7 +9,7 @@ Runs relaySMTP.exe on a server.
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
relaysmtp(host: string): boolean;
|
||||
relaysmtp(host?: string): boolean;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@@ -42,7 +42,7 @@ string
|
||||
|
||||
</td><td>
|
||||
|
||||
Hostname/IP of the target server.
|
||||
_(Optional)_ Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
|
||||
|
||||
</td></tr>
|
||||
|
||||
@@ -9,7 +9,7 @@ Kill all scripts with a filename.
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
scriptKill(script: string, host: string): boolean;
|
||||
scriptKill(script: string, host?: string): boolean;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@@ -58,7 +58,7 @@ string
|
||||
|
||||
</td><td>
|
||||
|
||||
Hostname/IP of target server.
|
||||
_(Optional)_ Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
|
||||
|
||||
</td></tr>
|
||||
|
||||
@@ -9,7 +9,7 @@ Check if any script with a filename is running.
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
scriptRunning(script: string, host: string): boolean;
|
||||
scriptRunning(script: string, host?: string): boolean;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@@ -58,7 +58,7 @@ string
|
||||
|
||||
</td><td>
|
||||
|
||||
Hostname/IP of target server.
|
||||
_(Optional)_ Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
|
||||
|
||||
</td></tr>
|
||||
|
||||
@@ -9,7 +9,7 @@ Returns a boolean denoting whether or not the specified server exists.
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
serverExists(host: string): boolean;
|
||||
serverExists(host?: string): boolean;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@@ -42,7 +42,7 @@ string
|
||||
|
||||
</td><td>
|
||||
|
||||
Hostname/IP of target server.
|
||||
_(Optional)_ Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
|
||||
|
||||
</td></tr>
|
||||
|
||||
@@ -9,7 +9,7 @@ Runs SQLInject.exe on a server.
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
sqlinject(host: string): boolean;
|
||||
sqlinject(host?: string): boolean;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@@ -42,7 +42,7 @@ string
|
||||
|
||||
</td><td>
|
||||
|
||||
Hostname/IP of the target server.
|
||||
_(Optional)_ Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
|
||||
|
||||
</td></tr>
|
||||
|
||||
@@ -9,7 +9,7 @@ Reduce a server's security level.
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
weaken(host: string, opts?: BasicHGWOptions): Promise<number>;
|
||||
weaken(host?: string, opts?: BasicHGWOptions): Promise<number>;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@@ -42,7 +42,7 @@ string
|
||||
|
||||
</td><td>
|
||||
|
||||
Hostname/IP of the target server to weaken.
|
||||
_(Optional)_ Hostname/IP of the target server to weaken. Optional. Defaults to current server if not provided.
|
||||
|
||||
|
||||
</td></tr>
|
||||
|
||||
@@ -178,7 +178,10 @@ export const deleteDarknetServer = (server: DarknetServer, force = false): void
|
||||
DarknetState.Network[server.depth][server.leftOffset] = null;
|
||||
}
|
||||
if (!isLabyrinth) {
|
||||
DarknetState.offlineServers.push(server.hostname);
|
||||
// Adding the ip first is an optimization to improve the random distribution
|
||||
// of reused hostnames slightly. See the comment in generateDarknetServerName.
|
||||
DarknetState.offlineServers.add(server.ip);
|
||||
DarknetState.offlineServers.add(server.hostname);
|
||||
}
|
||||
DeleteServer(server.hostname);
|
||||
const serverState = getServerState(server.hostname);
|
||||
@@ -192,9 +195,6 @@ export const addRandomDarknetServers = (count = 1, difficulty?: number, fixedDep
|
||||
const newServer = createDarknetServer(diff, -1, -1);
|
||||
const range = fixedDepth ? 0 : 3;
|
||||
moveDarknetServer(newServer, range, range);
|
||||
if (DarknetState.offlineServers.includes(newServer.hostname)) {
|
||||
DarknetState.offlineServers = DarknetState.offlineServers.filter((s) => s !== newServer.hostname);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ import { helpers } from "../../Netscript/NetscriptHelpers";
|
||||
import { errorMessage } from "../../Netscript/ErrorMessages";
|
||||
import type { BaseServer } from "../../Server/BaseServer";
|
||||
import { GetServer } from "../../Server/AllServers";
|
||||
import { DarknetState } from "../models/DarknetState";
|
||||
import { GenericResponseMessage, ResponseCodeEnum } from "../Enums";
|
||||
import { getBackdooredDarkwebServers } from "../utils/darknetNetworkUtils";
|
||||
import { hasDarknetAccess } from "../utils/darknetAuthUtils";
|
||||
@@ -19,6 +18,10 @@ type CheckDarknetServerOptions = {
|
||||
requireSession?: boolean;
|
||||
requireDirectConnection?: boolean;
|
||||
preventUseOnStationaryServers?: boolean;
|
||||
/**
|
||||
* If you use this option, the server property in the result object is only guaranteed to be a BaseServer, not a
|
||||
* DarknetServer as the result type shows.
|
||||
*/
|
||||
allowNonDarknet?: boolean;
|
||||
backdoorBypasses?: boolean;
|
||||
};
|
||||
@@ -36,27 +39,22 @@ export function expectDarknetAccess(ctx: NetscriptContext): void {
|
||||
|
||||
export function checkDarknetServer(
|
||||
ctx: NetscriptContext,
|
||||
host: string,
|
||||
_host: string,
|
||||
options: CheckDarknetServerOptions = {},
|
||||
):
|
||||
| { success: true; code: DarknetResponseCode; message: string; server: DarknetServer }
|
||||
| { success: false; code: DarknetResponseCode; message: string } {
|
||||
const currentServer = ctx.workerScript.getServer();
|
||||
const targetServer = GetServer(host);
|
||||
const [targetServer, host] = helpers.getServer(ctx, _host);
|
||||
if (!targetServer) {
|
||||
if (DarknetState.offlineServers.includes(host)) {
|
||||
// Because servers going offline is timing-sensitive, it is outside of
|
||||
// player's control. So we don't want to throw for "server does not exist" in this case,
|
||||
// despite throwing being the usual doctrine.
|
||||
logger(ctx)(`Server ${host} is offline.`);
|
||||
return {
|
||||
success: false,
|
||||
code: ResponseCodeEnum.ServiceUnavailable,
|
||||
message: GenericResponseMessage.ServiceUnavailable,
|
||||
};
|
||||
} else {
|
||||
throw errorMessage(ctx, `Server ${host} does not exist.`);
|
||||
}
|
||||
// Because servers going offline is timing-sensitive, it is outside of
|
||||
// player's control. So we don't want to throw for "server does not exist" in this case,
|
||||
// despite throwing being the usual doctrine.
|
||||
return {
|
||||
success: false,
|
||||
code: ResponseCodeEnum.ServiceUnavailable,
|
||||
message: GenericResponseMessage.ServiceUnavailable,
|
||||
};
|
||||
}
|
||||
const success = {
|
||||
success: true,
|
||||
@@ -67,19 +65,18 @@ export function checkDarknetServer(
|
||||
if (!(targetServer instanceof DarknetServer)) {
|
||||
if (options.allowNonDarknet) {
|
||||
// The return is off-shape here: server is of type DarknetServer, but
|
||||
// we've explicitly validated that it's only a BaseServer. Callers
|
||||
// using allowNonDarknet should call GetServer on their own for proper
|
||||
// type-safety, instead of using the server field.
|
||||
// we've explicitly validated that it's only a BaseServer. It's still OK
|
||||
// for callers to use this, as long as they are only expecting a BaseServer.
|
||||
return success;
|
||||
}
|
||||
const result = `${targetServer.hostname} is not a darknet server.`;
|
||||
const result = `${host} is not a darknet server.`;
|
||||
throw errorMessage(ctx, result);
|
||||
}
|
||||
// This is down here because we don't require darknet access for using
|
||||
// allowNonDarknet APIs on non-darknet servers.
|
||||
expectDarknetAccess(ctx);
|
||||
if (options.preventUseOnStationaryServers && targetServer.isStationary) {
|
||||
const result = `${targetServer.hostname} is not a valid target: it is a stationary server.`;
|
||||
const result = `${host} is not a valid target: it is a stationary server.`;
|
||||
throw errorMessage(ctx, result);
|
||||
}
|
||||
if (
|
||||
@@ -87,7 +84,7 @@ export function checkDarknetServer(
|
||||
!isDirectConnected(currentServer, targetServer) &&
|
||||
!(options.backdoorBypasses && targetServer.backdoorInstalled)
|
||||
) {
|
||||
let result = `${targetServer.hostname} is not connected to the current server ${currentServer.hostname}. It may have moved.`;
|
||||
let result = `${host} is not connected to the current server ${currentServer.hostname}. It may have moved.`;
|
||||
if (options.backdoorBypasses) {
|
||||
result += " You can also use a backdoor or stasis link on the target to allow remote access.";
|
||||
}
|
||||
@@ -103,7 +100,7 @@ export function checkDarknetServer(
|
||||
return success;
|
||||
}
|
||||
if (options.requireAdminRights && !targetServer.hasAdminRights) {
|
||||
const result = `${targetServer.hostname} requires root access. Use ns.dnet.authenticate() to gain access.`;
|
||||
const result = `${host} requires root access. Use ns.dnet.authenticate() to gain access.`;
|
||||
logger(ctx)(result);
|
||||
return {
|
||||
success: false,
|
||||
@@ -116,7 +113,7 @@ export function checkDarknetServer(
|
||||
host !== (!isIPAddress(host) ? currentServer.hostname : currentServer.ip) &&
|
||||
!isAuthenticated(targetServer, ctx.workerScript.pid)
|
||||
) {
|
||||
const result = `${targetServer.hostname} requires a session to do that. Use ns.dnet.connectToSession() first to authenticate with that server.`;
|
||||
const result = `${host} requires a session to do that. Use ns.dnet.connectToSession() first to authenticate with that server.`;
|
||||
logger(ctx)(result);
|
||||
return {
|
||||
success: false,
|
||||
|
||||
@@ -16,6 +16,7 @@ import { DarknetState } from "./DarknetState";
|
||||
import { getRamBlock } from "../effects/ramblock";
|
||||
import { hasFullDarknetAccess } from "../effects/effects";
|
||||
import { getFriendlyType, TypeAssertionError } from "../../utils/TypeAssertion";
|
||||
import { isIPAddress } from "../../Types/strings";
|
||||
|
||||
export type PasswordResponse = {
|
||||
code: DarknetResponseCode;
|
||||
@@ -86,23 +87,43 @@ export const DnetServerBuilder = (options: DarknetServerOptions): DarknetServer
|
||||
isStationary: false,
|
||||
});
|
||||
server.updateRamUsed(ramBlock);
|
||||
removeFromOfflineServers(name);
|
||||
DarknetState.offlineServers.delete(name);
|
||||
DarknetState.offlineServers.delete(server.ip);
|
||||
AddToAllServers(server);
|
||||
|
||||
return server;
|
||||
};
|
||||
|
||||
export const generateDarknetServerName = (): string => {
|
||||
if (Math.random() < 0.03 && DarknetState.offlineServers.length > 0 && hasFullDarknetAccess()) {
|
||||
return DarknetState.offlineServers[Math.floor(Math.random() * DarknetState.offlineServers.length)];
|
||||
if (Math.random() < 0.03 && DarknetState.offlineServers.size > 0 && hasFullDarknetAccess()) {
|
||||
// Reuse a hostname that went offline. Note that we're only reusing hostnames,
|
||||
// not IPs. This asymmetry is intentional - people find hostnames easier to
|
||||
// work with, and this adds a bit of friction to compensate.
|
||||
|
||||
// Use an iterator to directly skip to the appropriate position. Sets don't
|
||||
// have a way to index by offset, and converting to an array would be wasteful.
|
||||
const offset = Math.floor(Math.random() * DarknetState.offlineServers.size);
|
||||
const it = DarknetState.offlineServers.values();
|
||||
for (let i = 0; i < offset; ++i) {
|
||||
it.next();
|
||||
}
|
||||
// The set contains both IPs and hostnames. If we hit an IP, keep going
|
||||
// forward until we find a hostname. *If* the Set implements traversal in
|
||||
// the same order as insertion, then the fact that we insert IPs first
|
||||
// means that we will always find a hostname and the sampling will be
|
||||
// unbiased. Otherwise, it will be Mostly Unbiased(TM), and in rare cases
|
||||
// we will fall off the end without reusing a name.
|
||||
let serverName = it.next().value;
|
||||
while (serverName != null && isIPAddress(serverName)) {
|
||||
serverName = it.next().value;
|
||||
}
|
||||
if (serverName != null) {
|
||||
return serverName;
|
||||
}
|
||||
}
|
||||
return decorateName(getBaseName());
|
||||
};
|
||||
|
||||
export const removeFromOfflineServers = (hostname: string): void => {
|
||||
DarknetState.offlineServers = DarknetState.offlineServers.filter((server) => server !== hostname);
|
||||
};
|
||||
|
||||
const getBaseName = (): string => {
|
||||
if (Math.random() < 0.05) {
|
||||
return commonPasswordDictionary[Math.floor(Math.random() * commonPasswordDictionary.length)];
|
||||
|
||||
@@ -53,7 +53,23 @@ export const DarknetState = {
|
||||
* Do NOT access the server state directly via this property. You must call getServerState.
|
||||
*/
|
||||
serverState: new Map<string, ServerState>(),
|
||||
offlineServers: [] as string[],
|
||||
/**
|
||||
* Much like AllServers, this contains both hostnames and IP addresses in a single set.
|
||||
*
|
||||
* A note about memory use: On Chrome 144.0.7559.133, memory tests indicate that a
|
||||
* dense array takes ~4 bytes/entry. A Set takes ~10.24 bytes/entry. And the
|
||||
* strings we are storing inside take 14 + length bytes each. Random IPs
|
||||
* average (10+90*2+156*3)*4/256+3 = 13.28 chars, so 27.28 bytes. The
|
||||
* hostnames I don't know how to estimate, but same ballpark.
|
||||
*
|
||||
* There's two points to this:
|
||||
* 1. Most of the cost comes from the strings, so using an array won't save
|
||||
* much compared to a Set. It's better to use a Set for fast lookups.
|
||||
* 2. The size of this Set can grow without bound over time, so it's
|
||||
* important that servers not get deleted too aggressively. A
|
||||
* conservative estimate is 80 bytes/server, since there are two entries.
|
||||
*/
|
||||
offlineServers: new Set<string>(),
|
||||
showFullNetwork: false,
|
||||
zoomIndex: 7,
|
||||
netViewTopScroll: 0,
|
||||
@@ -76,7 +92,7 @@ export function prestigeDarknetState(prestigeSourceFile: boolean): void {
|
||||
DarknetState.stockPromotions = {};
|
||||
DarknetState.migrationInductionServers.clear();
|
||||
DarknetState.serverState.clear();
|
||||
DarknetState.offlineServers = [];
|
||||
DarknetState.offlineServers.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -41,7 +41,7 @@ In some cases, the only way to get to deeper parts of the net is to hitch a ride
|
||||
|
||||
**Connected** - Each server on the network has specific other servers it is linked to. These are the links seen in the UI, the servers that appear when using "scan" in the terminal, or that can be seen by calling dnet.probe. This kind of direct connection is required for most dnet API methods. ns.exec requires either a direct connection, or a backdoor, or a stasis link (which also sets a backdoor) to target a darknet server.
|
||||
|
||||
**Offline** - Sometimes darknet servers will go offline. Effectively, the server is deleted, and any running scripts that were on it are killed. Eventually, a server with the same name may come back online, but it will have a different password, and will be fully cleaned and cleared of scripts.
|
||||
**Offline** - Sometimes darknet servers will go offline. Effectively, the server is deleted, and any running scripts that were on it are killed. Eventually, a server with the same name may come back online, but it will have a different password, and will be fully cleaned and cleared of scripts. Using an API call targeting an offline server will produce a default/failed response instead of the exception you typically get with non-existent servers. Take care with this, since the list of offline servers is cleared on prestige and game reload.
|
||||
|
||||
### Darknet script design considerations
|
||||
|
||||
|
||||
@@ -67,6 +67,7 @@ import { Settings } from "../Settings/Settings";
|
||||
import { Programs } from "../Programs/Programs";
|
||||
import { getRecordKeys } from "../Types/Record";
|
||||
import { DarknetServer } from "../Server/DarknetServer";
|
||||
import { DarknetState } from "../DarkNet/models/DarknetState";
|
||||
import { getFriendlyType } from "../utils/TypeAssertion";
|
||||
|
||||
export const helpers = {
|
||||
@@ -474,22 +475,17 @@ function updateDynamicRam(ctx: NetscriptContext, ramCost: number): void {
|
||||
}
|
||||
}
|
||||
|
||||
function scriptIdentifier(
|
||||
ctx: NetscriptContext,
|
||||
scriptID: unknown,
|
||||
_hostname: unknown,
|
||||
_args: unknown,
|
||||
): ScriptIdentifier {
|
||||
function scriptIdentifier(ctx: NetscriptContext, scriptID: unknown, _host: unknown, _args: unknown): ScriptIdentifier {
|
||||
const ws = ctx.workerScript;
|
||||
// Provide the pid for the current script if no identifier provided
|
||||
if (scriptID === undefined) return ws.pid;
|
||||
if (typeof scriptID === "number") return scriptID;
|
||||
if (typeof scriptID === "string") {
|
||||
const hostname = _hostname === undefined ? ctx.workerScript.hostname : string(ctx, "hostname", _hostname);
|
||||
const host = _host === undefined ? ctx.workerScript.hostname : string(ctx, "host", _host);
|
||||
const args = _args === undefined ? [] : scriptArgs(ctx, _args);
|
||||
return {
|
||||
scriptname: scriptID,
|
||||
hostname,
|
||||
host,
|
||||
args,
|
||||
};
|
||||
}
|
||||
@@ -501,26 +497,34 @@ function scriptIdentifier(
|
||||
* server (e.g., pre-TOR darkweb, pre-TRP WD).
|
||||
*
|
||||
* @param {NetscriptContext} ctx - Context from which getServer is being called. For logging purposes.
|
||||
* @param {string} hostname - Hostname of the server
|
||||
* @returns {BaseServer} The specified server as a BaseServer
|
||||
* @param {unknown} _host - Hostname or ip of the server, defaults to current server
|
||||
* @returns {[BaseServer | null, string]} A pair containing the specified server as a BaseServer, or
|
||||
* null if the server is offline. The second part is the resolved hostname/ip.
|
||||
*/
|
||||
export function getServer(ctx: NetscriptContext, hostname: string): BaseServer {
|
||||
const server = GetServer(hostname);
|
||||
if (server == null || (server.serversOnNetwork.length == 0 && !(server instanceof DarknetServer))) {
|
||||
const str = hostname === "" ? "'' (empty string)" : "'" + hostname + "'";
|
||||
throw errorMessage(ctx, `Invalid hostname: ${str}`);
|
||||
export function getServer(ctx: NetscriptContext, _host: unknown): [BaseServer | null, string] {
|
||||
const host = helpers.string(ctx, "host", _host ?? ctx.workerScript.hostname);
|
||||
const server = GetServer(host);
|
||||
if (server != null && (server.serversOnNetwork.length > 0 || server instanceof DarknetServer)) {
|
||||
return [server, host];
|
||||
}
|
||||
return server;
|
||||
if (DarknetState.offlineServers.has(host)) {
|
||||
log(ctx, () => `Server ${host} is offline.`);
|
||||
return [null, host];
|
||||
}
|
||||
const str = host === "" ? "'' (empty string)" : "'" + host + "'";
|
||||
throw errorMessage(ctx, `Invalid host: ${str}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* A "normal server" is an instance of the Server class in src/Server/Server.ts.
|
||||
*/
|
||||
function getNormalServer(ctx: NetscriptContext, host: string): Server {
|
||||
const server = getServer(ctx, host);
|
||||
function getNormalServer(ctx: NetscriptContext, _host: unknown): Server {
|
||||
const [server, host] = getServer(ctx, _host);
|
||||
if (!(server instanceof Server)) {
|
||||
let errorMessage = `Cannot be executed on ${host}.`;
|
||||
if (server instanceof HacknetServer) {
|
||||
if (server == null) {
|
||||
errorMessage += " The server was offline (and thus a darknet server).";
|
||||
} else if (server instanceof HacknetServer) {
|
||||
errorMessage += " The server must not be a hacknet server.";
|
||||
} else if (server instanceof DarknetServer) {
|
||||
errorMessage += " The server must not be a darknet server.";
|
||||
@@ -530,10 +534,10 @@ function getNormalServer(ctx: NetscriptContext, host: string): Server {
|
||||
return server;
|
||||
}
|
||||
|
||||
function hack(ctx: NetscriptContext, hostname: string, manual: boolean, opts: unknown): Promise<number> {
|
||||
function hack(ctx: NetscriptContext, _host: unknown, manual: boolean, opts: unknown): Promise<number> {
|
||||
const ws = ctx.workerScript;
|
||||
const { threads, stock, additionalMsec } = validateHGWOptions(ctx, opts);
|
||||
const server = getNormalServer(ctx, hostname);
|
||||
const server = getNormalServer(ctx, _host);
|
||||
|
||||
// Calculate the hacking time
|
||||
// This is in seconds
|
||||
@@ -737,7 +741,7 @@ export function scriptPath(
|
||||
* Searches for and returns the RunningScript objects for the specified script.
|
||||
* If the 'fn' argument is not specified, this returns the current RunningScript.
|
||||
* @param fn - Filename of script
|
||||
* @param hostname - Hostname/ip of the server on which the script resides
|
||||
* @param host - Hostname/ip of the server on which the script resides
|
||||
* @param scriptArgs - Running script's arguments
|
||||
* @returns Running scripts identified by the parameters, or empty if no such script
|
||||
* exists, or only the current running script if the first argument 'fn'
|
||||
@@ -746,7 +750,7 @@ export function scriptPath(
|
||||
export function getRunningScriptsByArgs(
|
||||
ctx: NetscriptContext,
|
||||
fn: string,
|
||||
hostname: string,
|
||||
host: string,
|
||||
scriptArgs: ScriptArg[],
|
||||
): Map<number, RunningScript> | null {
|
||||
if (!Array.isArray(scriptArgs)) {
|
||||
@@ -759,10 +763,11 @@ export function getRunningScriptsByArgs(
|
||||
|
||||
const path = scriptPath(ctx, "filename", fn);
|
||||
// Lookup server to scope search
|
||||
if (hostname == null) {
|
||||
hostname = ctx.workerScript.hostname;
|
||||
if (host == null) {
|
||||
host = ctx.workerScript.hostname;
|
||||
}
|
||||
const server = helpers.getServer(ctx, hostname);
|
||||
const [server] = helpers.getServer(ctx, host);
|
||||
if (!server) return null;
|
||||
|
||||
return findRunningScripts(path, scriptArgs, server);
|
||||
}
|
||||
@@ -771,7 +776,7 @@ function getRunningScript(ctx: NetscriptContext, ident: ScriptIdentifier): Runni
|
||||
if (typeof ident === "number") {
|
||||
return findRunningScriptByPid(ident);
|
||||
} else {
|
||||
const scripts = getRunningScriptsByArgs(ctx, ident.scriptname, ident.hostname, ident.args);
|
||||
const scripts = getRunningScriptsByArgs(ctx, ident.scriptname, ident.host, ident.args);
|
||||
if (scripts === null) {
|
||||
return null;
|
||||
}
|
||||
@@ -789,7 +794,7 @@ function getRunningScript(ctx: NetscriptContext, ident: ScriptIdentifier): Runni
|
||||
function getCannotFindRunningScriptErrorMessage(ident: ScriptIdentifier): string {
|
||||
if (typeof ident === "number") return `Cannot find running script with pid: ${ident}`;
|
||||
|
||||
return `Cannot find running script ${ident.scriptname} on server ${ident.hostname} with args: ${arrayToString(
|
||||
return `Cannot find running script ${ident.scriptname} on server ${ident.host} with args: ${arrayToString(
|
||||
ident.args,
|
||||
)}`;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,6 @@ export type ScriptIdentifier =
|
||||
| number
|
||||
| {
|
||||
scriptname: string;
|
||||
hostname: string;
|
||||
host: string;
|
||||
args: ScriptArg[];
|
||||
};
|
||||
|
||||
@@ -109,7 +109,6 @@ import { isIPAddress } from "./Types/strings";
|
||||
import { compile } from "./NetscriptJSEvaluator";
|
||||
import { Script } from "./Script/Script";
|
||||
import { NetscriptFormat } from "./NetscriptFunctions/Format";
|
||||
import { DarknetState } from "./DarkNet/models/DarknetState";
|
||||
import { checkDarknetServer } from "./DarkNet/effects/offlineServerHandling";
|
||||
import { DarknetServer } from "./Server/DarknetServer";
|
||||
import { FragmentTypeEnum } from "./CotMG/FragmentType";
|
||||
@@ -176,10 +175,12 @@ export const ns: InternalAPI<NSFull> = {
|
||||
return vsprintf(format, _args);
|
||||
},
|
||||
scan: (ctx) => (_host, _returnOpts) => {
|
||||
const host = _host ? helpers.string(ctx, "host", _host) : ctx.workerScript.hostname;
|
||||
const returnOpts = helpers.hostReturnOptions(_returnOpts);
|
||||
const server = helpers.getServer(ctx, host);
|
||||
const [server, host] = helpers.getServer(ctx, _host);
|
||||
const out: string[] = [];
|
||||
if (!server) {
|
||||
return out;
|
||||
}
|
||||
for (let i = 0; i < server.serversOnNetwork.length; i++) {
|
||||
const s = getServerOnNetwork(server, i);
|
||||
if (s === null || s instanceof DarknetServer) continue;
|
||||
@@ -187,20 +188,18 @@ export const ns: InternalAPI<NSFull> = {
|
||||
if (entry === null) continue;
|
||||
out.push(entry);
|
||||
}
|
||||
helpers.log(ctx, () => `returned ${out.length} connections for ${isIPAddress(host) ? server.ip : server.hostname}`);
|
||||
helpers.log(ctx, () => `returned ${out.length} connections for ${host}`);
|
||||
return out;
|
||||
},
|
||||
hasTorRouter: () => () => Player.hasTorRouter(),
|
||||
hack: (ctx) => (_host, opts?) => {
|
||||
const host = helpers.string(ctx, "host", _host);
|
||||
return helpers.hack(ctx, host, false, opts);
|
||||
hack: (ctx) => (_host?, opts?) => {
|
||||
return helpers.hack(ctx, _host, false, opts);
|
||||
},
|
||||
hackAnalyzeThreads: (ctx) => (_host, _hackAmount) => {
|
||||
const host = helpers.string(ctx, "host", _host);
|
||||
const hackAmount = helpers.number(ctx, "hackAmount", _hackAmount);
|
||||
|
||||
// Check argument validity
|
||||
const server = helpers.getNormalServer(ctx, host);
|
||||
const server = helpers.getNormalServer(ctx, _host);
|
||||
if (isNaN(hackAmount)) {
|
||||
throw helpers.errorMessage(
|
||||
ctx,
|
||||
@@ -222,18 +221,15 @@ export const ns: InternalAPI<NSFull> = {
|
||||
|
||||
return hackAmount / (server.moneyAvailable * percentHacked);
|
||||
},
|
||||
hackAnalyze: (ctx) => (_host) => {
|
||||
const host = helpers.string(ctx, "host", _host);
|
||||
|
||||
const server = helpers.getNormalServer(ctx, host);
|
||||
hackAnalyze: (ctx) => (_host?) => {
|
||||
const server = helpers.getNormalServer(ctx, _host);
|
||||
|
||||
return calculatePercentMoneyHacked(server, Player);
|
||||
},
|
||||
hackAnalyzeSecurity: (ctx) => (_threads, _host?) => {
|
||||
let threads = helpers.number(ctx, "threads", _threads);
|
||||
if (_host) {
|
||||
const host = helpers.string(ctx, "host", _host);
|
||||
const server = helpers.getNormalServer(ctx, host);
|
||||
const server = helpers.getNormalServer(ctx, _host);
|
||||
|
||||
const percentHacked = calculatePercentMoneyHacked(server, Player);
|
||||
|
||||
@@ -245,10 +241,8 @@ export const ns: InternalAPI<NSFull> = {
|
||||
|
||||
return ServerConstants.ServerFortifyAmount * threads;
|
||||
},
|
||||
hackAnalyzeChance: (ctx) => (_host) => {
|
||||
const host = helpers.string(ctx, "host", _host);
|
||||
|
||||
const server = helpers.getNormalServer(ctx, host);
|
||||
hackAnalyzeChance: (ctx) => (_host?) => {
|
||||
const server = helpers.getNormalServer(ctx, _host);
|
||||
|
||||
return calculateHackingChance(server, Player);
|
||||
},
|
||||
@@ -269,10 +263,9 @@ export const ns: InternalAPI<NSFull> = {
|
||||
return new Promise((resolve) => setTimeout(() => resolve(true), time));
|
||||
},
|
||||
grow: (ctx) => (_host, opts?) => {
|
||||
const host = helpers.string(ctx, "host", _host);
|
||||
const { threads, stock, additionalMsec } = helpers.validateHGWOptions(ctx, opts);
|
||||
|
||||
const server = helpers.getNormalServer(ctx, host);
|
||||
const server = helpers.getNormalServer(ctx, _host);
|
||||
|
||||
// No root access or skill level too low
|
||||
const canHack = netscriptCanGrow(server);
|
||||
@@ -317,12 +310,11 @@ export const ns: InternalAPI<NSFull> = {
|
||||
growthAnalyze:
|
||||
(ctx) =>
|
||||
(_host, _multiplier, _cores = 1) => {
|
||||
const host = helpers.string(ctx, "hostname", _host);
|
||||
const mult = helpers.number(ctx, "multiplier", _multiplier);
|
||||
const cores = helpers.positiveInteger(ctx, "cores", _cores);
|
||||
|
||||
// Check argument validity
|
||||
const server = helpers.getNormalServer(ctx, host);
|
||||
const server = helpers.getNormalServer(ctx, _host);
|
||||
if (!Number.isFinite(mult) || mult < 1) {
|
||||
throw helpers.errorMessage(ctx, `Invalid argument: multiplier must be finite and >= 1, is ${mult}.`);
|
||||
}
|
||||
@@ -335,8 +327,7 @@ export const ns: InternalAPI<NSFull> = {
|
||||
let threads = helpers.number(ctx, "threads", _threads);
|
||||
if (_host) {
|
||||
const cores = helpers.number(ctx, "cores", _cores);
|
||||
const host = helpers.string(ctx, "host", _host);
|
||||
const server = helpers.getNormalServer(ctx, host);
|
||||
const server = helpers.getNormalServer(ctx, _host);
|
||||
|
||||
const maxThreadsNeeded = Math.ceil(
|
||||
numCycleForGrowthCorrected(server, server.moneyMax, server.moneyAvailable, cores),
|
||||
@@ -347,11 +338,10 @@ export const ns: InternalAPI<NSFull> = {
|
||||
|
||||
return 2 * ServerConstants.ServerFortifyAmount * threads;
|
||||
},
|
||||
weaken: (ctx) => async (_host, opts?) => {
|
||||
const host = helpers.string(ctx, "host", _host);
|
||||
weaken: (ctx) => async (_host?, opts?) => {
|
||||
const { threads, additionalMsec } = helpers.validateHGWOptions(ctx, opts);
|
||||
|
||||
const server = helpers.getNormalServer(ctx, host);
|
||||
const server = helpers.getNormalServer(ctx, _host);
|
||||
|
||||
// No root access or skill level too low
|
||||
const canHack = netscriptCanWeaken(server);
|
||||
@@ -404,7 +394,7 @@ export const ns: InternalAPI<NSFull> = {
|
||||
const threads = ctx.workerScript.scriptRef.threads;
|
||||
const hostname = ctx.workerScript.hostname;
|
||||
helpers.log(ctx, () => `Sharing ${threads} threads on ${hostname}.`);
|
||||
const end = startSharing(threads, helpers.getServer(ctx, hostname).cpuCores);
|
||||
const end = startSharing(threads, ctx.workerScript.getServer().cpuCores);
|
||||
return helpers.netscriptDelay(ctx, ShareBonusTime).finally(function () {
|
||||
helpers.log(ctx, () => `Finished sharing ${threads} threads on ${hostname}.`);
|
||||
end();
|
||||
@@ -537,10 +527,8 @@ export const ns: InternalAPI<NSFull> = {
|
||||
|
||||
return runningScriptObj.logs.map((x) => String(x));
|
||||
},
|
||||
nuke: (ctx) => (_host) => {
|
||||
const host = helpers.string(ctx, "host", _host);
|
||||
|
||||
const server = helpers.getNormalServer(ctx, host);
|
||||
nuke: (ctx) => (_host?) => {
|
||||
const server = helpers.getNormalServer(ctx, _host);
|
||||
if (server.hasAdminRights) {
|
||||
helpers.log(ctx, () => `Already have root access to '${server.hostname}'.`);
|
||||
return true;
|
||||
@@ -557,9 +545,8 @@ export const ns: InternalAPI<NSFull> = {
|
||||
helpers.log(ctx, () => `Executed NUKE.exe virus on '${server.hostname}' to gain root access.`);
|
||||
return true;
|
||||
},
|
||||
brutessh: (ctx) => (_host) => {
|
||||
const host = helpers.string(ctx, "host", _host);
|
||||
const server = helpers.getNormalServer(ctx, host);
|
||||
brutessh: (ctx) => (_host?) => {
|
||||
const server = helpers.getNormalServer(ctx, _host);
|
||||
if (!Player.hasProgram(CompletedProgramName.bruteSsh)) {
|
||||
helpers.log(ctx, () => "You do not have the BruteSSH.exe program!");
|
||||
return false;
|
||||
@@ -573,9 +560,8 @@ export const ns: InternalAPI<NSFull> = {
|
||||
}
|
||||
return true;
|
||||
},
|
||||
ftpcrack: (ctx) => (_host) => {
|
||||
const host = helpers.string(ctx, "host", _host);
|
||||
const server = helpers.getNormalServer(ctx, host);
|
||||
ftpcrack: (ctx) => (_host?) => {
|
||||
const server = helpers.getNormalServer(ctx, _host);
|
||||
if (!Player.hasProgram(CompletedProgramName.ftpCrack)) {
|
||||
helpers.log(ctx, () => "You do not have the FTPCrack.exe program!");
|
||||
return false;
|
||||
@@ -590,8 +576,7 @@ export const ns: InternalAPI<NSFull> = {
|
||||
return true;
|
||||
},
|
||||
relaysmtp: (ctx) => (_host) => {
|
||||
const host = helpers.string(ctx, "host", _host);
|
||||
const server = helpers.getNormalServer(ctx, host);
|
||||
const server = helpers.getNormalServer(ctx, _host);
|
||||
if (!Player.hasProgram(CompletedProgramName.relaySmtp)) {
|
||||
helpers.log(ctx, () => "You do not have the relaySMTP.exe program!");
|
||||
return false;
|
||||
@@ -605,9 +590,8 @@ export const ns: InternalAPI<NSFull> = {
|
||||
}
|
||||
return true;
|
||||
},
|
||||
httpworm: (ctx) => (_host) => {
|
||||
const host = helpers.string(ctx, "host", _host);
|
||||
const server = helpers.getNormalServer(ctx, host);
|
||||
httpworm: (ctx) => (_host?) => {
|
||||
const server = helpers.getNormalServer(ctx, _host);
|
||||
if (!Player.hasProgram(CompletedProgramName.httpWorm)) {
|
||||
helpers.log(ctx, () => "You do not have the HTTPWorm.exe program!");
|
||||
return false;
|
||||
@@ -621,9 +605,8 @@ export const ns: InternalAPI<NSFull> = {
|
||||
}
|
||||
return true;
|
||||
},
|
||||
sqlinject: (ctx) => (_host) => {
|
||||
const host = helpers.string(ctx, "host", _host);
|
||||
const server = helpers.getNormalServer(ctx, host);
|
||||
sqlinject: (ctx) => (_host?) => {
|
||||
const server = helpers.getNormalServer(ctx, _host);
|
||||
if (!Player.hasProgram(CompletedProgramName.sqlInject)) {
|
||||
helpers.log(ctx, () => "You do not have the SQLInject.exe program!");
|
||||
return false;
|
||||
@@ -654,19 +637,17 @@ export const ns: InternalAPI<NSFull> = {
|
||||
const host = helpers.string(ctx, "host", _host);
|
||||
const runOpts = helpers.runOptions(ctx, _thread_or_opt);
|
||||
const args = helpers.scriptArgs(ctx, _args);
|
||||
if (
|
||||
!checkDarknetServer(ctx, host, {
|
||||
allowNonDarknet: true,
|
||||
requireAdminRights: true,
|
||||
requireSession: true,
|
||||
requireDirectConnection: true,
|
||||
backdoorBypasses: true,
|
||||
}).success
|
||||
) {
|
||||
const serverCheck = checkDarknetServer(ctx, host, {
|
||||
allowNonDarknet: true,
|
||||
requireAdminRights: true,
|
||||
requireSession: true,
|
||||
requireDirectConnection: true,
|
||||
backdoorBypasses: true,
|
||||
});
|
||||
if (!serverCheck.success) {
|
||||
return 0;
|
||||
}
|
||||
const server = helpers.getServer(ctx, host);
|
||||
return runScriptFromScript("exec", server, path, args, ctx.workerScript, runOpts);
|
||||
return runScriptFromScript("exec", serverCheck.server, path, args, ctx.workerScript, runOpts);
|
||||
},
|
||||
spawn:
|
||||
(ctx) =>
|
||||
@@ -713,20 +694,20 @@ export const ns: InternalAPI<NSFull> = {
|
||||
},
|
||||
kill:
|
||||
(ctx) =>
|
||||
(scriptID, host = ctx.workerScript.hostname, ...scriptArgs) => {
|
||||
const ident = helpers.scriptIdentifier(ctx, scriptID, host, scriptArgs);
|
||||
(scriptID, _host?, ...scriptArgs) => {
|
||||
const ident = helpers.scriptIdentifier(ctx, scriptID, _host, scriptArgs);
|
||||
let res;
|
||||
const killByPid = typeof ident === "number";
|
||||
if (killByPid) {
|
||||
// Kill by pid
|
||||
res = killWorkerScriptByPid(ident, ctx.workerScript);
|
||||
} else {
|
||||
// Kill by filename/hostname
|
||||
// Kill by filename/host
|
||||
if (scriptID === undefined) {
|
||||
throw helpers.errorMessage(ctx, "Usage: kill(scriptname, server, [arg1], [arg2]...)");
|
||||
}
|
||||
|
||||
const byPid = helpers.getRunningScriptsByArgs(ctx, ident.scriptname, ident.hostname, ident.args);
|
||||
const byPid = helpers.getRunningScriptsByArgs(ctx, ident.scriptname, ident.host, ident.args);
|
||||
if (byPid === null) {
|
||||
helpers.log(ctx, () => helpers.getCannotFindRunningScriptErrorMessage(ident));
|
||||
return false;
|
||||
@@ -742,7 +723,7 @@ export const ns: InternalAPI<NSFull> = {
|
||||
if (killByPid) {
|
||||
helpers.log(ctx, () => `Killing script with PID ${ident}`);
|
||||
} else {
|
||||
helpers.log(ctx, () => `Killing '${scriptID}' on '${host}' with args: ${arrayToString(scriptArgs)}.`);
|
||||
helpers.log(ctx, () => `Killing '${scriptID}' on '${ident.host}' with args: ${arrayToString(scriptArgs)}.`);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
@@ -751,7 +732,7 @@ export const ns: InternalAPI<NSFull> = {
|
||||
} else {
|
||||
helpers.log(
|
||||
ctx,
|
||||
() => `Internal error killing '${scriptID}' on '${host}' with args: ${arrayToString(scriptArgs)}`,
|
||||
() => `Internal error killing '${scriptID}' on '${ident.host}' with args: ${arrayToString(scriptArgs)}`,
|
||||
);
|
||||
}
|
||||
return false;
|
||||
@@ -759,10 +740,10 @@ export const ns: InternalAPI<NSFull> = {
|
||||
},
|
||||
killall:
|
||||
(ctx) =>
|
||||
(_host = ctx.workerScript.hostname, _safetyGuard = true) => {
|
||||
const host = helpers.string(ctx, "host", _host);
|
||||
(_host?, _safetyGuard = true) => {
|
||||
const safetyGuard = !!_safetyGuard;
|
||||
const server = helpers.getServer(ctx, host);
|
||||
const [server, host] = helpers.getServer(ctx, _host);
|
||||
if (!server) return false;
|
||||
let scriptsKilled = 0;
|
||||
|
||||
for (const byPid of server.runningScriptMap.values()) {
|
||||
@@ -772,7 +753,7 @@ export const ns: InternalAPI<NSFull> = {
|
||||
++scriptsKilled;
|
||||
}
|
||||
}
|
||||
helpers.log(ctx, () => `Killing all scripts on '${server.hostname}'.`);
|
||||
helpers.log(ctx, () => `Killing all scripts on '${host}'.`);
|
||||
|
||||
return scriptsKilled > 0;
|
||||
},
|
||||
@@ -784,20 +765,19 @@ export const ns: InternalAPI<NSFull> = {
|
||||
scp: (ctx) => (_files, _destination, _source) => {
|
||||
const destination = helpers.string(ctx, "destination", _destination);
|
||||
const source = helpers.string(ctx, "source", _source ?? ctx.workerScript.hostname);
|
||||
if (
|
||||
!checkDarknetServer(ctx, destination, {
|
||||
allowNonDarknet: true,
|
||||
requireAdminRights: true,
|
||||
requireSession: true,
|
||||
}).success
|
||||
) {
|
||||
const destinationCheck = checkDarknetServer(ctx, destination, {
|
||||
allowNonDarknet: true,
|
||||
requireAdminRights: true,
|
||||
requireSession: true,
|
||||
});
|
||||
if (!destinationCheck.success) {
|
||||
return false;
|
||||
}
|
||||
if (!checkDarknetServer(ctx, source, { allowNonDarknet: true }).success) {
|
||||
const destServer = destinationCheck.server;
|
||||
const [sourceServer] = helpers.getServer(ctx, source);
|
||||
if (!sourceServer) {
|
||||
return false;
|
||||
}
|
||||
const sourceServer = helpers.getServer(ctx, source);
|
||||
const destServer = helpers.getServer(ctx, destination);
|
||||
const files = Array.isArray(_files) ? _files : [_files];
|
||||
const lits: FilePath[] = [];
|
||||
const contentFiles: ContentFilePath[] = [];
|
||||
@@ -857,13 +837,11 @@ export const ns: InternalAPI<NSFull> = {
|
||||
return noFailures;
|
||||
},
|
||||
ls: (ctx) => (_host, _substring) => {
|
||||
const host = helpers.string(ctx, "host", _host);
|
||||
const [server] = helpers.getServer(ctx, _host);
|
||||
const substring = helpers.string(ctx, "substring", _substring ?? "");
|
||||
if (DarknetState.offlineServers.includes(host)) {
|
||||
helpers.log(ctx, () => `ls failed, because ${host} is offline.`);
|
||||
if (!server) {
|
||||
return [];
|
||||
}
|
||||
const server = helpers.getServer(ctx, host);
|
||||
|
||||
const allFilenames = [
|
||||
...server.contracts.map((contract) => contract.fn),
|
||||
@@ -883,34 +861,31 @@ export const ns: InternalAPI<NSFull> = {
|
||||
...helpers.createPublicRunningScript(rs.runningScript),
|
||||
}));
|
||||
},
|
||||
ps:
|
||||
(ctx) =>
|
||||
(_host = ctx.workerScript.hostname) => {
|
||||
const host = helpers.string(ctx, "host", _host);
|
||||
const server = helpers.getServer(ctx, host);
|
||||
const processes: ProcessInfo[] = [];
|
||||
for (const byPid of server.runningScriptMap.values()) {
|
||||
for (const script of byPid.values()) {
|
||||
processes.push({
|
||||
filename: script.filename,
|
||||
threads: script.threads,
|
||||
args: script.args.slice(),
|
||||
pid: script.pid,
|
||||
temporary: script.temporary,
|
||||
});
|
||||
}
|
||||
ps: (ctx) => (_host?) => {
|
||||
const [server] = helpers.getServer(ctx, _host);
|
||||
const processes: ProcessInfo[] = [];
|
||||
if (!server) return processes;
|
||||
for (const byPid of server.runningScriptMap.values()) {
|
||||
for (const script of byPid.values()) {
|
||||
processes.push({
|
||||
filename: script.filename,
|
||||
threads: script.threads,
|
||||
args: script.args.slice(),
|
||||
pid: script.pid,
|
||||
temporary: script.temporary,
|
||||
});
|
||||
}
|
||||
return processes;
|
||||
},
|
||||
hasRootAccess: (ctx) => (_host) => {
|
||||
const host = helpers.string(ctx, "host", _host);
|
||||
const server = helpers.getServer(ctx, host);
|
||||
}
|
||||
return processes;
|
||||
},
|
||||
hasRootAccess: (ctx) => (_host?) => {
|
||||
const [server] = helpers.getServer(ctx, _host);
|
||||
if (!server) return false;
|
||||
return server.hasAdminRights;
|
||||
},
|
||||
getHostname: (ctx) => () => ctx.workerScript.hostname,
|
||||
getIP: (ctx) => () => {
|
||||
const hostname = ctx.workerScript.hostname;
|
||||
const server = helpers.getServer(ctx, hostname);
|
||||
const server = ctx.workerScript.getServer();
|
||||
return server.ip;
|
||||
},
|
||||
getHackingLevel: (ctx) => () => {
|
||||
@@ -949,23 +924,17 @@ export const ns: InternalAPI<NSFull> = {
|
||||
|
||||
return Object.assign({}, getBitNodeMultipliers(n, lvl));
|
||||
},
|
||||
getServer: (ctx) => (_host) => {
|
||||
const host = helpers.string(ctx, "host", _host ?? ctx.workerScript.hostname);
|
||||
const server = GetServer(host);
|
||||
// If the target server does not exist
|
||||
getServer: (ctx) => (_host?) => {
|
||||
const [server, host] = helpers.getServer(ctx, _host);
|
||||
if (!server) {
|
||||
if (DarknetState.offlineServers.includes(host)) {
|
||||
// If the server is offline, return a dummy object with isOnline = false.
|
||||
helpers.log(ctx, () => `Server ${host} is offline.`);
|
||||
return {
|
||||
isOnline: false,
|
||||
...exampleDarknetServerData,
|
||||
hostname: host,
|
||||
} satisfies DarknetServerData & { isOnline: boolean };
|
||||
} else {
|
||||
// Throw, otherwise.
|
||||
throw helpers.errorMessage(ctx, `Server ${host} does not exist.`);
|
||||
}
|
||||
// If the server is offline, return a dummy object with isOnline = false.
|
||||
const isIp = isIPAddress(host);
|
||||
return {
|
||||
isOnline: false,
|
||||
...exampleDarknetServerData,
|
||||
hostname: isIp ? "" : host,
|
||||
ip: isIp ? host : "",
|
||||
} satisfies DarknetServerData & { isOnline: boolean };
|
||||
}
|
||||
if (server instanceof DarknetServer) {
|
||||
return {
|
||||
@@ -1022,9 +991,8 @@ export const ns: InternalAPI<NSFull> = {
|
||||
serverGrowth: server.serverGrowth,
|
||||
} satisfies NSInterfaceServer;
|
||||
},
|
||||
getServerMoneyAvailable: (ctx) => (_host) => {
|
||||
const host = helpers.string(ctx, "host", _host);
|
||||
const server = helpers.getNormalServer(ctx, host);
|
||||
getServerMoneyAvailable: (ctx) => (_host?) => {
|
||||
const server = helpers.getNormalServer(ctx, _host);
|
||||
if (server.hostname == "home") {
|
||||
// Return player's money
|
||||
helpers.log(ctx, () => `returned player's money: ${formatMoney(Player.money)}`);
|
||||
@@ -1033,63 +1001,56 @@ export const ns: InternalAPI<NSFull> = {
|
||||
helpers.log(ctx, () => `returned ${formatMoney(server.moneyAvailable)} for '${server.hostname}'`);
|
||||
return server.moneyAvailable;
|
||||
},
|
||||
getServerSecurityLevel: (ctx) => (_host) => {
|
||||
const host = helpers.string(ctx, "host", _host);
|
||||
const server = helpers.getNormalServer(ctx, host);
|
||||
getServerSecurityLevel: (ctx) => (_host?) => {
|
||||
const server = helpers.getNormalServer(ctx, _host);
|
||||
helpers.log(ctx, () => `returned ${formatSecurity(server.hackDifficulty)} for '${server.hostname}'`);
|
||||
return server.hackDifficulty;
|
||||
},
|
||||
getServerBaseSecurityLevel: (ctx) => (_host) => {
|
||||
const host = helpers.string(ctx, "host", _host);
|
||||
const server = helpers.getNormalServer(ctx, host);
|
||||
getServerBaseSecurityLevel: (ctx) => (_host?) => {
|
||||
const server = helpers.getNormalServer(ctx, _host);
|
||||
helpers.log(ctx, () => `returned ${formatSecurity(server.baseDifficulty)} for '${server.hostname}'`);
|
||||
return server.baseDifficulty;
|
||||
},
|
||||
getServerMinSecurityLevel: (ctx) => (_host) => {
|
||||
const host = helpers.string(ctx, "host", _host);
|
||||
const server = helpers.getNormalServer(ctx, host);
|
||||
getServerMinSecurityLevel: (ctx) => (_host?) => {
|
||||
const server = helpers.getNormalServer(ctx, _host);
|
||||
helpers.log(ctx, () => `returned ${formatSecurity(server.minDifficulty)} for ${server.hostname}`);
|
||||
return server.minDifficulty;
|
||||
},
|
||||
getServerRequiredHackingLevel: (ctx) => (_host) => {
|
||||
const host = helpers.string(ctx, "host", _host);
|
||||
const server = helpers.getNormalServer(ctx, host);
|
||||
getServerRequiredHackingLevel: (ctx) => (_host?) => {
|
||||
const server = helpers.getNormalServer(ctx, _host);
|
||||
helpers.log(ctx, () => `returned ${formatNumberNoSuffix(server.requiredHackingSkill, 0)} for '${server.hostname}'`);
|
||||
return server.requiredHackingSkill;
|
||||
},
|
||||
getServerMaxMoney: (ctx) => (_host) => {
|
||||
const host = helpers.string(ctx, "host", _host);
|
||||
const server = helpers.getNormalServer(ctx, host);
|
||||
getServerMaxMoney: (ctx) => (_host?) => {
|
||||
const server = helpers.getNormalServer(ctx, _host);
|
||||
helpers.log(ctx, () => `returned ${formatMoney(server.moneyMax)} for '${server.hostname}'`);
|
||||
return server.moneyMax;
|
||||
},
|
||||
getServerGrowth: (ctx) => (_host) => {
|
||||
const host = helpers.string(ctx, "host", _host);
|
||||
const server = helpers.getNormalServer(ctx, host);
|
||||
getServerGrowth: (ctx) => (_host?) => {
|
||||
const server = helpers.getNormalServer(ctx, _host);
|
||||
helpers.log(ctx, () => `returned ${server.serverGrowth} for '${server.hostname}'`);
|
||||
return server.serverGrowth;
|
||||
},
|
||||
getServerNumPortsRequired: (ctx) => (_host) => {
|
||||
const host = helpers.string(ctx, "host", _host);
|
||||
const server = helpers.getNormalServer(ctx, host);
|
||||
getServerNumPortsRequired: (ctx) => (_host?) => {
|
||||
const server = helpers.getNormalServer(ctx, _host);
|
||||
helpers.log(ctx, () => `returned ${server.numOpenPortsRequired} for '${server.hostname}'`);
|
||||
return server.numOpenPortsRequired;
|
||||
},
|
||||
getServerMaxRam: (ctx) => (_host) => {
|
||||
const host = helpers.string(ctx, "host", _host);
|
||||
const server = helpers.getServer(ctx, host);
|
||||
getServerMaxRam: (ctx) => (_host?) => {
|
||||
const [server] = helpers.getServer(ctx, _host);
|
||||
if (!server) return 0;
|
||||
helpers.log(ctx, () => `returned ${formatRam(server.maxRam)}`);
|
||||
return server.maxRam;
|
||||
},
|
||||
getServerUsedRam: (ctx) => (_host) => {
|
||||
const host = helpers.string(ctx, "host", _host);
|
||||
const server = helpers.getServer(ctx, host);
|
||||
getServerUsedRam: (ctx) => (_host?) => {
|
||||
const [server] = helpers.getServer(ctx, _host);
|
||||
if (!server) return 0;
|
||||
helpers.log(ctx, () => `returned ${formatRam(server.ramUsed)}`);
|
||||
return server.ramUsed;
|
||||
},
|
||||
dnsLookup: (ctx) => (_host) => {
|
||||
const host = helpers.string(ctx, "host", _host);
|
||||
const server = helpers.getServer(ctx, host);
|
||||
dnsLookup: (ctx) => (_host?) => {
|
||||
const [server, host] = helpers.getServer(ctx, _host);
|
||||
if (!server) return "";
|
||||
return isIPAddress(host) ? server.hostname : server.ip;
|
||||
},
|
||||
serverExists: (ctx) => (_host) => {
|
||||
@@ -1097,10 +1058,10 @@ export const ns: InternalAPI<NSFull> = {
|
||||
const server = GetServer(host);
|
||||
return server !== null && (server.serversOnNetwork.length > 0 || server instanceof DarknetServer);
|
||||
},
|
||||
fileExists: (ctx) => (_filename, _host) => {
|
||||
fileExists: (ctx) => (_filename, _host?) => {
|
||||
const filename = helpers.string(ctx, "filename", _filename);
|
||||
const host = helpers.string(ctx, "host", _host ?? ctx.workerScript.hostname);
|
||||
const server = helpers.getServer(ctx, host);
|
||||
const [server] = helpers.getServer(ctx, _host);
|
||||
if (!server) return false;
|
||||
const path = resolveFilePath(filename, ctx.workerScript.name);
|
||||
if (!path) return false;
|
||||
if (hasScriptExtension(path)) return server.scripts.has(path);
|
||||
@@ -1113,7 +1074,7 @@ export const ns: InternalAPI<NSFull> = {
|
||||
},
|
||||
isRunning:
|
||||
(ctx) =>
|
||||
(fn, host, ...scriptArgs) => {
|
||||
(fn, host?, ...scriptArgs) => {
|
||||
const ident = helpers.scriptIdentifier(ctx, fn, host, scriptArgs);
|
||||
return helpers.getRunningScript(ctx, ident) !== null;
|
||||
},
|
||||
@@ -1126,7 +1087,7 @@ export const ns: InternalAPI<NSFull> = {
|
||||
const data = helpers.string(ctx, "data", _data ?? "");
|
||||
const mode = helpers.string(ctx, "mode", _mode ?? "a");
|
||||
|
||||
const server = helpers.getServer(ctx, ctx.workerScript.hostname);
|
||||
const server = ctx.workerScript.getServer();
|
||||
|
||||
if (hasScriptExtension(filepath)) {
|
||||
if (mode === "w") {
|
||||
@@ -1217,10 +1178,10 @@ export const ns: InternalAPI<NSFull> = {
|
||||
const portHandle = helpers.portHandle(ctx, _portNumber);
|
||||
return portHandle;
|
||||
},
|
||||
rm: (ctx) => (_fn, _host) => {
|
||||
rm: (ctx) => (_fn, _host?) => {
|
||||
const filepath = helpers.filePath(ctx, "fn", _fn);
|
||||
const host = helpers.string(ctx, "host", _host ?? ctx.workerScript.hostname);
|
||||
const s = helpers.getServer(ctx, host);
|
||||
const [s] = helpers.getServer(ctx, _host);
|
||||
if (!s) return false;
|
||||
if (!filepath) {
|
||||
helpers.log(ctx, () => `Error while parsing filepath ${filepath}`);
|
||||
return false;
|
||||
@@ -1233,16 +1194,16 @@ export const ns: InternalAPI<NSFull> = {
|
||||
|
||||
return status.res;
|
||||
},
|
||||
scriptRunning: (ctx) => (_scriptname, _host) => {
|
||||
scriptRunning: (ctx) => (_scriptname, _host?) => {
|
||||
const scriptname = helpers.scriptPath(ctx, "scriptname", _scriptname);
|
||||
const host = helpers.string(ctx, "host", _host);
|
||||
const server = helpers.getServer(ctx, host);
|
||||
const [server] = helpers.getServer(ctx, _host);
|
||||
if (!server) return false;
|
||||
return server.isRunning(scriptname);
|
||||
},
|
||||
scriptKill: (ctx) => (_scriptname, _host) => {
|
||||
scriptKill: (ctx) => (_scriptname, _host?) => {
|
||||
const path = helpers.scriptPath(ctx, "scriptname", _scriptname);
|
||||
const host = helpers.string(ctx, "host", _host);
|
||||
const server = helpers.getServer(ctx, host);
|
||||
const [server] = helpers.getServer(ctx, _host);
|
||||
if (!server) return false;
|
||||
let suc = false;
|
||||
|
||||
const pattern = matchScriptPathExact(escapeRegExp(path));
|
||||
@@ -1256,10 +1217,10 @@ export const ns: InternalAPI<NSFull> = {
|
||||
return suc;
|
||||
},
|
||||
getScriptName: (ctx) => () => ctx.workerScript.name,
|
||||
getScriptRam: (ctx) => (_scriptname, _host) => {
|
||||
getScriptRam: (ctx) => (_scriptname, _host?) => {
|
||||
const path = helpers.scriptPath(ctx, "scriptname", _scriptname);
|
||||
const host = helpers.string(ctx, "hostname", _host ?? ctx.workerScript.hostname);
|
||||
const server = helpers.getServer(ctx, host);
|
||||
const [server, host] = helpers.getServer(ctx, _host);
|
||||
if (!server) return 0;
|
||||
const script = server.scripts.get(path);
|
||||
if (!script) return 0;
|
||||
const ramUsage = script.getRamUsage(server.scripts);
|
||||
@@ -1271,7 +1232,7 @@ export const ns: InternalAPI<NSFull> = {
|
||||
},
|
||||
getRunningScript:
|
||||
(ctx) =>
|
||||
(fn, host, ...args) => {
|
||||
(fn, host?, ...args) => {
|
||||
const ident = helpers.scriptIdentifier(ctx, fn, host, args);
|
||||
const runningScript = helpers.getRunningScript(ctx, ident);
|
||||
if (runningScript === null) return null;
|
||||
@@ -1304,30 +1265,21 @@ export const ns: InternalAPI<NSFull> = {
|
||||
rs.ramUsage = newRam;
|
||||
return rs.ramUsage;
|
||||
},
|
||||
getHackTime:
|
||||
(ctx) =>
|
||||
(_host = ctx.workerScript.hostname) => {
|
||||
const host = helpers.string(ctx, "hostname", _host);
|
||||
const server = helpers.getNormalServer(ctx, host);
|
||||
getHackTime: (ctx) => (_host?) => {
|
||||
const server = helpers.getNormalServer(ctx, _host);
|
||||
|
||||
return calculateHackingTime(server, Player) * 1000;
|
||||
},
|
||||
getGrowTime:
|
||||
(ctx) =>
|
||||
(_host = ctx.workerScript.hostname) => {
|
||||
const host = helpers.string(ctx, "host", _host);
|
||||
const server = helpers.getNormalServer(ctx, host);
|
||||
return calculateHackingTime(server, Player) * 1000;
|
||||
},
|
||||
getGrowTime: (ctx) => (_host?) => {
|
||||
const server = helpers.getNormalServer(ctx, _host);
|
||||
|
||||
return calculateGrowTime(server, Player) * 1000;
|
||||
},
|
||||
getWeakenTime:
|
||||
(ctx) =>
|
||||
(_host = ctx.workerScript.hostname) => {
|
||||
const host = helpers.string(ctx, "hostname", _host);
|
||||
const server = helpers.getNormalServer(ctx, host);
|
||||
return calculateGrowTime(server, Player) * 1000;
|
||||
},
|
||||
getWeakenTime: (ctx) => (_host) => {
|
||||
const server = helpers.getNormalServer(ctx, _host);
|
||||
|
||||
return calculateWeakenTime(server, Player) * 1000;
|
||||
},
|
||||
return calculateWeakenTime(server, Player) * 1000;
|
||||
},
|
||||
getTotalScriptIncome: () => () => {
|
||||
// First element is total income of all currently running scripts
|
||||
let total = 0;
|
||||
@@ -1343,7 +1295,7 @@ export const ns: InternalAPI<NSFull> = {
|
||||
},
|
||||
getScriptIncome:
|
||||
(ctx) =>
|
||||
(fn, host, ...args) => {
|
||||
(fn, host?, ...args) => {
|
||||
const ident = helpers.scriptIdentifier(ctx, fn, host, args);
|
||||
const runningScript = helpers.getRunningScript(ctx, ident);
|
||||
if (runningScript == null) {
|
||||
@@ -1361,7 +1313,7 @@ export const ns: InternalAPI<NSFull> = {
|
||||
},
|
||||
getScriptExpGain:
|
||||
(ctx) =>
|
||||
(fn, host, ...args) => {
|
||||
(fn, host?, ...args) => {
|
||||
const ident = helpers.scriptIdentifier(ctx, fn, host, args);
|
||||
const runningScript = helpers.getRunningScript(ctx, ident);
|
||||
if (runningScript == null) {
|
||||
@@ -1425,15 +1377,17 @@ export const ns: InternalAPI<NSFull> = {
|
||||
});
|
||||
});
|
||||
},
|
||||
wget: (ctx) => async (_url, _target, _host) => {
|
||||
wget: (ctx) => async (_url, _target, _host?) => {
|
||||
const url = helpers.string(ctx, "url", _url);
|
||||
const target = helpers.filePath(ctx, "target", _target);
|
||||
const host = _host ? helpers.string(ctx, "hostname", _host) : ctx.workerScript.hostname;
|
||||
const server = helpers.getServer(ctx, host);
|
||||
const [server, host] = helpers.getServer(ctx, _host);
|
||||
if (!target || (!hasTextExtension(target) && !hasScriptExtension(target))) {
|
||||
helpers.log(ctx, () => `Invalid target file: '${target}'. Must be a script or text file.`);
|
||||
return false;
|
||||
}
|
||||
if (!server) {
|
||||
return false;
|
||||
}
|
||||
let response: Response;
|
||||
try {
|
||||
response = await fetch(url);
|
||||
@@ -1495,8 +1449,10 @@ export const ns: InternalAPI<NSFull> = {
|
||||
ctx.workerScript.atExit.set(id, callback);
|
||||
},
|
||||
mv: (ctx) => (_host, _source, _destination) => {
|
||||
const host = helpers.string(ctx, "host", _host);
|
||||
const server = helpers.getServer(ctx, host);
|
||||
const [server, host] = helpers.getServer(ctx, _host);
|
||||
if (!server) {
|
||||
return;
|
||||
}
|
||||
const sourcePath = helpers.filePath(ctx, "source", _source);
|
||||
const destinationPath = helpers.filePath(ctx, "destination", _destination);
|
||||
|
||||
@@ -1559,7 +1515,7 @@ export const ns: InternalAPI<NSFull> = {
|
||||
},
|
||||
dynamicImport: (ctx) => async (value) => {
|
||||
const path = helpers.scriptPath(ctx, "path", value);
|
||||
const server = helpers.getServer(ctx, ctx.workerScript.hostname);
|
||||
const server = ctx.workerScript.getServer();
|
||||
const script = server.getContentFile(path);
|
||||
|
||||
if (!script) throw helpers.errorMessage(ctx, `Script was not found\nPath: ${path}`);
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
renameCloudServer,
|
||||
upgradeCloudServer,
|
||||
} from "../Server/ServerPurchases";
|
||||
import { DeleteServer, AddToAllServers, createUniqueRandomIp } from "../Server/AllServers";
|
||||
import { DeleteServer, AddToAllServers, createUniqueRandomIp, GetServerOrThrow } from "../Server/AllServers";
|
||||
import { safelyCreateUniqueServer } from "../Server/ServerHelpers";
|
||||
import { formatMoney } from "../ui/formatNumber";
|
||||
import { isIPAddress } from "../Types/strings";
|
||||
@@ -195,12 +195,12 @@ export function NetscriptCloud(): InternalAPI<Cloud> {
|
||||
return false;
|
||||
},
|
||||
getServerNames:
|
||||
(ctx) =>
|
||||
() =>
|
||||
(_returnOpts): string[] => {
|
||||
const returnOpts = helpers.hostReturnOptions(_returnOpts);
|
||||
const res: string[] = [];
|
||||
for (const hostname of Player.purchasedServers) {
|
||||
const server = helpers.getServer(ctx, hostname);
|
||||
const server = GetServerOrThrow(hostname);
|
||||
const id = helpers.returnServerID(server, returnOpts);
|
||||
res.push(id);
|
||||
}
|
||||
|
||||
@@ -10,14 +10,18 @@ import { exceptionAlert } from "../utils/helpers/exceptionAlert";
|
||||
import { getEnumHelper } from "../utils/EnumHelper";
|
||||
|
||||
export function NetscriptCodingContract(): InternalAPI<ICodingContract> {
|
||||
const getCodingContract = function (ctx: NetscriptContext, hostname: string, filename: string): CodingContract {
|
||||
const server = helpers.getServer(ctx, hostname);
|
||||
const contract = server.getContract(filename);
|
||||
if (contract == null) {
|
||||
throw helpers.errorMessage(ctx, `Cannot find contract '${filename}' on server '${hostname}'`);
|
||||
const getCodingContract = function (
|
||||
ctx: NetscriptContext,
|
||||
_host: unknown,
|
||||
filename: string,
|
||||
): [CodingContract, BaseServer] {
|
||||
const [server, host] = helpers.getServer(ctx, _host);
|
||||
const contract = server?.getContract(filename);
|
||||
if (server == null || contract == null) {
|
||||
throw helpers.errorMessage(ctx, `Cannot find contract '${filename}' on server '${host}'`);
|
||||
}
|
||||
|
||||
return contract;
|
||||
return [contract, server];
|
||||
};
|
||||
|
||||
function attemptContract(
|
||||
@@ -81,28 +85,22 @@ export function NetscriptCodingContract(): InternalAPI<ICodingContract> {
|
||||
return {
|
||||
attempt: (ctx) => (answer, _filename, _host?) => {
|
||||
const filename = helpers.string(ctx, "filename", _filename);
|
||||
const host = _host ? helpers.string(ctx, "host", _host) : ctx.workerScript.hostname;
|
||||
const contract = getCodingContract(ctx, host, filename);
|
||||
const server = helpers.getServer(ctx, host);
|
||||
const [contract, server] = getCodingContract(ctx, _host, filename);
|
||||
return attemptContract(ctx, server, contract, answer);
|
||||
},
|
||||
getContractType: (ctx) => (_filename, _host?) => {
|
||||
const filename = helpers.string(ctx, "filename", _filename);
|
||||
const host = _host ? helpers.string(ctx, "host", _host) : ctx.workerScript.hostname;
|
||||
const contract = getCodingContract(ctx, host, filename);
|
||||
const [contract] = getCodingContract(ctx, _host, filename);
|
||||
return contract.getType();
|
||||
},
|
||||
getData: (ctx) => (_filename, _host?) => {
|
||||
const filename = helpers.string(ctx, "filename", _filename);
|
||||
const host = _host ? helpers.string(ctx, "host", _host) : ctx.workerScript.hostname;
|
||||
const contract = getCodingContract(ctx, host, filename);
|
||||
const [contract] = getCodingContract(ctx, _host, filename);
|
||||
return structuredClone(contract.getData());
|
||||
},
|
||||
getContract: (ctx) => (_filename, _host?) => {
|
||||
const filename = helpers.string(ctx, "filename", _filename);
|
||||
const host = _host ? helpers.string(ctx, "host", _host) : ctx.workerScript.hostname;
|
||||
const server = helpers.getServer(ctx, host);
|
||||
const contract = getCodingContract(ctx, host, filename);
|
||||
const [contract, server] = getCodingContract(ctx, _host, filename);
|
||||
// asserting type here is required, since it is not feasible to properly type getData
|
||||
return {
|
||||
type: contract.type,
|
||||
@@ -121,20 +119,20 @@ export function NetscriptCodingContract(): InternalAPI<ICodingContract> {
|
||||
},
|
||||
getDescription: (ctx) => (_filename, _host?) => {
|
||||
const filename = helpers.string(ctx, "filename", _filename);
|
||||
const host = _host ? helpers.string(ctx, "host", _host) : ctx.workerScript.hostname;
|
||||
const contract = getCodingContract(ctx, host, filename);
|
||||
const [contract] = getCodingContract(ctx, _host, filename);
|
||||
return contract.getDescription();
|
||||
},
|
||||
getNumTriesRemaining: (ctx) => (_filename, _host?) => {
|
||||
const filename = helpers.string(ctx, "filename", _filename);
|
||||
const host = _host ? helpers.string(ctx, "host", _host) : ctx.workerScript.hostname;
|
||||
const contract = getCodingContract(ctx, host, filename);
|
||||
const [contract] = getCodingContract(ctx, _host, filename);
|
||||
return contract.getMaxNumTries() - contract.tries;
|
||||
},
|
||||
createDummyContract: (ctx) => (_type, _host?) => {
|
||||
const type = getEnumHelper("CodingContractName").nsGetMember(ctx, _type);
|
||||
const host = _host ? helpers.string(ctx, "host", _host) : ctx.workerScript.hostname;
|
||||
const server = helpers.getServer(ctx, host);
|
||||
const [server] = helpers.getServer(ctx, _host);
|
||||
if (server == null) {
|
||||
return null;
|
||||
}
|
||||
return generateDummyContract(type, server);
|
||||
},
|
||||
getContractTypes: () => () => Object.values(CodingContractName),
|
||||
|
||||
@@ -470,16 +470,11 @@ export function NetscriptSingularity(): InternalAPI<ISingularity> {
|
||||
const server = Player.getCurrentServer();
|
||||
cat([filename], server);
|
||||
},
|
||||
connect: (ctx) => (_host) => {
|
||||
connect: (ctx) => (_host?) => {
|
||||
helpers.checkSingularityAccess(ctx);
|
||||
const host = helpers.string(ctx, "host", _host);
|
||||
if (!host) {
|
||||
throw helpers.errorMessage(ctx, `Invalid server: '${host}'`);
|
||||
}
|
||||
|
||||
const target = GetServer(host);
|
||||
const [target, host] = helpers.getServer(ctx, _host);
|
||||
if (target == null) {
|
||||
throw helpers.errorMessage(ctx, `Invalid server: '${host}'`);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Adjacent servers
|
||||
|
||||
@@ -44,7 +44,7 @@ export function NetscriptStanek(): InternalAPI<IStanek> {
|
||||
);
|
||||
}
|
||||
//Charge the fragment
|
||||
const cores = helpers.getServer(ctx, ctx.workerScript.hostname).cpuCores;
|
||||
const cores = ctx.workerScript.getServer().cpuCores;
|
||||
const coreBonus = getCoreBonus(cores);
|
||||
const inBonus = staneksGift.inBonus();
|
||||
const time = inBonus ? 200 : 1000;
|
||||
|
||||
132
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
132
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
@@ -4067,7 +4067,8 @@ export interface CodingContract {
|
||||
*
|
||||
* Generate a dummy contract on the current server with no reward. Used to test various algorithms.
|
||||
*
|
||||
* This function will return null and not generate a contract if the randomized contract name is the same as another contract's name.
|
||||
* This function will return null and not generate a contract if the randomized contract name is the same as another
|
||||
* contract's name or the host is offline.
|
||||
*
|
||||
* @param type - Type of contract to generate
|
||||
* @param host - Hostname/IP of the server containing the contract. Optional. Defaults to the server the calling script is running on.
|
||||
@@ -7060,11 +7061,11 @@ export interface NS {
|
||||
* ```js
|
||||
* let earnedMoney = await ns.hack("foodnstuff");
|
||||
* ```
|
||||
* @param host - Hostname/IP of the target server to hack.
|
||||
* @param host - Hostname/IP of the target server to hack. Optional. Defaults to current server if not provided.
|
||||
* @param opts - Optional parameters for configuring function behavior.
|
||||
* @returns A promise that resolves to the amount of money stolen (which is zero if the hack is unsuccessful).
|
||||
*/
|
||||
hack(host: string, opts?: BasicHGWOptions): Promise<number>;
|
||||
hack(host?: string, opts?: BasicHGWOptions): Promise<number>;
|
||||
|
||||
/**
|
||||
* Spoof money in a server's bank account, increasing the amount available.
|
||||
@@ -7106,11 +7107,11 @@ export interface NS {
|
||||
* let currentMoney = ns.getServerMoneyAvailable("n00dles");
|
||||
* currentMoney *= await ns.grow("n00dles");
|
||||
* ```
|
||||
* @param host - Hostname/IP of the target server to grow.
|
||||
* @param host - Hostname/IP of the target server to grow. Optional. Defaults to current server if not provided.
|
||||
* @param opts - Optional parameters for configuring function behavior.
|
||||
* @returns The total effective multiplier that was applied to the server's money (after both additive and multiplicative growth).
|
||||
*/
|
||||
grow(host: string, opts?: BasicHGWOptions): Promise<number>;
|
||||
grow(host?: string, opts?: BasicHGWOptions): Promise<number>;
|
||||
|
||||
/**
|
||||
* Reduce a server's security level.
|
||||
@@ -7133,11 +7134,11 @@ export interface NS {
|
||||
* let currentSecurity = ns.getServerSecurityLevel("foodnstuff");
|
||||
* currentSecurity -= await ns.weaken("foodnstuff");
|
||||
* ```
|
||||
* @param host - Hostname/IP of the target server to weaken.
|
||||
* @param host - Hostname/IP of the target server to weaken. Optional. Defaults to current server if not provided.
|
||||
* @param opts - Optional parameters for configuring function behavior.
|
||||
* @returns A promise that resolves to the value by which security was reduced.
|
||||
*/
|
||||
weaken(host: string, opts?: BasicHGWOptions): Promise<number>;
|
||||
weaken(host?: string, opts?: BasicHGWOptions): Promise<number>;
|
||||
|
||||
/**
|
||||
* Predict the effect of weaken.
|
||||
@@ -7173,7 +7174,7 @@ export interface NS {
|
||||
* ns.run("noodleHack.js", Math.floor(hackThreads));
|
||||
*
|
||||
* ```
|
||||
* @param host - Hostname of the target server to analyze.
|
||||
* @param host - Hostname/IP of the target server to analyze.
|
||||
* @param hackAmount - Amount of money you want to hack from the server.
|
||||
* @returns The number of threads needed to hack the server for hackAmount money.
|
||||
*/
|
||||
@@ -7206,9 +7207,10 @@ export interface NS {
|
||||
* RAM cost: 1 GB
|
||||
*
|
||||
* Returns the security increase that would occur if a hack with this many threads happened.
|
||||
* The number of threads is limited to the number needed to hack the server's maximum amount of money.
|
||||
*
|
||||
* @param threads - Amount of threads that will be used.
|
||||
* @param host - Hostname/IP of the target server. The number of threads is limited to the number needed to hack the server's maximum amount of money.
|
||||
* @param host - Hostname/IP of the target server. Optional. If unspecified, the threads are not capped.
|
||||
* @returns The security increase.
|
||||
*/
|
||||
hackAnalyzeSecurity(threads: number, host?: string): number;
|
||||
@@ -7225,10 +7227,10 @@ export interface NS {
|
||||
* Like other basic hacking analysis functions, this calculation uses the current status of the player and server.
|
||||
* To calculate using hypothetical server or player status, obtain access to the Formulas API and use {@link HackingFormulas.hackChance | formulas.hacking.hackChance}.
|
||||
*
|
||||
* @param host - Hostname/IP of the target server.
|
||||
* @param host - Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
* @returns The chance you have of successfully hacking the target server.
|
||||
*/
|
||||
hackAnalyzeChance(host: string): number;
|
||||
hackAnalyzeChance(host?: string): number;
|
||||
|
||||
/**
|
||||
* Calculate the number of grow threads needed for a given multiplicative growth factor.
|
||||
@@ -7659,10 +7661,10 @@ export interface NS {
|
||||
* ```js
|
||||
* ns.nuke("foodnstuff");
|
||||
* ```
|
||||
* @param host - Hostname/IP of the target server.
|
||||
* @param host - Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
* @returns True if the player runs the program successfully, and false otherwise.
|
||||
*/
|
||||
nuke(host: string): boolean;
|
||||
nuke(host?: string): boolean;
|
||||
|
||||
/**
|
||||
* Runs BruteSSH.exe on a server.
|
||||
@@ -7675,10 +7677,10 @@ export interface NS {
|
||||
* ```js
|
||||
* ns.brutessh("foodnstuff");
|
||||
* ```
|
||||
* @param host - Hostname/IP of the target server.
|
||||
* @param host - Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
* @returns True if the player runs the program successfully, and false otherwise.
|
||||
*/
|
||||
brutessh(host: string): boolean;
|
||||
brutessh(host?: string): boolean;
|
||||
|
||||
/**
|
||||
* Runs FTPCrack.exe on a server.
|
||||
@@ -7691,10 +7693,10 @@ export interface NS {
|
||||
* ```js
|
||||
* ns.ftpcrack("foodnstuff");
|
||||
* ```
|
||||
* @param host - Hostname/IP of the target server.
|
||||
* @param host - Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
* @returns True if the player runs the program successfully, and false otherwise.
|
||||
*/
|
||||
ftpcrack(host: string): boolean;
|
||||
ftpcrack(host?: string): boolean;
|
||||
|
||||
/**
|
||||
* Runs relaySMTP.exe on a server.
|
||||
@@ -7707,10 +7709,10 @@ export interface NS {
|
||||
* ```js
|
||||
* ns.relaysmtp("foodnstuff");
|
||||
* ```
|
||||
* @param host - Hostname/IP of the target server.
|
||||
* @param host - Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
* @returns True if the player runs the program successfully, and false otherwise.
|
||||
*/
|
||||
relaysmtp(host: string): boolean;
|
||||
relaysmtp(host?: string): boolean;
|
||||
|
||||
/**
|
||||
* Runs HTTPWorm.exe on a server.
|
||||
@@ -7723,10 +7725,10 @@ export interface NS {
|
||||
* ```js
|
||||
* ns.httpworm("foodnstuff");
|
||||
* ```
|
||||
* @param host - Hostname/IP of the target server.
|
||||
* @param host - Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
* @returns True if the player runs the program successfully, and false otherwise.
|
||||
*/
|
||||
httpworm(host: string): boolean;
|
||||
httpworm(host?: string): boolean;
|
||||
|
||||
/**
|
||||
* Runs SQLInject.exe on a server.
|
||||
@@ -7739,10 +7741,10 @@ export interface NS {
|
||||
* ```js
|
||||
* ns.sqlinject("foodnstuff");
|
||||
* ```
|
||||
* @param host - Hostname/IP of the target server.
|
||||
* @param host - Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
* @returns True if the player runs the program successfully, and false otherwise.
|
||||
*/
|
||||
sqlinject(host: string): boolean;
|
||||
sqlinject(host?: string): boolean;
|
||||
|
||||
/**
|
||||
* Start another script on the current server.
|
||||
@@ -7815,7 +7817,7 @@ export interface NS {
|
||||
* ns.exec("foo.js", "foodnstuff", 5, 1, "test");
|
||||
* ```
|
||||
* @param script - Filename of script to execute. This file must already exist on the target server.
|
||||
* @param host - Hostname/IP of the `target server` on which to execute the script.
|
||||
* @param host - Hostname/IP of the target server on which to execute the script.
|
||||
* @param threadOrOptions - Either an integer number of threads for new script, or a {@link RunOptions} object. Threads defaults to 1.
|
||||
* @param args - Additional arguments to pass into the new script that is being run. Note that if any arguments are being passed into the new script, then the third argument threadOrOptions must be filled in with a value.
|
||||
* @returns Returns the PID of a successfully started script, and 0 otherwise.
|
||||
@@ -7914,7 +7916,7 @@ export interface NS {
|
||||
* true if there are any scripts running on the target server.
|
||||
* If no host is defined, it will kill all scripts, where the script is running.
|
||||
*
|
||||
* @param host - Hostname/IP of the server on which to kill all scripts.
|
||||
* @param host - Hostname/IP of the server on which to kill all scripts. Optional. Defaults to current server if not provided.
|
||||
* @param safetyGuard - Skips the script that calls this function
|
||||
* @returns True if any scripts were killed, and false otherwise.
|
||||
*/
|
||||
@@ -8007,10 +8009,10 @@ export interface NS {
|
||||
* ns.nuke("foodnstuff");
|
||||
* }
|
||||
* ```
|
||||
* @param host - Hostname/IP of the target server.
|
||||
* @param host - Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
* @returns True if player has root access to the specified target server, and false otherwise.
|
||||
*/
|
||||
hasRootAccess(host: string): boolean;
|
||||
hasRootAccess(host?: string): boolean;
|
||||
|
||||
/**
|
||||
* Returns a string with the hostname of the server that the script is running on.
|
||||
@@ -8104,10 +8106,10 @@ export interface NS {
|
||||
* ns.getServerMoneyAvailable("foodnstuff");
|
||||
* ns.getServerMoneyAvailable("home"); // Returns player's money
|
||||
* ```
|
||||
* @param host - Hostname/IP of target server.
|
||||
* @param host - Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
* @returns Amount of money available on the server.
|
||||
*/
|
||||
getServerMoneyAvailable(host: string): number;
|
||||
getServerMoneyAvailable(host?: string): number;
|
||||
|
||||
/**
|
||||
* Get the maximum money available on a server.
|
||||
@@ -8116,10 +8118,10 @@ export interface NS {
|
||||
*
|
||||
* Returns the maximum amount of money that can be available on a server.
|
||||
*
|
||||
* @param host - Hostname/IP of target server.
|
||||
* @param host - Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
* @returns Maximum amount of money available on the server.
|
||||
*/
|
||||
getServerMaxMoney(host: string): number;
|
||||
getServerMaxMoney(host?: string): number;
|
||||
|
||||
/**
|
||||
* Get a server growth parameter.
|
||||
@@ -8133,10 +8135,10 @@ export interface NS {
|
||||
* grow function. A higher growth parameter will result in a
|
||||
* higher percentage increase from grow.
|
||||
*
|
||||
* @param host - Hostname/IP of target server.
|
||||
* @param host - Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
* @returns Parameter that affects the percentage by which the server’s money is increased when using the grow function.
|
||||
*/
|
||||
getServerGrowth(host: string): number;
|
||||
getServerGrowth(host?: string): number;
|
||||
|
||||
/**
|
||||
* Get server security level.
|
||||
@@ -8147,19 +8149,19 @@ export interface NS {
|
||||
* level is denoted by a number, typically between 1 and 100
|
||||
* (but it can go above 100).
|
||||
*
|
||||
* @param host - Hostname/IP of target server.
|
||||
* @param host - Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
* @returns Security level of the target server.
|
||||
*/
|
||||
getServerSecurityLevel(host: string): number;
|
||||
getServerSecurityLevel(host?: string): number;
|
||||
|
||||
/**
|
||||
* Returns the minimum security level of the target server.
|
||||
*
|
||||
* @remarks RAM cost: 0.1 GB
|
||||
* @param host - Hostname/IP of target server.
|
||||
* @param host - Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
* @returns Minimum security level of the target server.
|
||||
*/
|
||||
getServerMinSecurityLevel(host: string): number;
|
||||
getServerMinSecurityLevel(host?: string): number;
|
||||
|
||||
/**
|
||||
* Get the base security level of a server.
|
||||
@@ -8168,64 +8170,64 @@ export interface NS {
|
||||
* Returns the base security level of the target server.
|
||||
* For the server's actual security level, use {@link NS.getServerSecurityLevel | ns.getServerSecurityLevel}.
|
||||
*
|
||||
* @param host - Hostname/IP of target server.
|
||||
* @param host - Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
* @returns Base security level of the target server.
|
||||
*/
|
||||
getServerBaseSecurityLevel(host: string): number;
|
||||
getServerBaseSecurityLevel(host?: string): number;
|
||||
|
||||
/**
|
||||
* Get the maximum amount of RAM on a server.
|
||||
* @remarks
|
||||
* RAM cost: 0.05 GB
|
||||
*
|
||||
* @param host - Hostname/IP of the target server.
|
||||
* @param host - Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
* @returns The maximum amount of RAM (GB) a server can have.
|
||||
*/
|
||||
getServerMaxRam(host: string): number;
|
||||
getServerMaxRam(host?: string): number;
|
||||
/**
|
||||
* Get the used RAM on a server.
|
||||
* @remarks
|
||||
* RAM cost: 0.05 GB
|
||||
*
|
||||
* @param host - Hostname/IP of the target server.
|
||||
* @param host - Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
* @returns The amount of used RAM (GB) on the specified server.
|
||||
*/
|
||||
getServerUsedRam(host: string): number;
|
||||
getServerUsedRam(host?: string): number;
|
||||
|
||||
/**
|
||||
* Returns the required hacking level of the target server.
|
||||
*
|
||||
* @remarks RAM cost: 0.1 GB
|
||||
* @param host - Hostname/IP of target server.
|
||||
* @param host - Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
* @returns The required hacking level of the target server.
|
||||
*/
|
||||
getServerRequiredHackingLevel(host: string): number;
|
||||
getServerRequiredHackingLevel(host?: string): number;
|
||||
|
||||
/**
|
||||
* Returns the number of open ports required to successfully run NUKE.exe on the specified server.
|
||||
*
|
||||
* @remarks RAM cost: 0.1 GB
|
||||
* @param host - Hostname/IP of target server.
|
||||
* @param host - Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
* @returns The number of open ports required to successfully run NUKE.exe on the specified server.
|
||||
*/
|
||||
getServerNumPortsRequired(host: string): number;
|
||||
getServerNumPortsRequired(host?: string): number;
|
||||
|
||||
/**
|
||||
* Given a hostname, returns its IP address; or given an IP address, returns its hostname.
|
||||
*
|
||||
* @remarks RAM cost: 0.05 GB
|
||||
* @param host - Hostname/IP of target server.
|
||||
* @param host - Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
*/
|
||||
dnsLookup(host: string): string;
|
||||
dnsLookup(host?: string): string;
|
||||
|
||||
/**
|
||||
* Returns a boolean denoting whether or not the specified server exists.
|
||||
*
|
||||
* @remarks RAM cost: 0.1 GB
|
||||
* @param host - Hostname/IP of target server.
|
||||
* @param host - Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
* @returns True if the specified server exists, and false otherwise.
|
||||
*/
|
||||
serverExists(host: string): boolean;
|
||||
serverExists(host?: string): boolean;
|
||||
|
||||
/**
|
||||
* Check if a file exists.
|
||||
@@ -8515,10 +8517,10 @@ export interface NS {
|
||||
* ns.scriptRunning("foo.js", ns.getHostname());
|
||||
* ```
|
||||
* @param script - Filename of script to check. This is case-sensitive.
|
||||
* @param host - Hostname/IP of target server.
|
||||
* @param host - Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
* @returns True if the specified script is running, and false otherwise.
|
||||
*/
|
||||
scriptRunning(script: string, host: string): boolean;
|
||||
scriptRunning(script: string, host?: string): boolean;
|
||||
|
||||
/**
|
||||
* Kill all scripts with a filename.
|
||||
@@ -8529,10 +8531,10 @@ export interface NS {
|
||||
* regardless of arguments.
|
||||
*
|
||||
* @param script - Filename of script to kill. This is case-sensitive.
|
||||
* @param host - Hostname/IP of target server.
|
||||
* @param host - Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
* @returns True if one or more scripts were successfully killed, and false if none were.
|
||||
*/
|
||||
scriptKill(script: string, host: string): boolean;
|
||||
scriptKill(script: string, host?: string): boolean;
|
||||
|
||||
/**
|
||||
* Returns the current script name.
|
||||
@@ -8565,10 +8567,10 @@ export interface NS {
|
||||
* Returns the amount of time in milliseconds it takes to execute the {@link NS.hack | hack} Netscript function on the target server.
|
||||
* The required time is increased by the security level of the target server and decreased by the player's hacking level.
|
||||
*
|
||||
* @param host - Hostname/IP of target server.
|
||||
* @param host - Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
* @returns Returns the amount of time in milliseconds it takes to execute the {@link NS.hack | hack} Netscript function.
|
||||
*/
|
||||
getHackTime(host: string): number;
|
||||
getHackTime(host?: string): number;
|
||||
|
||||
/**
|
||||
* Get the execution time of a grow() call.
|
||||
@@ -8578,10 +8580,10 @@ export interface NS {
|
||||
* Returns the amount of time in milliseconds it takes to execute the grow Netscript function on the target server.
|
||||
* The required time is increased by the security level of the target server and decreased by the player's hacking level.
|
||||
*
|
||||
* @param host - Hostname/IP of target server.
|
||||
* @param host - Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
* @returns Returns the amount of time in milliseconds it takes to execute the grow Netscript function.
|
||||
*/
|
||||
getGrowTime(host: string): number;
|
||||
getGrowTime(host?: string): number;
|
||||
|
||||
/**
|
||||
* Get the execution time of a weaken() call.
|
||||
@@ -8591,10 +8593,10 @@ export interface NS {
|
||||
* Returns the amount of time in milliseconds it takes to execute the {@link NS.weaken | weaken} Netscript function on the target server.
|
||||
* The required time is increased by the security level of the target server and decreased by the player's hacking level.
|
||||
*
|
||||
* @param host - Hostname/IP of target server.
|
||||
* @param host - Hostname/IP of the target server. Optional. Defaults to current server if not provided.
|
||||
* @returns Returns the amount of time in milliseconds it takes to execute the {@link NS.weaken | weaken} Netscript function.
|
||||
*/
|
||||
getWeakenTime(host: string): number;
|
||||
getWeakenTime(host?: string): number;
|
||||
|
||||
/**
|
||||
* Get the income of all scripts.
|
||||
@@ -8622,11 +8624,11 @@ export interface NS {
|
||||
* those same arguments in the same order in this function call.
|
||||
*
|
||||
* @param script - Filename of script.
|
||||
* @param host - Hostname/IP of the server on which script is running.
|
||||
* @param host - Hostname/IP of the server on which the script is running. Optional. Defaults to current server if not provided.
|
||||
* @param args - Arguments that the script is running with.
|
||||
* @returns Amount of income the specified script generates while online.
|
||||
*/
|
||||
getScriptIncome(script: string, host: string, ...args: ScriptArg[]): number;
|
||||
getScriptIncome(script: string, host?: string, ...args: ScriptArg[]): number;
|
||||
|
||||
/**
|
||||
* Get the exp gain of all scripts.
|
||||
@@ -8650,11 +8652,11 @@ export interface NS {
|
||||
* scripts by running the function with no arguments.
|
||||
*
|
||||
* @param script - Filename of script.
|
||||
* @param host - Hostname/IP of the server on which script is running.
|
||||
* @param host - Hostname/IP of the server on which the script is running. Optional. Defaults to current server if not provided.
|
||||
* @param args - Arguments that the script is running with.
|
||||
* @returns Amount of hacking experience the specified script generates while online.
|
||||
*/
|
||||
getScriptExpGain(script: string, host: string, ...args: ScriptArg[]): number;
|
||||
getScriptExpGain(script: string, host?: string, ...args: ScriptArg[]): number;
|
||||
|
||||
/**
|
||||
* Format a string.
|
||||
|
||||
@@ -534,10 +534,10 @@ describe("Password Tests", () => {
|
||||
expect(isNumber(+server.password)).toBe(true);
|
||||
expect(isNumber(+server.passwordHintData)).toBe(true);
|
||||
|
||||
DarknetState.serverState[server.hostname] = {
|
||||
DarknetState.serverState.set(server.hostname, {
|
||||
serverLogs: [],
|
||||
authenticatedPIDs: [],
|
||||
};
|
||||
});
|
||||
const nonDivisibleResult = getAuthResult(server, `${server.password + 1}`, 1);
|
||||
expect(nonDivisibleResult.response.code).toBe(ResponseCodeEnum.AuthFailure);
|
||||
expect(nonDivisibleResult.response.message).toContain("not divisible");
|
||||
@@ -741,7 +741,7 @@ describe("Darknet server name generator", () => {
|
||||
}
|
||||
});
|
||||
test("generateDarknetServerName", () => {
|
||||
DarknetState.offlineServers = [];
|
||||
DarknetState.offlineServers = new Set();
|
||||
for (let i = 0; i < 1000; ++i) {
|
||||
validatePath(generateDarknetServerName());
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { AugmentationName, CompletedProgramName } from "@enums";
|
||||
import { Player } from "@player";
|
||||
import type { DarknetResult } from "@nsdefs";
|
||||
import { PlayerOwnedAugmentation } from "../../../src/Augmentation/PlayerOwnedAugmentation";
|
||||
import { addCacheToServer } from "../../../src/DarkNet/effects/cacheFiles";
|
||||
import { getDarkscapeNavigator } from "../../../src/DarkNet/effects/effects";
|
||||
@@ -35,8 +36,9 @@ import type { Result } from "@nsdefs";
|
||||
import { assertNonNullish } from "../../../src/utils/TypeAssertion";
|
||||
|
||||
const hostnameOfNonExistentServer = "fake-server";
|
||||
const errorMessageForNonExistentServer = `Server ${hostnameOfNonExistentServer} does not exist.`;
|
||||
const errorMessageForNonExistentServer = `Invalid host: '${hostnameOfNonExistentServer}'`;
|
||||
const hostnameForOfflineServer = "darknet-offline-server";
|
||||
const ipForOfflineServer = "0.0.0.0";
|
||||
|
||||
fixDoImportIssue();
|
||||
|
||||
@@ -45,7 +47,7 @@ beforeAll(() => {
|
||||
initStockMarket();
|
||||
});
|
||||
beforeEach(() => {
|
||||
DarknetState.offlineServers = [];
|
||||
DarknetState.offlineServers = new Set();
|
||||
setupBasicTestingEnvironment({ purchasePServer: true, purchaseHacknetServer: true });
|
||||
Player.sourceFiles.set(15, 1);
|
||||
getDarkscapeNavigator();
|
||||
@@ -1060,81 +1062,96 @@ describe("Non-darkweb darknet server", () => {
|
||||
|
||||
describe("Offline darknet server", () => {
|
||||
beforeEach(() => {
|
||||
DarknetState.offlineServers.push(hostnameForOfflineServer);
|
||||
DarknetState.offlineServers.add(hostnameForOfflineServer);
|
||||
DarknetState.offlineServers.add(ipForOfflineServer);
|
||||
});
|
||||
test("authenticate from home", async () => {
|
||||
const ns = getNsOnHome();
|
||||
const result = await ns.dnet.authenticate(hostnameForOfflineServer, "");
|
||||
async function testIpAndHostname(func: (host: string) => Promise<DarknetResult>) {
|
||||
let result = await func(hostnameForOfflineServer);
|
||||
expect(result.success).toStrictEqual(false);
|
||||
expect(result.code).toStrictEqual(ResponseCodeEnum.ServiceUnavailable);
|
||||
|
||||
result = await func(ipForOfflineServer);
|
||||
expect(result.success).toStrictEqual(false);
|
||||
expect(result.code).toStrictEqual(ResponseCodeEnum.ServiceUnavailable);
|
||||
}
|
||||
test("authenticate from home", async () => {
|
||||
const ns = getNsOnHome();
|
||||
await testIpAndHostname((host) => ns.dnet.authenticate(host, ""));
|
||||
});
|
||||
test("authenticate itself", async () => {
|
||||
const ns = getNsOnDarkWeb();
|
||||
const result = await ns.dnet.authenticate(hostnameForOfflineServer, "");
|
||||
expect(result.success).toStrictEqual(false);
|
||||
expect(result.code).toStrictEqual(ResponseCodeEnum.ServiceUnavailable);
|
||||
await testIpAndHostname((host) => ns.dnet.authenticate(host, ""));
|
||||
});
|
||||
test("connectToSession from home", () => {
|
||||
test("connectToSession from home", async () => {
|
||||
const ns = getNsOnHome();
|
||||
const result = ns.dnet.connectToSession(hostnameForOfflineServer, "");
|
||||
expect(result.success).toStrictEqual(false);
|
||||
expect(result.code).toStrictEqual(ResponseCodeEnum.ServiceUnavailable);
|
||||
await testIpAndHostname((host) => Promise.resolve(ns.dnet.connectToSession(host, "")));
|
||||
});
|
||||
test("heartbleed from home", async () => {
|
||||
const ns = getNsOnHome();
|
||||
const result = await ns.dnet.heartbleed(hostnameForOfflineServer);
|
||||
expect(result.success).toStrictEqual(false);
|
||||
expect(result.code).toStrictEqual(ResponseCodeEnum.ServiceUnavailable);
|
||||
await testIpAndHostname((host) => ns.dnet.heartbleed(host));
|
||||
});
|
||||
test("getServer", () => {
|
||||
const ns = getNsOnDarkWeb();
|
||||
const server = ns.getServer(hostnameForOfflineServer);
|
||||
if (!("isOnline" in server)) {
|
||||
throw new Error("getServer does not return DarknetServerData");
|
||||
}
|
||||
expect(server.isOnline).toStrictEqual(false);
|
||||
let server = ns.getServer(hostnameForOfflineServer);
|
||||
expect(server).toHaveProperty("isOnline", false);
|
||||
expect(server.hostname).toBe(hostnameForOfflineServer);
|
||||
expect(server.ip).toBe("");
|
||||
|
||||
server = ns.getServer(ipForOfflineServer);
|
||||
expect(server).toHaveProperty("isOnline", false);
|
||||
expect(server.hostname).toBe("");
|
||||
expect(server.ip).toBe(ipForOfflineServer);
|
||||
});
|
||||
test("getServerAuthDetails", () => {
|
||||
const ns = getNsOnDarkWeb();
|
||||
const authDetails = ns.dnet.getServerAuthDetails(hostnameForOfflineServer);
|
||||
let authDetails = ns.dnet.getServerAuthDetails(hostnameForOfflineServer);
|
||||
expect(authDetails.isOnline).toStrictEqual(false);
|
||||
|
||||
authDetails = ns.dnet.getServerAuthDetails(ipForOfflineServer);
|
||||
expect(authDetails.isOnline).toStrictEqual(false);
|
||||
});
|
||||
test("packetCapture from home", async () => {
|
||||
const ns = getNsOnHome();
|
||||
const result = await ns.dnet.packetCapture(hostnameForOfflineServer);
|
||||
expect(result.success).toStrictEqual(false);
|
||||
expect(result.code).toStrictEqual(ResponseCodeEnum.ServiceUnavailable);
|
||||
await testIpAndHostname((host) => ns.dnet.packetCapture(host));
|
||||
});
|
||||
test("induceServerMigration", async () => {
|
||||
const ns = getNsOnDarkWeb();
|
||||
const result = await ns.dnet.induceServerMigration(hostnameForOfflineServer);
|
||||
expect(result.success).toStrictEqual(false);
|
||||
expect(result.code).toStrictEqual(ResponseCodeEnum.ServiceUnavailable);
|
||||
await testIpAndHostname((host) => ns.dnet.induceServerMigration(host));
|
||||
});
|
||||
test("isDarknetServer", () => {
|
||||
const ns = getNsOnDarkWeb();
|
||||
const result = ns.dnet.isDarknetServer(hostnameForOfflineServer);
|
||||
let result = ns.dnet.isDarknetServer(hostnameForOfflineServer);
|
||||
expect(result).toStrictEqual(false);
|
||||
|
||||
result = ns.dnet.isDarknetServer(ipForOfflineServer);
|
||||
expect(result).toStrictEqual(false);
|
||||
});
|
||||
test("memoryReallocation", async () => {
|
||||
const ns = getNsOnDarkWeb();
|
||||
const result = await ns.dnet.memoryReallocation(hostnameForOfflineServer);
|
||||
expect(result.success).toStrictEqual(false);
|
||||
expect(result.code).toStrictEqual(ResponseCodeEnum.ServiceUnavailable);
|
||||
await testIpAndHostname((host) => ns.dnet.memoryReallocation(host));
|
||||
});
|
||||
test("getBlockedRam", () => {
|
||||
const ns = getNsOnDarkWeb();
|
||||
const result = ns.dnet.getBlockedRam(hostnameForOfflineServer);
|
||||
let result = ns.dnet.getBlockedRam(hostnameForOfflineServer);
|
||||
expect(result).toStrictEqual(0);
|
||||
|
||||
result = ns.dnet.getBlockedRam(ipForOfflineServer);
|
||||
expect(result).toStrictEqual(0);
|
||||
});
|
||||
test("getDepth", () => {
|
||||
const ns = getNsOnDarkWeb();
|
||||
const result = ns.dnet.getDepth(hostnameForOfflineServer);
|
||||
let result = ns.dnet.getDepth(hostnameForOfflineServer);
|
||||
expect(result).toStrictEqual(-1);
|
||||
|
||||
result = ns.dnet.getDepth(ipForOfflineServer);
|
||||
expect(result).toStrictEqual(-1);
|
||||
});
|
||||
test("getServerRequiredCharismaLevel", () => {
|
||||
const ns = getNsOnDarkWeb();
|
||||
const result = ns.dnet.getServerRequiredCharismaLevel(hostnameForOfflineServer);
|
||||
let result = ns.dnet.getServerRequiredCharismaLevel(hostnameForOfflineServer);
|
||||
expect(result).toStrictEqual(-1);
|
||||
|
||||
result = ns.dnet.getServerRequiredCharismaLevel(ipForOfflineServer);
|
||||
expect(result).toStrictEqual(-1);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user