mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2026-04-22 01:03:01 +02:00
typefix netscriptFunctions (see desc)
* Types for InternalFunction and ExternalFunction have been modified to actually typecheck ns functions against docs. * Internal functions are required to use unknown for any params on the inner function. * Return types for internal function inner-function must match the respective external function. * Added new typecheck assertion function for asserting dynamic object types, to allow unknownifying params that were previously hardcoded objec structures. * Because type assertion for parameter types and return types is enforced by InternalAPI, removed all duplicate type declarations on NetscriptFunction params and returns.
This commit is contained in:
@@ -2,17 +2,12 @@ import { Player as player } from "../Player";
|
||||
import { CodingContract } from "../CodingContracts";
|
||||
import { CodingAttemptOptions, CodingContract as ICodingContract } from "../ScriptEditor/NetscriptDefinitions";
|
||||
import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
|
||||
import { helpers } from "../Netscript/NetscriptHelpers";
|
||||
import { helpers, assertObjectType } from "../Netscript/NetscriptHelpers";
|
||||
import { codingContractTypesMetadata } from "../data/codingcontracttypes";
|
||||
import { generateDummyContract } from "../CodingContractGenerator";
|
||||
|
||||
export function NetscriptCodingContract(): InternalAPI<ICodingContract> {
|
||||
const getCodingContract = function (
|
||||
ctx: NetscriptContext,
|
||||
func: string,
|
||||
hostname: string,
|
||||
filename: string,
|
||||
): CodingContract {
|
||||
const getCodingContract = function (ctx: NetscriptContext, hostname: string, filename: string): CodingContract {
|
||||
const server = helpers.getServer(ctx, hostname);
|
||||
const contract = server.getContract(filename);
|
||||
if (contract == null) {
|
||||
@@ -23,102 +18,86 @@ export function NetscriptCodingContract(): InternalAPI<ICodingContract> {
|
||||
};
|
||||
|
||||
return {
|
||||
attempt:
|
||||
(ctx: NetscriptContext) =>
|
||||
(
|
||||
answer: unknown,
|
||||
_filename: unknown,
|
||||
_hostname: unknown = ctx.workerScript.hostname,
|
||||
{ returnReward }: CodingAttemptOptions = { returnReward: false },
|
||||
): boolean | string => {
|
||||
const filename = helpers.string(ctx, "filename", _filename);
|
||||
const hostname = helpers.string(ctx, "hostname", _hostname);
|
||||
const contract = getCodingContract(ctx, "attempt", hostname, filename);
|
||||
attempt: (ctx) => (answer, _filename, _hostname?, opts?) => {
|
||||
const filename = helpers.string(ctx, "filename", _filename);
|
||||
const hostname = _hostname ? helpers.string(ctx, "hostname", _hostname) : ctx.workerScript.hostname;
|
||||
const contract = getCodingContract(ctx, hostname, filename);
|
||||
|
||||
if (typeof answer !== "number" && typeof answer !== "string" && !Array.isArray(answer))
|
||||
throw new Error("The answer provided was not a number, string, or array");
|
||||
const optsValidator: CodingAttemptOptions = { returnReward: true };
|
||||
opts ??= optsValidator;
|
||||
assertObjectType(ctx, "opts", opts, optsValidator);
|
||||
if (typeof answer !== "number" && typeof answer !== "string" && !Array.isArray(answer))
|
||||
throw new Error("The answer provided was not a number, string, or array");
|
||||
|
||||
// Convert answer to string.
|
||||
const answerStr = typeof answer === "string" ? answer : JSON.stringify(answer);
|
||||
const creward = contract.reward;
|
||||
// Convert answer to string.
|
||||
const answerStr = typeof answer === "string" ? answer : JSON.stringify(answer);
|
||||
const creward = contract.reward;
|
||||
|
||||
const serv = helpers.getServer(ctx, hostname);
|
||||
if (contract.isSolution(answerStr)) {
|
||||
const reward = player.gainCodingContractReward(creward, contract.getDifficulty());
|
||||
helpers.log(ctx, () => `Successfully completed Coding Contract '${filename}'. Reward: ${reward}`);
|
||||
const serv = helpers.getServer(ctx, hostname);
|
||||
if (contract.isSolution(answerStr)) {
|
||||
const reward = player.gainCodingContractReward(creward, contract.getDifficulty());
|
||||
helpers.log(ctx, () => `Successfully completed Coding Contract '${filename}'. Reward: ${reward}`);
|
||||
serv.removeContract(filename);
|
||||
return opts.returnReward ? reward : true;
|
||||
} else {
|
||||
++contract.tries;
|
||||
if (contract.tries >= contract.getMaxNumTries()) {
|
||||
helpers.log(ctx, () => `Coding Contract attempt '${filename}' failed. Contract is now self-destructing`);
|
||||
serv.removeContract(filename);
|
||||
return returnReward ? reward : true;
|
||||
} else {
|
||||
++contract.tries;
|
||||
if (contract.tries >= contract.getMaxNumTries()) {
|
||||
helpers.log(ctx, () => `Coding Contract attempt '${filename}' failed. Contract is now self-destructing`);
|
||||
serv.removeContract(filename);
|
||||
} else {
|
||||
helpers.log(
|
||||
ctx,
|
||||
() =>
|
||||
`Coding Contract attempt '${filename}' failed. ${
|
||||
contract.getMaxNumTries() - contract.tries
|
||||
} attempts remaining.`,
|
||||
);
|
||||
}
|
||||
|
||||
return returnReward ? "" : false;
|
||||
helpers.log(
|
||||
ctx,
|
||||
() =>
|
||||
`Coding Contract attempt '${filename}' failed. ${
|
||||
contract.getMaxNumTries() - contract.tries
|
||||
} attempts remaining.`,
|
||||
);
|
||||
}
|
||||
},
|
||||
getContractType:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_filename: unknown, _hostname: unknown = ctx.workerScript.hostname): string => {
|
||||
const filename = helpers.string(ctx, "filename", _filename);
|
||||
const hostname = helpers.string(ctx, "hostname", _hostname);
|
||||
const contract = getCodingContract(ctx, "getContractType", hostname, filename);
|
||||
return contract.getType();
|
||||
},
|
||||
getData:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_filename: unknown, _hostname: unknown = ctx.workerScript.hostname): unknown => {
|
||||
const filename = helpers.string(ctx, "filename", _filename);
|
||||
const hostname = helpers.string(ctx, "hostname", _hostname);
|
||||
const contract = getCodingContract(ctx, "getData", hostname, filename);
|
||||
const data = contract.getData();
|
||||
if (Array.isArray(data)) {
|
||||
// For two dimensional arrays, we have to copy the internal arrays using
|
||||
// slice() as well. As of right now, no contract has arrays that have
|
||||
// more than two dimensions
|
||||
const copy = data.slice();
|
||||
for (let i = 0; i < copy.length; ++i) {
|
||||
if (data[i].constructor === Array) {
|
||||
copy[i] = data[i].slice();
|
||||
}
|
||||
}
|
||||
|
||||
return copy;
|
||||
} else {
|
||||
return data;
|
||||
return opts.returnReward ? "" : false;
|
||||
}
|
||||
},
|
||||
getContractType: (ctx) => (_filename, _hostname?) => {
|
||||
const filename = helpers.string(ctx, "filename", _filename);
|
||||
const hostname = _hostname ? helpers.string(ctx, "hostname", _hostname) : ctx.workerScript.hostname;
|
||||
const contract = getCodingContract(ctx, hostname, filename);
|
||||
return contract.getType();
|
||||
},
|
||||
getData: (ctx) => (_filename, _hostname?) => {
|
||||
const filename = helpers.string(ctx, "filename", _filename);
|
||||
const hostname = _hostname ? helpers.string(ctx, "hostname", _hostname) : ctx.workerScript.hostname;
|
||||
const contract = getCodingContract(ctx, hostname, filename);
|
||||
const data = contract.getData();
|
||||
if (Array.isArray(data)) {
|
||||
// For two dimensional arrays, we have to copy the internal arrays using
|
||||
// slice() as well. As of right now, no contract has arrays that have
|
||||
// more than two dimensions
|
||||
const copy = data.slice();
|
||||
for (let i = 0; i < copy.length; ++i) {
|
||||
if (data[i].constructor === Array) {
|
||||
copy[i] = data[i].slice();
|
||||
}
|
||||
}
|
||||
},
|
||||
getDescription:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_filename: unknown, _hostname: unknown = ctx.workerScript.hostname): string => {
|
||||
const filename = helpers.string(ctx, "filename", _filename);
|
||||
const hostname = helpers.string(ctx, "hostname", _hostname);
|
||||
const contract = getCodingContract(ctx, "getDescription", hostname, filename);
|
||||
return contract.getDescription();
|
||||
},
|
||||
getNumTriesRemaining:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_filename: unknown, _hostname: unknown = ctx.workerScript.hostname): number => {
|
||||
const filename = helpers.string(ctx, "filename", _filename);
|
||||
const hostname = helpers.string(ctx, "hostname", _hostname);
|
||||
const contract = getCodingContract(ctx, "getNumTriesRemaining", hostname, filename);
|
||||
return contract.getMaxNumTries() - contract.tries;
|
||||
},
|
||||
createDummyContract:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_type: unknown): void => {
|
||||
const type = helpers.string(ctx, "type", _type);
|
||||
generateDummyContract(type);
|
||||
},
|
||||
getContractTypes: () => (): string[] => codingContractTypesMetadata.map((c) => c.name),
|
||||
|
||||
return copy;
|
||||
} else return data;
|
||||
},
|
||||
getDescription: (ctx) => (_filename, _hostname?) => {
|
||||
const filename = helpers.string(ctx, "filename", _filename);
|
||||
const hostname = _hostname ? helpers.string(ctx, "hostname", _hostname) : ctx.workerScript.hostname;
|
||||
const contract = getCodingContract(ctx, hostname, filename);
|
||||
return contract.getDescription();
|
||||
},
|
||||
getNumTriesRemaining: (ctx) => (_filename, _hostname?) => {
|
||||
const filename = helpers.string(ctx, "filename", _filename);
|
||||
const hostname = _hostname ? helpers.string(ctx, "hostname", _hostname) : ctx.workerScript.hostname;
|
||||
const contract = getCodingContract(ctx, hostname, filename);
|
||||
return contract.getMaxNumTries() - contract.tries;
|
||||
},
|
||||
createDummyContract: (ctx) => (_type) => {
|
||||
const type = helpers.string(ctx, "type", _type);
|
||||
generateDummyContract(type);
|
||||
},
|
||||
getContractTypes: () => () => codingContractTypesMetadata.map((c) => c.name),
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user