diff --git a/markdown/bitburner.darknet.unleashstormseed.md b/markdown/bitburner.darknet.unleashstormseed.md
index 274faa2c6..276eea6cb 100644
--- a/markdown/bitburner.darknet.unleashstormseed.md
+++ b/markdown/bitburner.darknet.unleashstormseed.md
@@ -17,7 +17,7 @@ unleashStormSeed(): DarknetResult;
[DarknetResult](./bitburner.darknetresult.md)
-A promise that resolves to a [DarknetResult](./bitburner.darknetresult.md) object.
+A [DarknetResult](./bitburner.darknetresult.md) object.
## Remarks
diff --git a/markdown/bitburner.ns.getserverusedram.md b/markdown/bitburner.ns.getserverusedram.md
index 85bf28dff..9c3845b18 100644
--- a/markdown/bitburner.ns.getserverusedram.md
+++ b/markdown/bitburner.ns.getserverusedram.md
@@ -4,7 +4,7 @@
## NS.getServerUsedRam() method
-Get the used RAM on a server.
+Get the used RAM on a server. This includes ram used by running scripts as well as blocked ram on darknet servers.
**Signature:**
diff --git a/markdown/bitburner.ns.md b/markdown/bitburner.ns.md
index 43c291e42..83d3074f3 100644
--- a/markdown/bitburner.ns.md
+++ b/markdown/bitburner.ns.md
@@ -1037,7 +1037,7 @@ Get server security level.
-Get the used RAM on a server.
+Get the used RAM on a server. This includes ram used by running scripts as well as blocked ram on darknet servers.
|
diff --git a/markdown/bitburner.ns.scp.md b/markdown/bitburner.ns.scp.md
index d625135d1..5f7f5e622 100644
--- a/markdown/bitburner.ns.scp.md
+++ b/markdown/bitburner.ns.scp.md
@@ -112,5 +112,5 @@ const server = ns.args[0];
const files = ["hack.js", "weaken.js", "grow.js"];
ns.scp(files, server, "home");
```
-For password-protected servers (such as darknet servers), a session must be established with the destination server before using this function.
+For password-protected servers (such as darknet servers), a session must be established with the destination server before using this function. (The source server does not require a session.)
diff --git a/src/DarkNet/controllers/NetworkGenerator.ts b/src/DarkNet/controllers/NetworkGenerator.ts
index e0e8f1add..957f5172b 100644
--- a/src/DarkNet/controllers/NetworkGenerator.ts
+++ b/src/DarkNet/controllers/NetworkGenerator.ts
@@ -181,17 +181,19 @@ export const addRandomConnections = (server: DarknetServer) => {
const x = server.depth;
const y = server.leftOffset;
const horizontalNeighbors = getNeighborsOnRow(x, y);
+ const lateralConnectionChance = HORIZONTAL_CONNECTION_CHANCE * (1.1 - server.depth * 0.01);
horizontalNeighbors.forEach((neighbor) => {
- if (Math.random() < HORIZONTAL_CONNECTION_CHANCE) {
+ if (Math.random() < lateralConnectionChance) {
connectServers(server, neighbor);
}
});
const serversAbove = getServersOnRowAbove(x);
const serversBelow = getServersOnRowBelow(x);
+ const verticalConnectionChance = VERTICAL_CONNECTION_CHANCE * (1.1 - server.depth * 0.01);
[...serversAbove, ...serversBelow].forEach((neighbor) => {
const distance = Math.abs(neighbor.depth ?? x - x) + 1;
- if (Math.random() < VERTICAL_CONNECTION_CHANCE / distance) {
+ if (Math.random() < verticalConnectionChance / distance) {
connectServers(server, neighbor);
}
});
diff --git a/src/DarkNet/controllers/NetworkMovement.ts b/src/DarkNet/controllers/NetworkMovement.ts
index 1e00b8750..e40ab05c0 100644
--- a/src/DarkNet/controllers/NetworkMovement.ts
+++ b/src/DarkNet/controllers/NetworkMovement.ts
@@ -111,7 +111,7 @@ export const mutateDarknet = (): void => {
restartRandomServer();
}
- if (Math.random() < 0.5) {
+ if (Math.random() < 0.3) {
moveRandomDarknetServers(3);
}
diff --git a/src/DarkNet/effects/effects.ts b/src/DarkNet/effects/effects.ts
index 59a172595..fbfff3dca 100644
--- a/src/DarkNet/effects/effects.ts
+++ b/src/DarkNet/effects/effects.ts
@@ -62,22 +62,24 @@ export const handleFailedAuth = (server: DarknetServer, threads: number) => {
* @param person - the player's character
* @param attemptedPassword - the password being attempted
* @param threads - the number of threads used for the password attempt (which speeds up the process)
+ * @param linear - if true, the time scaling is linear with the number of threads instead of having diminishing returns
*/
export const calculateAuthenticationTime = (
darknetServerData: DarknetServerData,
person: IPerson = Player,
threads = 1,
attemptedPassword = "",
+ linear = false,
) => {
const chaRequired = darknetServerData.requiredCharismaSkill;
const difficulty = darknetServerData.difficulty;
const baseDiff = (difficulty + 1) * 100;
const diffFactor = 5;
- const baseTime = 500;
+ const baseTime = 850;
- const threadsFactor = 1 / (1 + 0.2 * (threads - 1));
- const skillFactor = (diffFactor * chaRequired + baseDiff) / (person.skills.charisma + 100);
+ const threadsFactor = 1 / (linear ? threads : 1 + 0.2 * (threads - 1));
+ const skillFactor = (diffFactor * chaRequired + baseDiff) / (person.skills.charisma + 150);
const backdoorFactor = getBackdoorAuthTimeDebuff();
const applyUnderleveledFactor = person.skills.charisma <= chaRequired && darknetServerData.depth > 1;
const underleveledFactor = applyUnderleveledFactor ? 1.5 + (chaRequired + 50) / (person.skills.charisma + 50) : 1;
@@ -128,10 +130,9 @@ export const getMultiplierFromCharisma = (scalar = 1) => {
);
};
-// TODO: balance xp gain
export const calculatePasswordAttemptChaGain = (server: DarknetServerData, threads: number = 1, success = false) => {
const baseXpGain = 3;
- const difficultyBase = 1.12;
+ const difficultyBase = 0.8;
const xpGain = baseXpGain + difficultyBase ** server.difficulty;
const alreadyHackedMult = server.hasAdminRights ? 0.2 : 1;
const successMult = success && !server.hasAdminRights ? 10 : 1;
diff --git a/src/DarkNet/models/packetSniffing.ts b/src/DarkNet/models/packetSniffing.ts
index 3f40ec04e..488e7bf71 100644
--- a/src/DarkNet/models/packetSniffing.ts
+++ b/src/DarkNet/models/packetSniffing.ts
@@ -4,7 +4,7 @@ import { generateDarknetServerName, isPasswordResponse, type PasswordResponse }
import { LocationName } from "@enums";
import { getServerState, LogEntry } from "./DarknetState";
import { ModelIds } from "../Enums";
-import { getDarknetServer } from "../utils/darknetServerUtils";
+import { getDarknetServer, getDarknetServerOrThrow } from "../utils/darknetServerUtils";
import { getAllMovableDarknetServers } from "../utils/darknetNetworkUtils";
import { getExactCorrectChars, getTwoCharsInPassword } from "../utils/darknetAuthUtils";
import type { DarknetServer } from "../../Server/DarknetServer";
@@ -200,8 +200,8 @@ const getLogNoise = (server: DarknetServer, logDate: Date): LogEntry => {
return log(`--${randomServer.password}--`);
}
- if (server.modelId === ModelIds.packetSniffer && Math.random() < 0.5 / (server.difficulty + 1)) {
- return log("Authentication successful: " + server.password);
+ if (server.modelId === ModelIds.packetSniffer && Math.random() < 0.7 - server.difficulty * 0.01) {
+ return addPacketSnifferNoise(server);
}
return log(`${logDate.toLocaleTimeString()}: ${server.hostname} - heartbeat check (alive)`);
@@ -212,6 +212,18 @@ const log = (message: string, pid = -1) => ({
pid,
});
+const addPacketSnifferNoise = (server: DarknetServer) => {
+ const connectedServers = server.serversOnNetwork;
+ // If the server becomes disconnected while the UI is open and has no neighbors but still
+ // has logs being populated, fall back to showing the current password
+ if (Math.random() < 0.3 || connectedServers.length === 0) {
+ return log(`Logging in with passcode: ${server.password} ...`);
+ }
+ const randomServerName = connectedServers[Math.floor(Math.random() * connectedServers.length)];
+ const randomServer = getDarknetServerOrThrow(randomServerName);
+ return log(`Connecting to ${randomServer.hostname}:${randomServer.password} ...`);
+};
+
export const getMostRecentAuthLog = (hostname: string) => {
for (const log of getServerState(hostname).serverLogs) {
if (!isPasswordResponse(log.message)) {
diff --git a/src/DarkNet/utils/darknetNetworkUtils.ts b/src/DarkNet/utils/darknetNetworkUtils.ts
index 8415598f9..d330b3b60 100644
--- a/src/DarkNet/utils/darknetNetworkUtils.ts
+++ b/src/DarkNet/utils/darknetNetworkUtils.ts
@@ -4,11 +4,13 @@ import { AIR_GAP_DEPTH, MS_PER_MUTATION_PER_ROW, NET_WIDTH } from "../Enums";
import { GetAllServers } from "../../Server/AllServers";
import { getNetDepth } from "../effects/labyrinth";
import { CONSTANTS } from "../../Constants";
+import { Player } from "@player";
export const getDarknetCyclesPerMutation = () => {
const depth = getNetDepth();
const cycleRate = MS_PER_MUTATION_PER_ROW / CONSTANTS.MilliPerCycle;
- return cycleRate / depth;
+ const rateMultiplier = Player.bitNodeN !== 15 ? 2 : 1;
+ return (rateMultiplier * cycleRate) / depth;
};
export const getAllOpenPositions = (minDepth: number, maxDepth: number): [number, number][] => {
diff --git a/src/NetscriptFunctions/Darknet.ts b/src/NetscriptFunctions/Darknet.ts
index 3489a0504..7c41332d5 100644
--- a/src/NetscriptFunctions/Darknet.ts
+++ b/src/NetscriptFunctions/Darknet.ts
@@ -425,7 +425,8 @@ export function NetscriptDarknet(): InternalAPI {
}
const server = serverCheck.server;
- const networkDelay = calculateAuthenticationTime(server, Player, ctx.workerScript.scriptRef.threads) * 4;
+ const networkDelay =
+ calculateAuthenticationTime(server, Player, ctx.workerScript.scriptRef.threads, "", true) * 4;
const xp = formatNumber(calculatePasswordAttemptChaGain(server, ctx.workerScript.scriptRef.threads), 1);
logger(ctx)(`Captured some outgoing transmissions from ${server.hostname}. (Gained ${xp} cha xp)`);
diff --git a/src/ScriptEditor/NetscriptDefinitions.d.ts b/src/ScriptEditor/NetscriptDefinitions.d.ts
index 26f9afd2f..b0cbeac96 100644
--- a/src/ScriptEditor/NetscriptDefinitions.d.ts
+++ b/src/ScriptEditor/NetscriptDefinitions.d.ts
@@ -4619,7 +4619,7 @@ export interface Darknet {
* @remarks
* RAM cost: 0.1 GB
*
- * @returns A promise that resolves to a {@link DarknetResult} object.
+ * @returns A {@link DarknetResult} object.
*/
unleashStormSeed(): DarknetResult;
@@ -7953,7 +7953,7 @@ export interface NS {
* ns.scp(files, server, "home");
* ```
*
- * For password-protected servers (such as darknet servers), a session must be established with the destination server before using this function.
+ * For password-protected servers (such as darknet servers), a session must be established with the destination server before using this function. (The source server does not require a session.)
*
* @param files - Filename or an array of filenames of script/literature files to copy. Note that if a file is located in a subdirectory, the filename must include the leading `/`.
* @param destination - Hostname/IP of the destination server, which is the server to which the file will be copied.
@@ -8185,7 +8185,7 @@ export interface NS {
*/
getServerMaxRam(host?: string): number;
/**
- * Get the used RAM on a server.
+ * Get the used RAM on a server. This includes ram used by running scripts as well as blocked ram on darknet servers.
* @remarks
* RAM cost: 0.05 GB
*
diff --git a/test/jest/Netscript/Darknet.test.ts b/test/jest/Netscript/Darknet.test.ts
index ae91f3779..15da05e4a 100644
--- a/test/jest/Netscript/Darknet.test.ts
+++ b/test/jest/Netscript/Darknet.test.ts
@@ -17,7 +17,7 @@ import {
} from "../Utilities";
import type { ScriptFilePath } from "../../../src/Paths/ScriptFilePath";
import { DarknetState, getServerState, triggerNextUpdate } from "../../../src/DarkNet/models/DarknetState";
-import { getDarknetServerOrThrow } from "../../../src/DarkNet/utils/darknetServerUtils";
+import { getDarknetServer, getDarknetServerOrThrow } from "../../../src/DarkNet/utils/darknetServerUtils";
import { ModelIds, ResponseCodeEnum } from "../../../src/DarkNet/Enums";
import { getAllMovableDarknetServers } from "../../../src/DarkNet/utils/darknetNetworkUtils";
import { expectRunningOnDarknetServer } from "../../../src/DarkNet/effects/offlineServerHandling";
@@ -878,9 +878,19 @@ describe("Non-darkweb darknet server", () => {
test("authenticate from darkweb", async () => {
const ns = getNsOnDarkWeb();
const target = getFirstDarknetServerAdjacentToDarkWeb();
- const result = await ns.dnet.authenticate(target, getDarknetServerOrThrow(target).password);
- expect(result.success).toStrictEqual(true);
+ const server = getDarknetServerOrThrow(target);
+ const result = await ns.dnet.authenticate(target, server.password);
+ // Logging details for debugging flaky test
+ if (!result.success) {
+ console.log("Server details grabbed before auth:");
+ console.log(server);
+ console.log("result:");
+ console.log(result);
+ console.log("currentServerDetails:");
+ console.log(getDarknetServer(target));
+ }
expect(result.code).toStrictEqual(ResponseCodeEnum.Success);
+ expect(result.success).toStrictEqual(true);
});
test("authenticate itself", async () => {
const ns = getNsOnNonDarkwebDarknetServer();