Merge pull request #3748 from danielyxie/api-wrap

MISC: API Wrapping blocked
This commit is contained in:
hydroflame 2022-05-24 20:19:52 -04:00 committed by GitHub
commit 467e307c05
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 2200 additions and 2080 deletions

@ -9,15 +9,16 @@ import { Settings } from "../Settings/Settings";
import { CONSTANTS } from "../Constants";
type ExternalFunction = (...args: any[]) => any;
type ExternalAPI = {
export type ExternalAPI = {
[string: string]: ExternalAPI | ExternalFunction;
};
type InternalFunction<F extends (...args: unknown[]) => unknown> = (ctx: NetscriptContext) => F;
export type InternalAPI<API> = {
[Property in keyof API]: API[Property] extends ExternalFunction
? InternalFunction<API[Property]>
: API[Property] extends ExternalAPI
: API[Property] extends object
? InternalAPI<API[Property]>
: never;
};
@ -42,9 +43,14 @@ type NetscriptHelpers = {
number: (funcName: string, argName: string, v: unknown) => number;
city: (funcName: string, argName: string, v: unknown) => CityName;
boolean: (v: unknown) => boolean;
getServer: (hostname: string, callingFnName: string) => BaseServer;
getServer: (hostname: string, ctx: NetscriptContext) => BaseServer;
checkSingularityAccess: (func: string) => void;
hack: (hostname: any, manual: any, { threads: requestedThreads, stock }?: any) => Promise<number>;
hack: (
ctx: NetscriptContext,
hostname: any,
manual: any,
{ threads: requestedThreads, stock }?: any,
) => Promise<number>;
getValidPort: (funcName: string, port: any) => IPort;
};
@ -87,7 +93,7 @@ function wrapFunction(
number: (argName: string, v: unknown) => helpers.number(functionPath, argName, v),
city: (argName: string, v: unknown) => helpers.city(functionPath, argName, v),
boolean: helpers.boolean,
getServer: (hostname: string) => helpers.getServer(hostname, functionPath),
getServer: (hostname: string) => helpers.getServer(hostname, ctx),
checkSingularityAccess: () => helpers.checkSingularityAccess(functionName),
hack: helpers.hack,
getValidPort: (port: any) => helpers.getValidPort(functionPath, port),

@ -1,6 +1,18 @@
import { IPlayer } from "src/PersonObjects/IPlayer";
import { IMap } from "../types";
import { NS as INS } from "../ScriptEditor/NetscriptDefinitions";
import { INetscriptExtra } from "../NetscriptFunctions/Extra";
type RamCostTree<API> = {
[Property in keyof API]: API[Property] extends () => void
? number | ((p: IPlayer) => void)
: API[Property] extends object
? RamCostTree<API[Property]>
: never;
};
// TODO remember to update RamCalculations.js and WorkerScript.js
// RAM costs for Netscript functions
@ -89,7 +101,7 @@ function SF4Cost(cost: number): (player: IPlayer) => number {
}
// Hacknet API
const hacknet: IMap<any> = {
const hacknet = {
numNodes: 0,
purchaseNode: 0,
getPurchaseNodeCost: 0,
@ -106,10 +118,15 @@ const hacknet: IMap<any> = {
hashCost: 0,
spendHashes: 0,
maxNumNodes: 0,
hashCapacity: 0,
getHashUpgrades: 0,
getHashUpgradeLevel: 0,
getStudyMult: 0,
getTrainingMult: 0,
};
// Stock API
const stock: IMap<any> = {
const stock = {
getSymbols: RamCostConstants.ScriptGetStockRamCost,
getPrice: RamCostConstants.ScriptGetStockRamCost,
getAskPrice: RamCostConstants.ScriptGetStockRamCost,
@ -134,7 +151,7 @@ const stock: IMap<any> = {
};
// Singularity API
const singularity: IMap<any> = {
const singularity = {
universityCourse: SF4Cost(RamCostConstants.ScriptSingularityFn1RamCost),
gymWorkout: SF4Cost(RamCostConstants.ScriptSingularityFn1RamCost),
travelToCity: SF4Cost(RamCostConstants.ScriptSingularityFn1RamCost),
@ -190,7 +207,7 @@ const singularity: IMap<any> = {
};
// Gang API
const gang: IMap<any> = {
const gang = {
createGang: RamCostConstants.ScriptGangApiBaseRamCost / 4,
inGang: RamCostConstants.ScriptGangApiBaseRamCost / 4,
getMemberNames: RamCostConstants.ScriptGangApiBaseRamCost / 4,
@ -215,7 +232,7 @@ const gang: IMap<any> = {
};
// Bladeburner API
const bladeburner: IMap<any> = {
const bladeburner = {
getContractNames: RamCostConstants.ScriptBladeburnerApiBaseRamCost / 10,
getOperationNames: RamCostConstants.ScriptBladeburnerApiBaseRamCost / 10,
getBlackOpNames: RamCostConstants.ScriptBladeburnerApiBaseRamCost / 10,
@ -253,15 +270,13 @@ const bladeburner: IMap<any> = {
getBonusTime: 0,
};
const infiltration: IMap<any> = {
calculateDifficulty: RamCostConstants.ScriptInfiltrationCalculateDifficulty,
calculateRewards: RamCostConstants.ScriptInfiltrationCalculateRewards,
calculateGetLocations: RamCostConstants.ScriptInfiltrationGetLocations,
calculateGetInfiltrations: RamCostConstants.ScriptInfiltrationGetInfiltrations,
const infiltration = {
getPossibleLocations: RamCostConstants.ScriptInfiltrationGetLocations,
getInfiltration: RamCostConstants.ScriptInfiltrationGetInfiltrations,
};
// Coding Contract API
const codingcontract: IMap<any> = {
const codingcontract = {
attempt: RamCostConstants.ScriptCodingContractBaseRamCost,
getContractType: RamCostConstants.ScriptCodingContractBaseRamCost / 2,
getData: RamCostConstants.ScriptCodingContractBaseRamCost / 2,
@ -270,7 +285,7 @@ const codingcontract: IMap<any> = {
};
// Duplicate Sleeve API
const sleeve: IMap<any> = {
const sleeve = {
getNumSleeves: RamCostConstants.ScriptSleeveBaseRamCost,
setToShockRecovery: RamCostConstants.ScriptSleeveBaseRamCost,
setToSynchronize: RamCostConstants.ScriptSleeveBaseRamCost,
@ -290,7 +305,7 @@ const sleeve: IMap<any> = {
};
// Stanek API
const stanek: IMap<any> = {
const stanek = {
giftWidth: RamCostConstants.ScriptStanekWidth,
giftHeight: RamCostConstants.ScriptStanekHeight,
chargeFragment: RamCostConstants.ScriptStanekCharge,
@ -305,7 +320,7 @@ const stanek: IMap<any> = {
};
// UI API
const ui: IMap<any> = {
const ui = {
getTheme: 0,
setTheme: 0,
resetTheme: 0,
@ -313,17 +328,84 @@ const ui: IMap<any> = {
setStyles: 0,
resetStyles: 0,
getGameInfo: 0,
clearTerminal: 0,
};
// Grafting API
const grafting: IMap<any> = {
const grafting = {
getAugmentationGraftPrice: 3.75,
getAugmentationGraftTime: 3.75,
getGraftableAugmentations: 5,
graftAugmentation: 7.5,
};
export const RamCosts: IMap<any> = {
const corporation = {
createCorporation: 0,
hasUnlockUpgrade: 0,
getUnlockUpgradeCost: 0,
getUpgradeLevel: 0,
getUpgradeLevelCost: 0,
getExpandIndustryCost: 0,
getExpandCityCost: 0,
getInvestmentOffer: 0,
acceptInvestmentOffer: 0,
goPublic: 0,
bribe: 0,
getCorporation: 0,
getDivision: 0,
expandIndustry: 0,
expandCity: 0,
unlockUpgrade: 0,
levelUpgrade: 0,
issueDividends: 0,
buyBackShares: 0,
sellShares: 0,
getBonusTime: 0,
sellMaterial: 0,
sellProduct: 0,
discontinueProduct: 0,
setSmartSupply: 0,
setSmartSupplyUseLeftovers: 0,
buyMaterial: 0,
bulkPurchase: 0,
getWarehouse: 0,
getProduct: 0,
getMaterial: 0,
setMaterialMarketTA1: 0,
setMaterialMarketTA2: 0,
setProductMarketTA1: 0,
setProductMarketTA2: 0,
exportMaterial: 0,
cancelExportMaterial: 0,
purchaseWarehouse: 0,
upgradeWarehouse: 0,
makeProduct: 0,
limitMaterialProduction: 0,
limitProductProduction: 0,
getPurchaseWarehouseCost: 0,
getUpgradeWarehouseCost: 0,
hasWarehouse: 0,
assignJob: 0,
hireEmployee: 0,
upgradeOfficeSize: 0,
throwParty: 0,
buyCoffee: 0,
hireAdVert: 0,
research: 0,
getOffice: 0,
getEmployee: 0,
getHireAdVertCost: 0,
getHireAdVertCount: 0,
getResearchCost: 0,
hasResearched: 0,
setAutoJobAssignment: 0,
getOfficeSizeUpgradeCost: 0,
};
const SourceRamCosts = {
args: undefined as unknown as never[], // special use case
enums: undefined as unknown as never,
corporation,
hacknet,
stock,
singularity,
@ -363,7 +445,6 @@ export const RamCosts: IMap<any> = {
enableLog: 0,
isLogEnabled: 0,
getScriptLogs: 0,
clearTerminal: RamCostConstants.ScriptClearTerminalCost,
nuke: RamCostConstants.ScriptPortProgramRamCost,
brutessh: RamCostConstants.ScriptPortProgramRamCost,
ftpcrack: RamCostConstants.ScriptPortProgramRamCost,
@ -382,7 +463,6 @@ export const RamCosts: IMap<any> = {
ps: RamCostConstants.ScriptScanRamCost,
getRecentScripts: RamCostConstants.ScriptRecentScriptsRamCost,
hasRootAccess: RamCostConstants.ScriptHasRootAccessRamCost,
getIp: RamCostConstants.ScriptGetHostnameRamCost,
getHostname: RamCostConstants.ScriptGetHostnameRamCost,
getHackingLevel: RamCostConstants.ScriptGetHackingLevelRamCost,
getHackingMultipliers: RamCostConstants.ScriptGetMultipliersRamCost,
@ -439,12 +519,74 @@ export const RamCosts: IMap<any> = {
getOwnedSourceFiles: RamCostConstants.ScriptGetOwnedSourceFiles,
tail: 0,
toast: 0,
closeTail: 0,
clearPort: 0,
openDevMenu: 0,
alert: 0,
flags: 0,
exploit: 0,
bypass: 0,
alterReality: 0,
rainbow: 0,
heart: {
// Easter egg function
break: 0,
},
formulas: {
reputation: {
calculateFavorToRep: 0,
calculateRepToFavor: 0,
repFromDonation: 0,
},
skills: {
calculateSkill: 0,
calculateExp: 0,
},
hacking: {
hackChance: 0,
hackExp: 0,
hackPercent: 0,
growPercent: 0,
hackTime: 0,
growTime: 0,
weakenTime: 0,
},
hacknetNodes: {
moneyGainRate: 0,
levelUpgradeCost: 0,
ramUpgradeCost: 0,
coreUpgradeCost: 0,
hacknetNodeCost: 0,
constants: 0,
},
hacknetServers: {
hashGainRate: 0,
levelUpgradeCost: 0,
ramUpgradeCost: 0,
coreUpgradeCost: 0,
cacheUpgradeCost: 0,
hashUpgradeCost: 0,
hacknetServerCost: 0,
constants: 0,
},
gang: {
wantedPenalty: 0,
respectGain: 0,
wantedLevelGain: 0,
moneyGain: 0,
ascensionPointsGain: 0,
ascensionMultiplier: 0,
},
},
};
export const RamCosts: IMap<any> = SourceRamCosts;
// This line in particular is there so typescript typechecks that we are not missing any static ram cost.
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const _typecheck: RamCostTree<INS & INetscriptExtra> = SourceRamCosts;
export function getRamCost(player: IPlayer, ...args: string[]): number {
if (args.length === 0) {
console.warn(`No arguments passed to getRamCost()`);

@ -2,6 +2,7 @@ import { isString } from "./utils/helpers/isString";
import { GetServer } from "./Server/AllServers";
import { ScriptDeath } from "./Netscript/ScriptDeath";
import { WorkerScript } from "./Netscript/WorkerScript";
import { NetscriptContext } from "./Netscript/APIWrapper";
export function netscriptDelay(time: number, workerScript: WorkerScript): Promise<void> {
// Cancel any pre-existing netscriptDelay'ed function call
@ -36,26 +37,22 @@ export function makeRuntimeRejectMsg(workerScript: WorkerScript, msg: string): s
return "|DELIMITER|" + server.hostname + "|DELIMITER|" + workerScript.name + "|DELIMITER|" + msg;
}
export function resolveNetscriptRequestedThreads(
workerScript: WorkerScript,
functionName: string,
requestedThreads: number,
): number {
const threads = workerScript.scriptRef.threads;
export function resolveNetscriptRequestedThreads(ctx: NetscriptContext, requestedThreads: number): number {
const threads = ctx.workerScript.scriptRef.threads;
if (!requestedThreads) {
return isNaN(threads) || threads < 1 ? 1 : threads;
}
const requestedThreadsAsInt = requestedThreads | 0;
if (isNaN(requestedThreads) || requestedThreadsAsInt < 1) {
throw makeRuntimeRejectMsg(
workerScript,
`Invalid thread count passed to ${functionName}: ${requestedThreads}. Threads must be a positive number.`,
ctx.workerScript,
`Invalid thread count passed to ${ctx.function}: ${requestedThreads}. Threads must be a positive number.`,
);
}
if (requestedThreadsAsInt > threads) {
throw makeRuntimeRejectMsg(
workerScript,
`Too many threads requested by ${functionName}. Requested: ${requestedThreads}. Has: ${threads}.`,
ctx.workerScript,
`Too many threads requested by ${ctx.function}. Requested: ${requestedThreads}. Has: ${threads}.`,
);
}
return requestedThreadsAsInt;

File diff suppressed because it is too large Load Diff

@ -1,9 +1,8 @@
import { WorkerScript } from "../Netscript/WorkerScript";
import { IPlayer } from "../PersonObjects/IPlayer";
import { Exploit } from "../Exploits/Exploit";
import * as bcrypt from "bcryptjs";
import { INetscriptHelper } from "./INetscriptHelper";
import { Apr1Events as devMenu } from "../ui/Apr1";
import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
export interface INetscriptExtra {
heart: {
@ -16,35 +15,37 @@ export interface INetscriptExtra {
rainbow(guess: string): void;
}
export function NetscriptExtra(player: IPlayer, workerScript: WorkerScript, helper: INetscriptHelper): INetscriptExtra {
export function NetscriptExtra(player: IPlayer): InternalAPI<INetscriptExtra> {
return {
heart: {
// Easter egg function
break: function (): number {
break: () => (): number => {
return player.karma;
},
},
openDevMenu: function (): void {
openDevMenu: () => (): void => {
devMenu.emit();
},
exploit: function (): void {
exploit: () => (): void => {
player.giveExploit(Exploit.UndocumentedFunctionCall);
},
bypass: function (doc: unknown): void {
// reset both fields first
const d = doc as any;
d.completely_unused_field = undefined;
const real_document: any = document;
real_document.completely_unused_field = undefined;
// set one to true and check that it affected the other.
real_document.completely_unused_field = true;
if (d.completely_unused_field && workerScript.ramUsage === 1.6) {
player.giveExploit(Exploit.Bypass);
}
d.completely_unused_field = undefined;
real_document.completely_unused_field = undefined;
},
alterReality: function (): void {
bypass:
(ctx: NetscriptContext) =>
(doc: unknown): void => {
// reset both fields first
const d = doc as any;
d.completely_unused_field = undefined;
const real_document: any = document;
real_document.completely_unused_field = undefined;
// set one to true and check that it affected the other.
real_document.completely_unused_field = true;
if (d.completely_unused_field && ctx.workerScript.ramUsage === 1.6) {
player.giveExploit(Exploit.Bypass);
}
d.completely_unused_field = undefined;
real_document.completely_unused_field = undefined;
},
alterReality: () => (): void => {
// We need to trick webpack into not optimizing a variable that is guaranteed to be false (and doesn't use prototypes)
let x = false;
const recur = function (depth: number): void {
@ -59,20 +60,22 @@ export function NetscriptExtra(player: IPlayer, workerScript: WorkerScript, help
player.giveExploit(Exploit.RealityAlteration);
}
},
rainbow: function (guess: unknown): boolean {
function tryGuess(): boolean {
// eslint-disable-next-line no-sync
const verified = bcrypt.compareSync(
helper.string("rainbow", "guess", guess),
"$2a$10$aertxDEkgor8baVtQDZsLuMwwGYmkRM/ohcA6FjmmzIHQeTCsrCcO",
);
if (verified) {
player.giveExploit(Exploit.INeedARainbow);
return true;
rainbow:
(ctx: NetscriptContext) =>
(guess: unknown): boolean => {
function tryGuess(): boolean {
// eslint-disable-next-line no-sync
const verified = bcrypt.compareSync(
ctx.helper.string("guess", guess),
"$2a$10$aertxDEkgor8baVtQDZsLuMwwGYmkRM/ohcA6FjmmzIHQeTCsrCcO",
);
if (verified) {
player.giveExploit(Exploit.INeedARainbow);
return true;
}
return false;
}
return false;
}
return tryGuess();
},
return tryGuess();
},
};
}

@ -39,212 +39,267 @@ import {
} from "../Gang/formulas/formulas";
import { favorToRep as calculateFavorToRep, repToFavor as calculateRepToFavor } from "../Faction/formulas/favor";
import { repFromDonation } from "../Faction/formulas/donation";
import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
export function NetscriptFormulas(player: IPlayer, workerScript: WorkerScript, helper: INetscriptHelper): IFormulas {
const checkFormulasAccess = function (func: string): void {
export function NetscriptFormulas(player: IPlayer, helper: INetscriptHelper): InternalAPI<IFormulas> {
const checkFormulasAccess = function (ctx: NetscriptContext): void {
if (!player.hasProgram(Programs.Formulas.name)) {
throw helper.makeRuntimeErrorMsg(`formulas.${func}`, `Requires Formulas.exe to run.`);
throw helper.makeRuntimeErrorMsg(`formulas.${ctx.function}`, `Requires Formulas.exe to run.`);
}
};
return {
reputation: {
calculateFavorToRep: function (_favor: unknown): number {
const favor = helper.number("calculateFavorToRep", "favor", _favor);
checkFormulasAccess("reputation.calculateFavorToRep");
return calculateFavorToRep(favor);
},
calculateRepToFavor: function (_rep: unknown): number {
const rep = helper.number("calculateRepToFavor", "rep", _rep);
checkFormulasAccess("reputation.calculateRepToFavor");
return calculateRepToFavor(rep);
},
repFromDonation: function (_amount: unknown, player: any): number {
const amount = helper.number("repFromDonation", "amount", _amount);
checkFormulasAccess("reputation.repFromDonation");
return repFromDonation(amount, player);
},
calculateFavorToRep:
(ctx: NetscriptContext) =>
(_favor: unknown): number => {
const favor = ctx.helper.number("favor", _favor);
checkFormulasAccess(ctx);
return calculateFavorToRep(favor);
},
calculateRepToFavor:
(ctx: NetscriptContext) =>
(_rep: unknown): number => {
const rep = ctx.helper.number("rep", _rep);
checkFormulasAccess(ctx);
return calculateRepToFavor(rep);
},
repFromDonation:
(ctx: NetscriptContext) =>
(_amount: unknown, player: any): number => {
const amount = ctx.helper.number("amount", _amount);
checkFormulasAccess(ctx);
return repFromDonation(amount, player);
},
},
skills: {
calculateSkill: function (_exp: unknown, _mult: unknown = 1): number {
const exp = helper.number("calculateSkill", "exp", _exp);
const mult = helper.number("calculateSkill", "mult", _mult);
checkFormulasAccess("skills.calculateSkill");
return calculateSkill(exp, mult);
},
calculateExp: function (_skill: unknown, _mult: unknown = 1): number {
const skill = helper.number("calculateExp", "skill", _skill);
const mult = helper.number("calculateExp", "mult", _mult);
checkFormulasAccess("skills.calculateExp");
return calculateExp(skill, mult);
},
calculateSkill:
(ctx: NetscriptContext) =>
(_exp: unknown, _mult: unknown = 1): number => {
const exp = ctx.helper.number("exp", _exp);
const mult = ctx.helper.number("mult", _mult);
checkFormulasAccess(ctx);
return calculateSkill(exp, mult);
},
calculateExp:
(ctx: NetscriptContext) =>
(_skill: unknown, _mult: unknown = 1): number => {
const skill = ctx.helper.number("skill", _skill);
const mult = ctx.helper.number("mult", _mult);
checkFormulasAccess(ctx);
return calculateExp(skill, mult);
},
},
hacking: {
hackChance: function (server: any, player: any): number {
checkFormulasAccess("hacking.hackChance");
return calculateHackingChance(server, player);
},
hackExp: function (server: any, player: any): number {
checkFormulasAccess("hacking.hackExp");
return calculateHackingExpGain(server, player);
},
hackPercent: function (server: any, player: any): number {
checkFormulasAccess("hacking.hackPercent");
return calculatePercentMoneyHacked(server, player);
},
growPercent: function (server: any, _threads: unknown, player: any, _cores: unknown = 1): number {
const threads = helper.number("growPercent", "threads", _threads);
const cores = helper.number("growPercent", "cores", _cores);
checkFormulasAccess("hacking.growPercent");
return calculateServerGrowth(server, threads, player, cores);
},
hackTime: function (server: any, player: any): number {
checkFormulasAccess("hacking.hackTime");
return calculateHackingTime(server, player) * 1000;
},
growTime: function (server: any, player: any): number {
checkFormulasAccess("hacking.growTime");
return calculateGrowTime(server, player) * 1000;
},
weakenTime: function (server: any, player: any): number {
checkFormulasAccess("hacking.weakenTime");
return calculateWeakenTime(server, player) * 1000;
},
hackChance:
(ctx: NetscriptContext) =>
(server: any, player: any): number => {
checkFormulasAccess(ctx);
return calculateHackingChance(server, player);
},
hackExp:
(ctx: NetscriptContext) =>
(server: any, player: any): number => {
checkFormulasAccess(ctx);
return calculateHackingExpGain(server, player);
},
hackPercent:
(ctx: NetscriptContext) =>
(server: any, player: any): number => {
checkFormulasAccess(ctx);
return calculatePercentMoneyHacked(server, player);
},
growPercent:
(ctx: NetscriptContext) =>
(server: any, _threads: unknown, player: any, _cores: unknown = 1): number => {
const threads = ctx.helper.number("threads", _threads);
const cores = ctx.helper.number("cores", _cores);
checkFormulasAccess(ctx);
return calculateServerGrowth(server, threads, player, cores);
},
hackTime:
(ctx: NetscriptContext) =>
(server: any, player: any): number => {
checkFormulasAccess(ctx);
return calculateHackingTime(server, player) * 1000;
},
growTime:
(ctx: NetscriptContext) =>
(server: any, player: any): number => {
checkFormulasAccess(ctx);
return calculateGrowTime(server, player) * 1000;
},
weakenTime:
(ctx: NetscriptContext) =>
(server: any, player: any): number => {
checkFormulasAccess(ctx);
return calculateWeakenTime(server, player) * 1000;
},
},
hacknetNodes: {
moneyGainRate: function (_level: unknown, _ram: unknown, _cores: unknown, _mult: unknown = 1): number {
const level = helper.number("moneyGainRate", "level", _level);
const ram = helper.number("moneyGainRate", "ram", _ram);
const cores = helper.number("moneyGainRate", "cores", _cores);
const mult = helper.number("moneyGainRate", "mult", _mult);
checkFormulasAccess("hacknetNodes.moneyGainRate");
return calculateMoneyGainRate(level, ram, cores, mult);
},
levelUpgradeCost: function (_startingLevel: unknown, _extraLevels: unknown = 1, _costMult: unknown = 1): number {
const startingLevel = helper.number("levelUpgradeCost", "startingLevel", _startingLevel);
const extraLevels = helper.number("levelUpgradeCost", "extraLevels", _extraLevels);
const costMult = helper.number("levelUpgradeCost", "costMult", _costMult);
checkFormulasAccess("hacknetNodes.levelUpgradeCost");
return calculateLevelUpgradeCost(startingLevel, extraLevels, costMult);
},
ramUpgradeCost: function (_startingRam: unknown, _extraLevels: unknown = 1, _costMult: unknown = 1): number {
const startingRam = helper.number("ramUpgradeCost", "startingRam", _startingRam);
const extraLevels = helper.number("ramUpgradeCost", "extraLevels", _extraLevels);
const costMult = helper.number("ramUpgradeCost", "costMult", _costMult);
checkFormulasAccess("hacknetNodes.ramUpgradeCost");
return calculateRamUpgradeCost(startingRam, extraLevels, costMult);
},
coreUpgradeCost: function (_startingCore: unknown, _extraCores: unknown = 1, _costMult: unknown = 1): number {
const startingCore = helper.number("coreUpgradeCost", "startingCore", _startingCore);
const extraCores = helper.number("coreUpgradeCost", "extraCores", _extraCores);
const costMult = helper.number("coreUpgradeCost", "costMult", _costMult);
checkFormulasAccess("hacknetNodes.coreUpgradeCost");
return calculateCoreUpgradeCost(startingCore, extraCores, costMult);
},
hacknetNodeCost: function (_n: unknown, _mult: unknown): number {
const n = helper.number("hacknetNodeCost", "n", _n);
const mult = helper.number("hacknetNodeCost", "mult", _mult);
checkFormulasAccess("hacknetNodes.hacknetNodeCost");
return calculateNodeCost(n, mult);
},
constants: function (): any {
checkFormulasAccess("hacknetNodes.constants");
moneyGainRate:
(ctx: NetscriptContext) =>
(_level: unknown, _ram: unknown, _cores: unknown, _mult: unknown = 1): number => {
const level = ctx.helper.number("level", _level);
const ram = ctx.helper.number("ram", _ram);
const cores = ctx.helper.number("cores", _cores);
const mult = ctx.helper.number("mult", _mult);
checkFormulasAccess(ctx);
return calculateMoneyGainRate(level, ram, cores, mult);
},
levelUpgradeCost:
(ctx: NetscriptContext) =>
(_startingLevel: unknown, _extraLevels: unknown = 1, _costMult: unknown = 1): number => {
const startingLevel = ctx.helper.number("startingLevel", _startingLevel);
const extraLevels = ctx.helper.number("extraLevels", _extraLevels);
const costMult = ctx.helper.number("costMult", _costMult);
checkFormulasAccess(ctx);
return calculateLevelUpgradeCost(startingLevel, extraLevels, costMult);
},
ramUpgradeCost:
(ctx: NetscriptContext) =>
(_startingRam: unknown, _extraLevels: unknown = 1, _costMult: unknown = 1): number => {
const startingRam = ctx.helper.number("startingRam", _startingRam);
const extraLevels = ctx.helper.number("extraLevels", _extraLevels);
const costMult = ctx.helper.number("costMult", _costMult);
checkFormulasAccess(ctx);
return calculateRamUpgradeCost(startingRam, extraLevels, costMult);
},
coreUpgradeCost:
(ctx: NetscriptContext) =>
(_startingCore: unknown, _extraCores: unknown = 1, _costMult: unknown = 1): number => {
const startingCore = ctx.helper.number("startingCore", _startingCore);
const extraCores = ctx.helper.number("extraCores", _extraCores);
const costMult = ctx.helper.number("costMult", _costMult);
checkFormulasAccess(ctx);
return calculateCoreUpgradeCost(startingCore, extraCores, costMult);
},
hacknetNodeCost:
(ctx: NetscriptContext) =>
(_n: unknown, _mult: unknown): number => {
const n = ctx.helper.number("n", _n);
const mult = ctx.helper.number("mult", _mult);
checkFormulasAccess(ctx);
return calculateNodeCost(n, mult);
},
constants: (ctx: NetscriptContext) => (): any => {
checkFormulasAccess(ctx);
return Object.assign({}, HacknetNodeConstants);
},
},
hacknetServers: {
hashGainRate: function (
_level: unknown,
_ramUsed: unknown,
_maxRam: unknown,
_cores: unknown,
_mult: unknown = 1,
): number {
const level = helper.number("hashGainRate", "level", _level);
const ramUsed = helper.number("hashGainRate", "ramUsed", _ramUsed);
const maxRam = helper.number("hashGainRate", "maxRam", _maxRam);
const cores = helper.number("hashGainRate", "cores", _cores);
const mult = helper.number("hashGainRate", "mult", _mult);
checkFormulasAccess("hacknetServers.hashGainRate");
return HScalculateHashGainRate(level, ramUsed, maxRam, cores, mult);
},
levelUpgradeCost: function (_startingLevel: unknown, _extraLevels: unknown = 1, _costMult: unknown = 1): number {
const startingLevel = helper.number("levelUpgradeCost", "startingLevel", _startingLevel);
const extraLevels = helper.number("levelUpgradeCost", "extraLevels", _extraLevels);
const costMult = helper.number("levelUpgradeCost", "costMult", _costMult);
checkFormulasAccess("hacknetServers.levelUpgradeCost");
return HScalculateLevelUpgradeCost(startingLevel, extraLevels, costMult);
},
ramUpgradeCost: function (_startingRam: unknown, _extraLevels: unknown = 1, _costMult: unknown = 1): number {
const startingRam = helper.number("ramUpgradeCost", "startingRam", _startingRam);
const extraLevels = helper.number("ramUpgradeCost", "extraLevels", _extraLevels);
const costMult = helper.number("ramUpgradeCost", "costMult", _costMult);
checkFormulasAccess("hacknetServers.ramUpgradeCost");
return HScalculateRamUpgradeCost(startingRam, extraLevels, costMult);
},
coreUpgradeCost: function (_startingCore: unknown, _extraCores: unknown = 1, _costMult: unknown = 1): number {
const startingCore = helper.number("coreUpgradeCost", "startingCore", _startingCore);
const extraCores = helper.number("coreUpgradeCost", "extraCores", _extraCores);
const costMult = helper.number("coreUpgradeCost", "costMult", _costMult);
checkFormulasAccess("hacknetServers.coreUpgradeCost");
return HScalculateCoreUpgradeCost(startingCore, extraCores, costMult);
},
cacheUpgradeCost: function (_startingCache: unknown, _extraCache: unknown = 1): number {
const startingCache = helper.number("cacheUpgradeCost", "startingCache", _startingCache);
const extraCache = helper.number("cacheUpgradeCost", "extraCache", _extraCache);
checkFormulasAccess("hacknetServers.cacheUpgradeCost");
return HScalculateCacheUpgradeCost(startingCache, extraCache);
},
hashUpgradeCost: function (_upgName: unknown, _level: unknown): number {
const upgName = helper.string("hashUpgradeCost", "upgName", _upgName);
const level = helper.number("hashUpgradeCost", "level", _level);
checkFormulasAccess("hacknetServers.hashUpgradeCost");
const upg = player.hashManager.getUpgrade(upgName);
if (!upg) {
throw helper.makeRuntimeErrorMsg(
"formulas.hacknetServers.calculateHashUpgradeCost",
`Invalid Hash Upgrade: ${upgName}`,
);
}
return upg.getCost(level);
},
hacknetServerCost: function (_n: unknown, _mult: unknown = 1): number {
const n = helper.number("hacknetServerCost", "n", _n);
const mult = helper.number("hacknetServerCost", "mult", _mult);
checkFormulasAccess("hacknetServers.hacknetServerCost");
return HScalculateServerCost(n, mult);
},
constants: function (): any {
checkFormulasAccess("hacknetServers.constants");
hashGainRate:
(ctx: NetscriptContext) =>
(_level: unknown, _ramUsed: unknown, _maxRam: unknown, _cores: unknown, _mult: unknown = 1): number => {
const level = ctx.helper.number("level", _level);
const ramUsed = ctx.helper.number("ramUsed", _ramUsed);
const maxRam = ctx.helper.number("maxRam", _maxRam);
const cores = ctx.helper.number("cores", _cores);
const mult = ctx.helper.number("mult", _mult);
checkFormulasAccess(ctx);
return HScalculateHashGainRate(level, ramUsed, maxRam, cores, mult);
},
levelUpgradeCost:
(ctx: NetscriptContext) =>
(_startingLevel: unknown, _extraLevels: unknown = 1, _costMult: unknown = 1): number => {
const startingLevel = ctx.helper.number("startingLevel", _startingLevel);
const extraLevels = ctx.helper.number("extraLevels", _extraLevels);
const costMult = ctx.helper.number("costMult", _costMult);
checkFormulasAccess(ctx);
return HScalculateLevelUpgradeCost(startingLevel, extraLevels, costMult);
},
ramUpgradeCost:
(ctx: NetscriptContext) =>
(_startingRam: unknown, _extraLevels: unknown = 1, _costMult: unknown = 1): number => {
const startingRam = ctx.helper.number("startingRam", _startingRam);
const extraLevels = ctx.helper.number("extraLevels", _extraLevels);
const costMult = ctx.helper.number("costMult", _costMult);
checkFormulasAccess(ctx);
return HScalculateRamUpgradeCost(startingRam, extraLevels, costMult);
},
coreUpgradeCost:
(ctx: NetscriptContext) =>
(_startingCore: unknown, _extraCores: unknown = 1, _costMult: unknown = 1): number => {
const startingCore = ctx.helper.number("startingCore", _startingCore);
const extraCores = ctx.helper.number("extraCores", _extraCores);
const costMult = ctx.helper.number("costMult", _costMult);
checkFormulasAccess(ctx);
return HScalculateCoreUpgradeCost(startingCore, extraCores, costMult);
},
cacheUpgradeCost:
(ctx: NetscriptContext) =>
(_startingCache: unknown, _extraCache: unknown = 1): number => {
const startingCache = ctx.helper.number("startingCache", _startingCache);
const extraCache = ctx.helper.number("extraCache", _extraCache);
checkFormulasAccess(ctx);
return HScalculateCacheUpgradeCost(startingCache, extraCache);
},
hashUpgradeCost:
(ctx: NetscriptContext) =>
(_upgName: unknown, _level: unknown): number => {
const upgName = helper.string("hashUpgradeCost", "upgName", _upgName);
const level = ctx.helper.number("level", _level);
checkFormulasAccess(ctx);
const upg = player.hashManager.getUpgrade(upgName);
if (!upg) {
throw helper.makeRuntimeErrorMsg(
"formulas.hacknetServers.calculateHashUpgradeCost",
`Invalid Hash Upgrade: ${upgName}`,
);
}
return upg.getCost(level);
},
hacknetServerCost:
(ctx: NetscriptContext) =>
(_n: unknown, _mult: unknown = 1): number => {
const n = ctx.helper.number("n", _n);
const mult = ctx.helper.number("mult", _mult);
checkFormulasAccess(ctx);
return HScalculateServerCost(n, mult);
},
constants: (ctx: NetscriptContext) => (): any => {
checkFormulasAccess(ctx);
return Object.assign({}, HacknetServerConstants);
},
},
gang: {
wantedPenalty(gang: any): number {
checkFormulasAccess("gang.wantedPenalty");
return calculateWantedPenalty(gang);
},
respectGain: function (gang: any, member: any, task: any): number {
checkFormulasAccess("gang.respectGain");
return calculateRespectGain(gang, member, task);
},
wantedLevelGain: function (gang: any, member: any, task: any): number {
checkFormulasAccess("gang.wantedLevelGain");
return calculateWantedLevelGain(gang, member, task);
},
moneyGain: function (gang: any, member: any, task: any): number {
checkFormulasAccess("gang.moneyGain");
return calculateMoneyGain(gang, member, task);
},
ascensionPointsGain: function (_exp: unknown): number {
const exp = helper.number("ascensionPointsGain", "exp", _exp);
checkFormulasAccess("gang.ascensionPointsGain");
return calculateAscensionPointsGain(exp);
},
ascensionMultiplier: function (_points: unknown): number {
const points = helper.number("ascensionMultiplier", "points", _points);
checkFormulasAccess("gang.ascensionMultiplier");
return calculateAscensionMult(points);
},
wantedPenalty:
(ctx: NetscriptContext) =>
(gang: any): number => {
checkFormulasAccess(ctx);
return calculateWantedPenalty(gang);
},
respectGain:
(ctx: NetscriptContext) =>
(gang: any, member: any, task: any): number => {
checkFormulasAccess(ctx);
return calculateRespectGain(gang, member, task);
},
wantedLevelGain:
(ctx: NetscriptContext) =>
(gang: any, member: any, task: any): number => {
checkFormulasAccess(ctx);
return calculateWantedLevelGain(gang, member, task);
},
moneyGain:
(ctx: NetscriptContext) =>
(gang: any, member: any, task: any): number => {
checkFormulasAccess(ctx);
return calculateMoneyGain(gang, member, task);
},
ascensionPointsGain:
(ctx: NetscriptContext) =>
(_exp: unknown): number => {
const exp = ctx.helper.number("exp", _exp);
checkFormulasAccess(ctx);
return calculateAscensionPointsGain(exp);
},
ascensionMultiplier:
(ctx: NetscriptContext) =>
(_points: unknown): number => {
const points = ctx.helper.number("points", _points);
checkFormulasAccess(ctx);
return calculateAscensionMult(points);
},
},
};
}

@ -1,4 +1,6 @@
import { CityName } from "src/Locations/data/CityNames";
import { NetscriptContext } from "src/Netscript/APIWrapper";
import { IPort } from "src/NetscriptPort";
import { BaseServer } from "../Server/BaseServer";
export interface INetscriptHelper {
@ -8,7 +10,8 @@ export interface INetscriptHelper {
number(funcName: string, argName: string, v: unknown): number;
city(funcName: string, argName: string, v: unknown): CityName;
boolean(v: unknown): boolean;
getServer(ip: any, fn: any): BaseServer;
getServer(ip: any, ctx: NetscriptContext): BaseServer;
checkSingularityAccess(func: string): void;
hack(hostname: string, manual: boolean): Promise<number>;
hack(ctx: NetscriptContext, hostname: string, manual: boolean): Promise<number>;
getValidPort(funcName: string, port: number): IPort;
}