mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2026-04-26 03:00:56 +02:00
DARKNET: Darkweb Expansion Project & Bitnode (#2139)
This is BN15. It is a really big change; see the PR for all the details.
This commit is contained in:
committed by
GitHub
parent
a674633f6c
commit
6073964768
@@ -0,0 +1,170 @@
|
||||
import { AddToAllServers, createUniqueRandomIp, GetServer } from "../../Server/AllServers";
|
||||
import {
|
||||
commonPasswordDictionary,
|
||||
connectors,
|
||||
l33t,
|
||||
loreNames,
|
||||
presetNames,
|
||||
ServerNamePrefixes,
|
||||
ServerNameSuffixes,
|
||||
} from "./dictionaryData";
|
||||
import { getLabyrinthDetails } from "../effects/labyrinth";
|
||||
import { DarknetServer } from "../../Server/DarknetServer";
|
||||
import type { DarknetResponseCode } from "@nsdefs";
|
||||
import type { MinigamesType } from "../Enums";
|
||||
import { DarknetState } from "./DarknetState";
|
||||
import { getRamBlock } from "../effects/ramblock";
|
||||
import { hasFullDarknetAccess } from "../effects/effects";
|
||||
import { getFriendlyType, TypeAssertionError } from "../../utils/TypeAssertion";
|
||||
|
||||
export type PasswordResponse = {
|
||||
code: DarknetResponseCode;
|
||||
passwordAttempted: string;
|
||||
passwordExpected?: string;
|
||||
message: string;
|
||||
data?: string;
|
||||
};
|
||||
|
||||
export function isPasswordResponse(v: unknown): v is PasswordResponse {
|
||||
return (
|
||||
v != null &&
|
||||
typeof v === "object" &&
|
||||
"code" in v &&
|
||||
"passwordAttempted" in v &&
|
||||
"message" in v &&
|
||||
typeof v.passwordAttempted === "string"
|
||||
);
|
||||
}
|
||||
|
||||
export function assertPasswordResponse(v: unknown): asserts v is PasswordResponse {
|
||||
const type = getFriendlyType(v);
|
||||
if (!isPasswordResponse(v)) {
|
||||
console.error("The value is not a PasswordResponse. Value:", v);
|
||||
throw new TypeAssertionError(`The value is not a PasswordResponse. Its type is ${type}.`, type);
|
||||
}
|
||||
}
|
||||
|
||||
export type DarknetServerOptions = {
|
||||
password: string;
|
||||
modelId: MinigamesType;
|
||||
staticPasswordHint: string;
|
||||
passwordHintData?: string;
|
||||
difficulty: number;
|
||||
depth: number;
|
||||
leftOffset: number;
|
||||
};
|
||||
|
||||
export const DnetServerBuilder = (options: DarknetServerOptions, name = generateDarknetServerName()): DarknetServer => {
|
||||
const maxRam = 16 * 2 ** Math.floor(options.difficulty / 4);
|
||||
const ramBlock = getRamBlock(maxRam);
|
||||
|
||||
const labDetails = getLabyrinthDetails();
|
||||
const labDifficulty = labDetails.cha;
|
||||
const depth = options.difficulty;
|
||||
const depthScaling = depth < 2 ? depth * 10 : (depth / labDetails.depth) ** 1.5 * labDifficulty * 0.85;
|
||||
const levelVariance = (Math.random() * 3 - 1) * depth;
|
||||
const requiredLevel = Math.max(Math.floor(depthScaling + levelVariance), 1);
|
||||
|
||||
const server = new DarknetServer({
|
||||
hostname: name,
|
||||
ip: createUniqueRandomIp(),
|
||||
maxRam,
|
||||
password: options.password,
|
||||
modelId: options.modelId,
|
||||
staticPasswordHint: options.staticPasswordHint,
|
||||
passwordHintData: options.passwordHintData ?? "",
|
||||
difficulty: options.difficulty,
|
||||
depth: options.depth,
|
||||
leftOffset: options.leftOffset,
|
||||
hasStasisLink: false,
|
||||
blockedRam: ramBlock,
|
||||
logTrafficInterval: 1 + 30 * 0.9 ** options.difficulty,
|
||||
requiredCharismaSkill: requiredLevel,
|
||||
isStationary: false,
|
||||
});
|
||||
server.updateRamUsed(ramBlock);
|
||||
removeFromOfflineServers(name);
|
||||
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)];
|
||||
}
|
||||
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)];
|
||||
}
|
||||
|
||||
if (Math.random() < 0.2) {
|
||||
return loreNames[Math.floor(Math.random() * loreNames.length)];
|
||||
}
|
||||
|
||||
if (Math.random() < 0.3) {
|
||||
return presetNames[Math.floor(Math.random() * presetNames.length)];
|
||||
}
|
||||
|
||||
const prefix = ServerNamePrefixes[Math.floor(Math.random() * ServerNamePrefixes.length)];
|
||||
const suffix = ServerNameSuffixes[Math.floor(Math.random() * ServerNameSuffixes.length)];
|
||||
const connector = connectors[Math.floor(Math.random() * connectors.length)];
|
||||
return `${prefix}${connector}${suffix}`;
|
||||
};
|
||||
|
||||
const decorateName = (name: string): string => {
|
||||
let updatedName = name;
|
||||
let count = 0;
|
||||
do {
|
||||
if (count++ > 20) {
|
||||
// Just in case we hit a lot of the same name mutations, or if the player
|
||||
// messes with Math.random(), prevent an infinite loop
|
||||
updatedName += `/T${Date.now()}`;
|
||||
break;
|
||||
}
|
||||
|
||||
const connector = connectors[Math.floor(Math.random() * connectors.length)];
|
||||
|
||||
if (Math.random() < 0.3) {
|
||||
updatedName = l33tifyName(name);
|
||||
}
|
||||
|
||||
if (Math.random() < 0.05) {
|
||||
updatedName = updatedName.split("").reverse().join("");
|
||||
}
|
||||
|
||||
if (Math.random() < 0.1) {
|
||||
const randomSuffix = ServerNameSuffixes[Math.floor(Math.random() * ServerNameSuffixes.length)];
|
||||
updatedName = `${updatedName}${connector}${randomSuffix}`;
|
||||
}
|
||||
|
||||
if (Math.random() < 0.1) {
|
||||
const randomPrefix = ServerNamePrefixes[Math.floor(Math.random() * ServerNamePrefixes.length)];
|
||||
updatedName = `${randomPrefix}${connector}${updatedName}`;
|
||||
}
|
||||
|
||||
if (Math.random() < 0.05 && updatedName) {
|
||||
updatedName = `${updatedName}:${Math.floor(Math.random() * 10000)}`;
|
||||
}
|
||||
} while (GetServer(updatedName) !== null);
|
||||
|
||||
return updatedName;
|
||||
};
|
||||
|
||||
const l33tifyName = (name: string): string => {
|
||||
let updatedName = name;
|
||||
const amount = Math.random() * 3 + 1;
|
||||
for (let i = 0; i < amount; i++) {
|
||||
const char = Object.keys(l33t)[Math.floor(Math.random() * Object.keys(l33t).length)];
|
||||
const replacement: string = l33t[char] ?? "";
|
||||
updatedName = updatedName.replaceAll(char, replacement);
|
||||
}
|
||||
return updatedName;
|
||||
};
|
||||
Reference in New Issue
Block a user