mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2026-04-22 01:03:01 +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:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user