From ea2b444b87f468040d159dfd38a063a7b90a534e Mon Sep 17 00:00:00 2001 From: TheMas3212 Date: Sun, 20 Mar 2022 19:32:29 +1100 Subject: [PATCH 1/7] Initial API Wrapper Work onlying wrapping Stanek api currently as test sample (Rebased onto upstream/dev) --- src/Netscript/APIWrapper.ts | 110 +++++++++++++++++++++++++++++++ src/NetscriptFunctions.ts | 3 +- src/NetscriptFunctions/Stanek.ts | 63 ++++++++---------- 3 files changed, 141 insertions(+), 35 deletions(-) create mode 100644 src/Netscript/APIWrapper.ts diff --git a/src/Netscript/APIWrapper.ts b/src/Netscript/APIWrapper.ts new file mode 100644 index 000000000..c968f171e --- /dev/null +++ b/src/Netscript/APIWrapper.ts @@ -0,0 +1,110 @@ +import { getRamCost } from "./RamCostGenerator"; +import type { IPort } from "../NetscriptPort"; +import type { BaseServer } from "../Server/BaseServer"; +import type { WorkerScript } from "./WorkerScript"; +import { makeRuntimeRejectMsg } from "../NetscriptEvaluator"; +import { Player } from "../Player"; + + +// type TargetFn = (...args: [T, ...any[]]) => Promise; +// type WrappedFn = F extends (a: infer A1, ...args: infer U) => Promise ? (a: A1|A1[], ...args: U) => Promise : unknown; +// Need to think more about how to get these types to work +type InternalNetscriptFunction = (ctx: NetscriptContext, ...args: unknown[]) => unknown; +type WrappedNetscriptFunction = (...args: unknown[]) => unknown; +export type InternalNetscriptAPI = { + [string: string]: InternalNetscriptAPI | InternalNetscriptFunction; +} +export type WrappedNetscriptAPI = { + [string: string]: WrappedNetscriptAPI | WrappedNetscriptFunction; +} + +export type NetscriptContext = { + workerScript: WorkerScript; + function: string; + makeRuntimeErrorMsg: (message: string) => string; + log: (message: () => string) => void; + updateDynamicRam: () => void; +}; + +type NetscriptHelpers = { + updateDynamicRam: (fnName: string, ramCost: number) => void; + makeRuntimeErrorMsg: (caller: string, msg: string) => string; + string: (funcName: string, argName: string, v: unknown) => string; + number: (funcName: string, argName: string, v: unknown) => number; + boolean: (v: unknown) => boolean; + getServer: (hostname: string, callingFnName: string) => BaseServer; + checkSingularityAccess: (func: string) => void; + hack: (hostname: any, manual: any, { threads: requestedThreads, stock }?: any) => Promise; + getValidPort: (funcName: string, port: any) => IPort; +} + +function wrapFunction(helpers: NetscriptHelpers, wrappedAPI: any, workerScript: WorkerScript, func: (ctx: NetscriptContext, ...args: unknown[]) => T, ...tree: string[]): void { + const functionName = tree.pop(); + if (typeof functionName !== 'string') { + throw makeRuntimeRejectMsg(workerScript, 'Failure occured while wrapping netscript api'); + } + const ctx = { + workerScript, + function: functionName, + makeRuntimeErrorMsg: (message: string) => { return helpers.makeRuntimeErrorMsg(functionName, message); }, + log: (message: () => string) => { workerScript.log(functionName, message); }, + updateDynamicRam: () => { + helpers.updateDynamicRam(functionName, getRamCost(Player, ...tree, functionName)); + } + }; + function wrappedFunction(...args: unknown[]): T { + return func(ctx, ...args); + } + const parent = getNestedProperty(wrappedAPI, ...tree); + Object.defineProperty(parent, functionName, { + value: wrappedFunction, + writable: true + }); +} + +// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types +export function wrapAPI(helpers: NetscriptHelpers, wrappedAPI: any, workerScript: WorkerScript, namespace: any, ...tree: string[]): WrappedNetscriptAPI { + if (typeof namespace !== 'object') throw new Error('Invalid namespace?'); + for (const property of Object.getOwnPropertyNames(namespace)) { + switch (typeof namespace[property]) { + case 'function': { + wrapFunction(helpers, wrappedAPI, workerScript, namespace[property], ...tree, property); + break; + } + case 'object': { + wrapAPI(helpers, wrappedAPI, workerScript, namespace[property], ...tree, property); + break; + } + default: { + setNestedProperty(wrappedAPI, namespace[property], ...tree, property); + } + } + } + return wrappedAPI; +} + +function setNestedProperty(root: any, value: any, ...tree: string[]): any { + let target = root; + const key = tree.pop(); + if (typeof key !== 'string') { + throw new Error('Failure occured while wrapping netscript api (setNestedProperty)') + } + for (const branch of tree) { + if (target[branch] === undefined) { + target[branch] = {}; + } + target = target[branch]; + } + target[key] = value; +} + +function getNestedProperty(root: any, ...tree: string[]): any { + let target = root; + for (const branch of tree) { + if (target[branch] === undefined) { + target[branch] = {}; + } + target = target[branch]; + } + return target; +} diff --git a/src/NetscriptFunctions.ts b/src/NetscriptFunctions.ts index bc204239a..a24978bb0 100644 --- a/src/NetscriptFunctions.ts +++ b/src/NetscriptFunctions.ts @@ -99,6 +99,7 @@ import { Flags } from "./NetscriptFunctions/Flags"; import { calculateIntelligenceBonus } from "./PersonObjects/formulas/intelligence"; import { CalculateShareMult, StartSharing } from "./NetworkShare/Share"; import { CityName } from "./Locations/data/CityNames"; +import { wrapAPI } from "./Netscript/APIWrapper"; interface NS extends INS { [key: string]: any; @@ -491,7 +492,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS { const sleeve = NetscriptSleeve(Player, workerScript, helper); const extra = NetscriptExtra(Player, workerScript, helper); const hacknet = NetscriptHacknet(Player, workerScript, helper); - const stanek = NetscriptStanek(Player, workerScript, helper); + const stanek = wrapAPI(helper, {}, workerScript, NetscriptStanek(Player, workerScript, helper), 'stanek').stanek as unknown as IStanek; const bladeburner = NetscriptBladeburner(Player, workerScript, helper); const codingcontract = NetscriptCodingContract(Player, workerScript, helper); const corporation = NetscriptCorporation(Player, workerScript, helper); diff --git a/src/NetscriptFunctions/Stanek.ts b/src/NetscriptFunctions/Stanek.ts index 6c55e21bd..a361cd27b 100644 --- a/src/NetscriptFunctions/Stanek.ts +++ b/src/NetscriptFunctions/Stanek.ts @@ -2,99 +2,94 @@ import { INetscriptHelper } from "./INetscriptHelper"; import { IPlayer } from "../PersonObjects/IPlayer"; import { WorkerScript } from "../Netscript/WorkerScript"; import { netscriptDelay } from "../NetscriptEvaluator"; -import { getRamCost } from "../Netscript/RamCostGenerator"; import { staneksGift } from "../CotMG/Helper"; import { Fragments, FragmentById } from "../CotMG/Fragment"; import { - Stanek as IStanek, Fragment as IFragment, ActiveFragment as IActiveFragment, } from "../ScriptEditor/NetscriptDefinitions"; import { AugmentationNames } from "../Augmentation/data/AugmentationNames"; +import { NetscriptContext, InternalNetscriptAPI } from "src/Netscript/APIWrapper"; -export function NetscriptStanek(player: IPlayer, workerScript: WorkerScript, helper: INetscriptHelper): IStanek { +export function NetscriptStanek(player: IPlayer, workerScript: WorkerScript, helper: INetscriptHelper): InternalNetscriptAPI { function checkStanekAPIAccess(func: string): void { if (!player.hasAugmentation(AugmentationNames.StaneksGift1, true)) { helper.makeRuntimeErrorMsg(func, "Requires Stanek's Gift installed."); } } - const updateRam = (funcName: string): void => - helper.updateDynamicRam(funcName, getRamCost(player, "stanek", funcName)); - return { - giftWidth: function (): number { - updateRam("giftWidth"); + giftWidth: function (ctx: NetscriptContext): number { + ctx.updateDynamicRam(); checkStanekAPIAccess("giftWidth"); return staneksGift.width(); }, - giftHeight: function (): number { - updateRam("giftHeight"); + giftHeight: function (ctx: NetscriptContext): number { + ctx.updateDynamicRam(); checkStanekAPIAccess("giftHeight"); return staneksGift.height(); }, - chargeFragment: function (_rootX: unknown, _rootY: unknown): Promise { - updateRam("chargeFragment"); + chargeFragment: function (ctx: NetscriptContext, _rootX: unknown, _rootY: unknown): Promise { + ctx.updateDynamicRam(); const rootX = helper.number("stanek.chargeFragment", "rootX", _rootX); const rootY = helper.number("stanek.chargeFragment", "rootY", _rootY); checkStanekAPIAccess("chargeFragment"); const fragment = staneksGift.findFragment(rootX, rootY); - if (!fragment) - throw helper.makeRuntimeErrorMsg("stanek.chargeFragment", `No fragment with root (${rootX}, ${rootY}).`); + if (!fragment) throw ctx.makeRuntimeErrorMsg(`No fragment with root (${rootX}, ${rootY}).`); const time = staneksGift.inBonus() ? 200 : 1000; return netscriptDelay(time, workerScript).then(function () { const charge = staneksGift.charge(player, fragment, workerScript.scriptRef.threads); - workerScript.log("stanek.chargeFragment", () => `Charged fragment for ${charge} charge.`); + ctx.log(() => `Charged fragment for ${charge} charge.`); return Promise.resolve(); }); }, - fragmentDefinitions: function (): IFragment[] { - updateRam("fragmentDefinitions"); + fragmentDefinitions: function (ctx: NetscriptContext): IFragment[] { + ctx.updateDynamicRam(); checkStanekAPIAccess("fragmentDefinitions"); - workerScript.log("stanek.fragmentDefinitions", () => `Returned ${Fragments.length} fragments`); + ctx.log(() => `Returned ${Fragments.length} fragments`); return Fragments.map((f) => f.copy()); }, - activeFragments: function (): IActiveFragment[] { - updateRam("activeFragments"); + activeFragments: function (ctx: NetscriptContext): IActiveFragment[] { + ctx.updateDynamicRam(); checkStanekAPIAccess("activeFragments"); - workerScript.log("stanek.activeFragments", () => `Returned ${staneksGift.fragments.length} fragments`); + ctx.log(() => `Returned ${staneksGift.fragments.length} fragments`); return staneksGift.fragments.map((af) => { return { ...af.copy(), ...af.fragment().copy() }; }); }, - clearGift: function (): void { - updateRam("clearGift"); + clearGift: function (ctx: NetscriptContext): void { + ctx.updateDynamicRam(); checkStanekAPIAccess("clearGift"); - workerScript.log("stanek.clearGift", () => `Cleared Stanek's Gift.`); + ctx.log(() => `Cleared Stanek's Gift.`); staneksGift.clear(); }, - canPlaceFragment: function (_rootX: unknown, _rootY: unknown, _rotation: unknown, _fragmentId: unknown): boolean { - updateRam("canPlaceFragment"); + canPlaceFragment: function (ctx: NetscriptContext, _rootX: unknown, _rootY: unknown, _rotation: unknown, _fragmentId: unknown): boolean { + ctx.updateDynamicRam(); const rootX = helper.number("stanek.canPlaceFragment", "rootX", _rootX); const rootY = helper.number("stanek.canPlaceFragment", "rootY", _rootY); const rotation = helper.number("stanek.canPlaceFragment", "rotation", _rotation); const fragmentId = helper.number("stanek.canPlaceFragment", "fragmentId", _fragmentId); checkStanekAPIAccess("canPlaceFragment"); const fragment = FragmentById(fragmentId); - if (!fragment) throw helper.makeRuntimeErrorMsg("stanek.canPlaceFragment", `Invalid fragment id: ${fragmentId}`); + if (!fragment) throw ctx.makeRuntimeErrorMsg(`Invalid fragment id: ${fragmentId}`); const can = staneksGift.canPlace(rootX, rootY, rotation, fragment); return can; }, - placeFragment: function (_rootX: unknown, _rootY: unknown, _rotation: unknown, _fragmentId: unknown): boolean { - updateRam("placeFragment"); + placeFragment: function (ctx: NetscriptContext, _rootX: unknown, _rootY: unknown, _rotation: unknown, _fragmentId: unknown): boolean { + ctx.updateDynamicRam(); const rootX = helper.number("stanek.placeFragment", "rootX", _rootX); const rootY = helper.number("stanek.placeFragment", "rootY", _rootY); const rotation = helper.number("stanek.placeFragment", "rotation", _rotation); const fragmentId = helper.number("stanek.placeFragment", "fragmentId", _fragmentId); checkStanekAPIAccess("placeFragment"); const fragment = FragmentById(fragmentId); - if (!fragment) throw helper.makeRuntimeErrorMsg("stanek.placeFragment", `Invalid fragment id: ${fragmentId}`); + if (!fragment) throw ctx.makeRuntimeErrorMsg(`Invalid fragment id: ${fragmentId}`); return staneksGift.place(rootX, rootY, rotation, fragment); }, - getFragment: function (_rootX: unknown, _rootY: unknown): IActiveFragment | undefined { - updateRam("getFragment"); + getFragment: function (ctx: NetscriptContext, _rootX: unknown, _rootY: unknown): IActiveFragment | undefined { + ctx.updateDynamicRam(); const rootX = helper.number("stanek.getFragment", "rootX", _rootX); const rootY = helper.number("stanek.getFragment", "rootY", _rootY); checkStanekAPIAccess("getFragment"); @@ -102,8 +97,8 @@ export function NetscriptStanek(player: IPlayer, workerScript: WorkerScript, hel if (fragment !== undefined) return fragment.copy(); return undefined; }, - removeFragment: function (_rootX: unknown, _rootY: unknown): boolean { - updateRam("removeFragment"); + removeFragment: function (ctx: NetscriptContext, _rootX: unknown, _rootY: unknown): boolean { + ctx.updateDynamicRam(); const rootX = helper.number("stanek.removeFragment", "rootX", _rootX); const rootY = helper.number("stanek.removeFragment", "rootY", _rootY); checkStanekAPIAccess("removeFragment"); From 40f74e4a9817f6deacb73d0ad3937f2f0f412c2f Mon Sep 17 00:00:00 2001 From: TheMas3212 Date: Wed, 30 Mar 2022 08:57:17 +1100 Subject: [PATCH 2/7] add wrapped helpers to ctx add ramcheck into wrapper --- src/Netscript/APIWrapper.ts | 35 ++++++++++++++++++++------ src/NetscriptFunctions/Stanek.ts | 42 ++++++++++++-------------------- 2 files changed, 44 insertions(+), 33 deletions(-) diff --git a/src/Netscript/APIWrapper.ts b/src/Netscript/APIWrapper.ts index c968f171e..82bd1c3e1 100644 --- a/src/Netscript/APIWrapper.ts +++ b/src/Netscript/APIWrapper.ts @@ -19,11 +19,11 @@ export type WrappedNetscriptAPI = { } export type NetscriptContext = { - workerScript: WorkerScript; - function: string; makeRuntimeErrorMsg: (message: string) => string; log: (message: () => string) => void; - updateDynamicRam: () => void; + workerScript: WorkerScript; + function: string; + helper: WrappedNetscriptHelpers; }; type NetscriptHelpers = { @@ -38,21 +38,42 @@ type NetscriptHelpers = { getValidPort: (funcName: string, port: any) => IPort; } +type WrappedNetscriptHelpers = { + updateDynamicRam: (ramCost: number) => void; + makeRuntimeErrorMsg: (msg: string) => string; + string: (argName: string, v: unknown) => string; + number: (argName: string, v: unknown) => number; + boolean: (v: unknown) => boolean; + getServer: (hostname: string)=> BaseServer; + checkSingularityAccess: () => void; + hack: (hostname: any, manual: any, { threads: requestedThreads, stock }?: any) => Promise; + getValidPort: (port: any) => IPort; +} + function wrapFunction(helpers: NetscriptHelpers, wrappedAPI: any, workerScript: WorkerScript, func: (ctx: NetscriptContext, ...args: unknown[]) => T, ...tree: string[]): void { const functionName = tree.pop(); if (typeof functionName !== 'string') { throw makeRuntimeRejectMsg(workerScript, 'Failure occured while wrapping netscript api'); } const ctx = { - workerScript, - function: functionName, makeRuntimeErrorMsg: (message: string) => { return helpers.makeRuntimeErrorMsg(functionName, message); }, log: (message: () => string) => { workerScript.log(functionName, message); }, - updateDynamicRam: () => { - helpers.updateDynamicRam(functionName, getRamCost(Player, ...tree, functionName)); + workerScript, + function: functionName, + helper: { + updateDynamicRam: (ramCost: number) => helpers.updateDynamicRam(functionName, ramCost), + makeRuntimeErrorMsg: (msg: string) => helpers.makeRuntimeErrorMsg(functionName, msg), + string: (argName: string, v: unknown) => helpers.string(functionName, argName, v), + number: (argName: string, v: unknown) => helpers.number(functionName, argName, v), + boolean: helpers.boolean, + getServer: (hostname: string) => helpers.getServer(hostname, functionName), + checkSingularityAccess: () => helpers.checkSingularityAccess(functionName), + hack: helpers.hack, + getValidPort: (port: any) => helpers.getValidPort(functionName, port) } }; function wrappedFunction(...args: unknown[]): T { + helpers.updateDynamicRam(ctx.function, getRamCost(Player, ...tree, ctx.function)); return func(ctx, ...args); } const parent = getNestedProperty(wrappedAPI, ...tree); diff --git a/src/NetscriptFunctions/Stanek.ts b/src/NetscriptFunctions/Stanek.ts index a361cd27b..598115a77 100644 --- a/src/NetscriptFunctions/Stanek.ts +++ b/src/NetscriptFunctions/Stanek.ts @@ -21,20 +21,17 @@ export function NetscriptStanek(player: IPlayer, workerScript: WorkerScript, hel } return { - giftWidth: function (ctx: NetscriptContext): number { - ctx.updateDynamicRam(); + giftWidth: function (): number { checkStanekAPIAccess("giftWidth"); return staneksGift.width(); }, - giftHeight: function (ctx: NetscriptContext): number { - ctx.updateDynamicRam(); + giftHeight: function (): number { checkStanekAPIAccess("giftHeight"); return staneksGift.height(); }, chargeFragment: function (ctx: NetscriptContext, _rootX: unknown, _rootY: unknown): Promise { - ctx.updateDynamicRam(); - const rootX = helper.number("stanek.chargeFragment", "rootX", _rootX); - const rootY = helper.number("stanek.chargeFragment", "rootY", _rootY); + const rootX = ctx.helper.number("rootX", _rootX); + const rootY = ctx.helper.number("rootY", _rootY); checkStanekAPIAccess("chargeFragment"); const fragment = staneksGift.findFragment(rootX, rootY); if (!fragment) throw ctx.makeRuntimeErrorMsg(`No fragment with root (${rootX}, ${rootY}).`); @@ -46,13 +43,11 @@ export function NetscriptStanek(player: IPlayer, workerScript: WorkerScript, hel }); }, fragmentDefinitions: function (ctx: NetscriptContext): IFragment[] { - ctx.updateDynamicRam(); checkStanekAPIAccess("fragmentDefinitions"); ctx.log(() => `Returned ${Fragments.length} fragments`); return Fragments.map((f) => f.copy()); }, activeFragments: function (ctx: NetscriptContext): IActiveFragment[] { - ctx.updateDynamicRam(); checkStanekAPIAccess("activeFragments"); ctx.log(() => `Returned ${staneksGift.fragments.length} fragments`); return staneksGift.fragments.map((af) => { @@ -60,17 +55,15 @@ export function NetscriptStanek(player: IPlayer, workerScript: WorkerScript, hel }); }, clearGift: function (ctx: NetscriptContext): void { - ctx.updateDynamicRam(); checkStanekAPIAccess("clearGift"); ctx.log(() => `Cleared Stanek's Gift.`); staneksGift.clear(); }, canPlaceFragment: function (ctx: NetscriptContext, _rootX: unknown, _rootY: unknown, _rotation: unknown, _fragmentId: unknown): boolean { - ctx.updateDynamicRam(); - const rootX = helper.number("stanek.canPlaceFragment", "rootX", _rootX); - const rootY = helper.number("stanek.canPlaceFragment", "rootY", _rootY); - const rotation = helper.number("stanek.canPlaceFragment", "rotation", _rotation); - const fragmentId = helper.number("stanek.canPlaceFragment", "fragmentId", _fragmentId); + const rootX = ctx.helper.number("rootX", _rootX); + const rootY = ctx.helper.number("rootY", _rootY); + const rotation = ctx.helper.number("rotation", _rotation); + const fragmentId = ctx.helper.number("fragmentId", _fragmentId); checkStanekAPIAccess("canPlaceFragment"); const fragment = FragmentById(fragmentId); if (!fragment) throw ctx.makeRuntimeErrorMsg(`Invalid fragment id: ${fragmentId}`); @@ -78,29 +71,26 @@ export function NetscriptStanek(player: IPlayer, workerScript: WorkerScript, hel return can; }, placeFragment: function (ctx: NetscriptContext, _rootX: unknown, _rootY: unknown, _rotation: unknown, _fragmentId: unknown): boolean { - ctx.updateDynamicRam(); - const rootX = helper.number("stanek.placeFragment", "rootX", _rootX); - const rootY = helper.number("stanek.placeFragment", "rootY", _rootY); - const rotation = helper.number("stanek.placeFragment", "rotation", _rotation); - const fragmentId = helper.number("stanek.placeFragment", "fragmentId", _fragmentId); + const rootX = ctx.helper.number("rootX", _rootX); + const rootY = ctx.helper.number("rootY", _rootY); + const rotation = ctx.helper.number("rotation", _rotation); + const fragmentId = ctx.helper.number("fragmentId", _fragmentId); checkStanekAPIAccess("placeFragment"); const fragment = FragmentById(fragmentId); if (!fragment) throw ctx.makeRuntimeErrorMsg(`Invalid fragment id: ${fragmentId}`); return staneksGift.place(rootX, rootY, rotation, fragment); }, getFragment: function (ctx: NetscriptContext, _rootX: unknown, _rootY: unknown): IActiveFragment | undefined { - ctx.updateDynamicRam(); - const rootX = helper.number("stanek.getFragment", "rootX", _rootX); - const rootY = helper.number("stanek.getFragment", "rootY", _rootY); + const rootX = ctx.helper.number("rootX", _rootX); + const rootY = ctx.helper.number("rootY", _rootY); checkStanekAPIAccess("getFragment"); const fragment = staneksGift.findFragment(rootX, rootY); if (fragment !== undefined) return fragment.copy(); return undefined; }, removeFragment: function (ctx: NetscriptContext, _rootX: unknown, _rootY: unknown): boolean { - ctx.updateDynamicRam(); - const rootX = helper.number("stanek.removeFragment", "rootX", _rootX); - const rootY = helper.number("stanek.removeFragment", "rootY", _rootY); + const rootX = ctx.helper.number("rootX", _rootX); + const rootY = ctx.helper.number("rootY", _rootY); checkStanekAPIAccess("removeFragment"); return staneksGift.delete(rootX, rootY); }, From 8c58f0676dd7cc147c3a2d0219fd5da5ea7880ce Mon Sep 17 00:00:00 2001 From: TheMas3212 Date: Wed, 30 Mar 2022 10:11:13 +1100 Subject: [PATCH 3/7] Improve Typesafety on API Wrapper --- src/Netscript/APIWrapper.ts | 21 ++++++++++++--------- src/NetscriptFunctions/Stanek.ts | 5 +++-- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/Netscript/APIWrapper.ts b/src/Netscript/APIWrapper.ts index 82bd1c3e1..7cc2933bb 100644 --- a/src/Netscript/APIWrapper.ts +++ b/src/Netscript/APIWrapper.ts @@ -6,15 +6,18 @@ import { makeRuntimeRejectMsg } from "../NetscriptEvaluator"; import { Player } from "../Player"; -// type TargetFn = (...args: [T, ...any[]]) => Promise; -// type WrappedFn = F extends (a: infer A1, ...args: infer U) => Promise ? (a: A1|A1[], ...args: U) => Promise : unknown; -// Need to think more about how to get these types to work -type InternalNetscriptFunction = (ctx: NetscriptContext, ...args: unknown[]) => unknown; -type WrappedNetscriptFunction = (...args: unknown[]) => unknown; -export type InternalNetscriptAPI = { - [string: string]: InternalNetscriptAPI | InternalNetscriptFunction; +type ExternalFunction = (...args: any[]) => any; +type ExternalAPI = { + [string: string]: ExternalAPI | ExternalFunction; } -export type WrappedNetscriptAPI = { + +type InternalFunction unknown> = (ctx: NetscriptContext, ...args: unknown[]) => ReturnType; +export type InternalAPI = { + [Property in keyof API]: API[Property] extends ExternalFunction ? InternalFunction : API[Property] extends ExternalAPI ? InternalAPI : never; +} + +type WrappedNetscriptFunction = (...args: unknown[]) => unknown; +type WrappedNetscriptAPI = { [string: string]: WrappedNetscriptAPI | WrappedNetscriptFunction; } @@ -84,7 +87,7 @@ function wrapFunction(helpers: NetscriptHelpers, wrappedAPI: any, workerScrip } // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types -export function wrapAPI(helpers: NetscriptHelpers, wrappedAPI: any, workerScript: WorkerScript, namespace: any, ...tree: string[]): WrappedNetscriptAPI { +export function wrapAPI(helpers: NetscriptHelpers, wrappedAPI: ExternalAPI, workerScript: WorkerScript, namespace: any, ...tree: string[]): WrappedNetscriptAPI { if (typeof namespace !== 'object') throw new Error('Invalid namespace?'); for (const property of Object.getOwnPropertyNames(namespace)) { switch (typeof namespace[property]) { diff --git a/src/NetscriptFunctions/Stanek.ts b/src/NetscriptFunctions/Stanek.ts index 598115a77..dd65f74a4 100644 --- a/src/NetscriptFunctions/Stanek.ts +++ b/src/NetscriptFunctions/Stanek.ts @@ -9,11 +9,12 @@ import { Fragments, FragmentById } from "../CotMG/Fragment"; import { Fragment as IFragment, ActiveFragment as IActiveFragment, + Stanek as IStanek } from "../ScriptEditor/NetscriptDefinitions"; import { AugmentationNames } from "../Augmentation/data/AugmentationNames"; -import { NetscriptContext, InternalNetscriptAPI } from "src/Netscript/APIWrapper"; +import { NetscriptContext, InternalAPI } from "src/Netscript/APIWrapper"; -export function NetscriptStanek(player: IPlayer, workerScript: WorkerScript, helper: INetscriptHelper): InternalNetscriptAPI { +export function NetscriptStanek(player: IPlayer, workerScript: WorkerScript, helper: INetscriptHelper): InternalAPI { function checkStanekAPIAccess(func: string): void { if (!player.hasAugmentation(AugmentationNames.StaneksGift1, true)) { helper.makeRuntimeErrorMsg(func, "Requires Stanek's Gift installed."); From f0cfc8700a5e5060b1c3c8a122e766348663a58c Mon Sep 17 00:00:00 2001 From: TheMas3212 Date: Thu, 7 Apr 2022 10:00:54 +1000 Subject: [PATCH 4/7] run formater --- src/Netscript/APIWrapper.ts | 70 +++++++++++++++++++++----------- src/NetscriptFunctions.ts | 3 +- src/NetscriptFunctions/Stanek.ts | 24 +++++++++-- 3 files changed, 68 insertions(+), 29 deletions(-) diff --git a/src/Netscript/APIWrapper.ts b/src/Netscript/APIWrapper.ts index 7cc2933bb..03528a520 100644 --- a/src/Netscript/APIWrapper.ts +++ b/src/Netscript/APIWrapper.ts @@ -5,21 +5,27 @@ import type { WorkerScript } from "./WorkerScript"; import { makeRuntimeRejectMsg } from "../NetscriptEvaluator"; import { Player } from "../Player"; - type ExternalFunction = (...args: any[]) => any; type ExternalAPI = { [string: string]: ExternalAPI | ExternalFunction; -} +}; -type InternalFunction unknown> = (ctx: NetscriptContext, ...args: unknown[]) => ReturnType; +type InternalFunction unknown> = ( + ctx: NetscriptContext, + ...args: unknown[] +) => ReturnType; export type InternalAPI = { - [Property in keyof API]: API[Property] extends ExternalFunction ? InternalFunction : API[Property] extends ExternalAPI ? InternalAPI : never; -} + [Property in keyof API]: API[Property] extends ExternalFunction + ? InternalFunction + : API[Property] extends ExternalAPI + ? InternalAPI + : never; +}; type WrappedNetscriptFunction = (...args: unknown[]) => unknown; type WrappedNetscriptAPI = { [string: string]: WrappedNetscriptAPI | WrappedNetscriptFunction; -} +}; export type NetscriptContext = { makeRuntimeErrorMsg: (message: string) => string; @@ -39,7 +45,7 @@ type NetscriptHelpers = { checkSingularityAccess: (func: string) => void; hack: (hostname: any, manual: any, { threads: requestedThreads, stock }?: any) => Promise; getValidPort: (funcName: string, port: any) => IPort; -} +}; type WrappedNetscriptHelpers = { updateDynamicRam: (ramCost: number) => void; @@ -47,20 +53,30 @@ type WrappedNetscriptHelpers = { string: (argName: string, v: unknown) => string; number: (argName: string, v: unknown) => number; boolean: (v: unknown) => boolean; - getServer: (hostname: string)=> BaseServer; + getServer: (hostname: string) => BaseServer; checkSingularityAccess: () => void; hack: (hostname: any, manual: any, { threads: requestedThreads, stock }?: any) => Promise; getValidPort: (port: any) => IPort; -} +}; -function wrapFunction(helpers: NetscriptHelpers, wrappedAPI: any, workerScript: WorkerScript, func: (ctx: NetscriptContext, ...args: unknown[]) => T, ...tree: string[]): void { +function wrapFunction( + helpers: NetscriptHelpers, + wrappedAPI: any, + workerScript: WorkerScript, + func: (ctx: NetscriptContext, ...args: unknown[]) => T, + ...tree: string[] +): void { const functionName = tree.pop(); - if (typeof functionName !== 'string') { - throw makeRuntimeRejectMsg(workerScript, 'Failure occured while wrapping netscript api'); + if (typeof functionName !== "string") { + throw makeRuntimeRejectMsg(workerScript, "Failure occured while wrapping netscript api"); } const ctx = { - makeRuntimeErrorMsg: (message: string) => { return helpers.makeRuntimeErrorMsg(functionName, message); }, - log: (message: () => string) => { workerScript.log(functionName, message); }, + makeRuntimeErrorMsg: (message: string) => { + return helpers.makeRuntimeErrorMsg(functionName, message); + }, + log: (message: () => string) => { + workerScript.log(functionName, message); + }, workerScript, function: functionName, helper: { @@ -72,8 +88,8 @@ function wrapFunction(helpers: NetscriptHelpers, wrappedAPI: any, workerScrip getServer: (hostname: string) => helpers.getServer(hostname, functionName), checkSingularityAccess: () => helpers.checkSingularityAccess(functionName), hack: helpers.hack, - getValidPort: (port: any) => helpers.getValidPort(functionName, port) - } + getValidPort: (port: any) => helpers.getValidPort(functionName, port), + }, }; function wrappedFunction(...args: unknown[]): T { helpers.updateDynamicRam(ctx.function, getRamCost(Player, ...tree, ctx.function)); @@ -82,20 +98,26 @@ function wrapFunction(helpers: NetscriptHelpers, wrappedAPI: any, workerScrip const parent = getNestedProperty(wrappedAPI, ...tree); Object.defineProperty(parent, functionName, { value: wrappedFunction, - writable: true + writable: true, }); } -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types -export function wrapAPI(helpers: NetscriptHelpers, wrappedAPI: ExternalAPI, workerScript: WorkerScript, namespace: any, ...tree: string[]): WrappedNetscriptAPI { - if (typeof namespace !== 'object') throw new Error('Invalid namespace?'); +export function wrapAPI( + helpers: NetscriptHelpers, + wrappedAPI: ExternalAPI, + workerScript: WorkerScript, + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types + namespace: any, + ...tree: string[] +): WrappedNetscriptAPI { + if (typeof namespace !== "object") throw new Error("Invalid namespace?"); for (const property of Object.getOwnPropertyNames(namespace)) { switch (typeof namespace[property]) { - case 'function': { + case "function": { wrapFunction(helpers, wrappedAPI, workerScript, namespace[property], ...tree, property); break; } - case 'object': { + case "object": { wrapAPI(helpers, wrappedAPI, workerScript, namespace[property], ...tree, property); break; } @@ -110,8 +132,8 @@ export function wrapAPI(helpers: NetscriptHelpers, wrappedAPI: ExternalAPI, work function setNestedProperty(root: any, value: any, ...tree: string[]): any { let target = root; const key = tree.pop(); - if (typeof key !== 'string') { - throw new Error('Failure occured while wrapping netscript api (setNestedProperty)') + if (typeof key !== "string") { + throw new Error("Failure occured while wrapping netscript api (setNestedProperty)"); } for (const branch of tree) { if (target[branch] === undefined) { diff --git a/src/NetscriptFunctions.ts b/src/NetscriptFunctions.ts index a24978bb0..0ced4545f 100644 --- a/src/NetscriptFunctions.ts +++ b/src/NetscriptFunctions.ts @@ -492,7 +492,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS { const sleeve = NetscriptSleeve(Player, workerScript, helper); const extra = NetscriptExtra(Player, workerScript, helper); const hacknet = NetscriptHacknet(Player, workerScript, helper); - const stanek = wrapAPI(helper, {}, workerScript, NetscriptStanek(Player, workerScript, helper), 'stanek').stanek as unknown as IStanek; + const stanek = wrapAPI(helper, {}, workerScript, NetscriptStanek(Player, workerScript, helper), "stanek") + .stanek as unknown as IStanek; const bladeburner = NetscriptBladeburner(Player, workerScript, helper); const codingcontract = NetscriptCodingContract(Player, workerScript, helper); const corporation = NetscriptCorporation(Player, workerScript, helper); diff --git a/src/NetscriptFunctions/Stanek.ts b/src/NetscriptFunctions/Stanek.ts index dd65f74a4..5dd2d53b4 100644 --- a/src/NetscriptFunctions/Stanek.ts +++ b/src/NetscriptFunctions/Stanek.ts @@ -9,12 +9,16 @@ import { Fragments, FragmentById } from "../CotMG/Fragment"; import { Fragment as IFragment, ActiveFragment as IActiveFragment, - Stanek as IStanek + Stanek as IStanek, } from "../ScriptEditor/NetscriptDefinitions"; import { AugmentationNames } from "../Augmentation/data/AugmentationNames"; import { NetscriptContext, InternalAPI } from "src/Netscript/APIWrapper"; -export function NetscriptStanek(player: IPlayer, workerScript: WorkerScript, helper: INetscriptHelper): InternalAPI { +export function NetscriptStanek( + player: IPlayer, + workerScript: WorkerScript, + helper: INetscriptHelper, +): InternalAPI { function checkStanekAPIAccess(func: string): void { if (!player.hasAugmentation(AugmentationNames.StaneksGift1, true)) { helper.makeRuntimeErrorMsg(func, "Requires Stanek's Gift installed."); @@ -60,7 +64,13 @@ export function NetscriptStanek(player: IPlayer, workerScript: WorkerScript, hel ctx.log(() => `Cleared Stanek's Gift.`); staneksGift.clear(); }, - canPlaceFragment: function (ctx: NetscriptContext, _rootX: unknown, _rootY: unknown, _rotation: unknown, _fragmentId: unknown): boolean { + canPlaceFragment: function ( + ctx: NetscriptContext, + _rootX: unknown, + _rootY: unknown, + _rotation: unknown, + _fragmentId: unknown, + ): boolean { const rootX = ctx.helper.number("rootX", _rootX); const rootY = ctx.helper.number("rootY", _rootY); const rotation = ctx.helper.number("rotation", _rotation); @@ -71,7 +81,13 @@ export function NetscriptStanek(player: IPlayer, workerScript: WorkerScript, hel const can = staneksGift.canPlace(rootX, rootY, rotation, fragment); return can; }, - placeFragment: function (ctx: NetscriptContext, _rootX: unknown, _rootY: unknown, _rotation: unknown, _fragmentId: unknown): boolean { + placeFragment: function ( + ctx: NetscriptContext, + _rootX: unknown, + _rootY: unknown, + _rotation: unknown, + _fragmentId: unknown, + ): boolean { const rootX = ctx.helper.number("rootX", _rootX); const rootY = ctx.helper.number("rootY", _rootY); const rotation = ctx.helper.number("rotation", _rotation); From 9b53896732c77944d9b9053bbac242a580ddd3ea Mon Sep 17 00:00:00 2001 From: TheMas3212 Date: Fri, 8 Apr 2022 09:57:16 +1000 Subject: [PATCH 5/7] slight change on how wrapping work based on discussion in #development --- src/Netscript/APIWrapper.ts | 29 ++++++++------- src/NetscriptFunctions/Stanek.ts | 64 ++++++++++++++++---------------- 2 files changed, 46 insertions(+), 47 deletions(-) diff --git a/src/Netscript/APIWrapper.ts b/src/Netscript/APIWrapper.ts index 03528a520..f5ed8c860 100644 --- a/src/Netscript/APIWrapper.ts +++ b/src/Netscript/APIWrapper.ts @@ -11,9 +11,8 @@ type ExternalAPI = { }; type InternalFunction unknown> = ( - ctx: NetscriptContext, - ...args: unknown[] -) => ReturnType; + ctx: NetscriptContext +) => (...args: unknown[]) => ReturnType; export type InternalAPI = { [Property in keyof API]: API[Property] extends ExternalFunction ? InternalFunction @@ -59,46 +58,48 @@ type WrappedNetscriptHelpers = { getValidPort: (port: any) => IPort; }; -function wrapFunction( +function wrapFunction( helpers: NetscriptHelpers, wrappedAPI: any, workerScript: WorkerScript, - func: (ctx: NetscriptContext, ...args: unknown[]) => T, + func: (_ctx: NetscriptContext) => (...args: unknown[]) => unknown, ...tree: string[] ): void { + const functionPath = tree.join('.'); const functionName = tree.pop(); if (typeof functionName !== "string") { throw makeRuntimeRejectMsg(workerScript, "Failure occured while wrapping netscript api"); } const ctx = { makeRuntimeErrorMsg: (message: string) => { - return helpers.makeRuntimeErrorMsg(functionName, message); + return helpers.makeRuntimeErrorMsg(functionPath, message); }, log: (message: () => string) => { - workerScript.log(functionName, message); + workerScript.log(functionPath, message); }, workerScript, function: functionName, helper: { updateDynamicRam: (ramCost: number) => helpers.updateDynamicRam(functionName, ramCost), - makeRuntimeErrorMsg: (msg: string) => helpers.makeRuntimeErrorMsg(functionName, msg), - string: (argName: string, v: unknown) => helpers.string(functionName, argName, v), - number: (argName: string, v: unknown) => helpers.number(functionName, argName, v), + makeRuntimeErrorMsg: (msg: string) => helpers.makeRuntimeErrorMsg(functionPath, msg), + string: (argName: string, v: unknown) => helpers.string(functionPath, argName, v), + number: (argName: string, v: unknown) => helpers.number(functionPath, argName, v), boolean: helpers.boolean, - getServer: (hostname: string) => helpers.getServer(hostname, functionName), + getServer: (hostname: string) => helpers.getServer(hostname, functionPath), checkSingularityAccess: () => helpers.checkSingularityAccess(functionName), hack: helpers.hack, - getValidPort: (port: any) => helpers.getValidPort(functionName, port), + getValidPort: (port: any) => helpers.getValidPort(functionPath, port), }, }; - function wrappedFunction(...args: unknown[]): T { + function wrappedFunction(...args: unknown[]): unknown { helpers.updateDynamicRam(ctx.function, getRamCost(Player, ...tree, ctx.function)); - return func(ctx, ...args); + return func(ctx)(...args); } const parent = getNestedProperty(wrappedAPI, ...tree); Object.defineProperty(parent, functionName, { value: wrappedFunction, writable: true, + enumerable: true }); } diff --git a/src/NetscriptFunctions/Stanek.ts b/src/NetscriptFunctions/Stanek.ts index 5dd2d53b4..644bd9115 100644 --- a/src/NetscriptFunctions/Stanek.ts +++ b/src/NetscriptFunctions/Stanek.ts @@ -26,88 +26,86 @@ export function NetscriptStanek( } return { - giftWidth: function (): number { + giftWidth: (_ctx: NetscriptContext) => function (): number { checkStanekAPIAccess("giftWidth"); return staneksGift.width(); }, - giftHeight: function (): number { + giftHeight: (_ctx: NetscriptContext) => function (): number { checkStanekAPIAccess("giftHeight"); return staneksGift.height(); }, - chargeFragment: function (ctx: NetscriptContext, _rootX: unknown, _rootY: unknown): Promise { - const rootX = ctx.helper.number("rootX", _rootX); - const rootY = ctx.helper.number("rootY", _rootY); + chargeFragment: (_ctx: NetscriptContext) => function (_rootX: unknown, _rootY: unknown): Promise { + const rootX = _ctx.helper.number("rootX", _rootX); + const rootY = _ctx.helper.number("rootY", _rootY); checkStanekAPIAccess("chargeFragment"); const fragment = staneksGift.findFragment(rootX, rootY); - if (!fragment) throw ctx.makeRuntimeErrorMsg(`No fragment with root (${rootX}, ${rootY}).`); + if (!fragment) throw _ctx.makeRuntimeErrorMsg(`No fragment with root (${rootX}, ${rootY}).`); const time = staneksGift.inBonus() ? 200 : 1000; return netscriptDelay(time, workerScript).then(function () { const charge = staneksGift.charge(player, fragment, workerScript.scriptRef.threads); - ctx.log(() => `Charged fragment for ${charge} charge.`); + _ctx.log(() => `Charged fragment for ${charge} charge.`); return Promise.resolve(); }); }, - fragmentDefinitions: function (ctx: NetscriptContext): IFragment[] { + fragmentDefinitions: (_ctx: NetscriptContext) => function (): IFragment[] { checkStanekAPIAccess("fragmentDefinitions"); - ctx.log(() => `Returned ${Fragments.length} fragments`); + _ctx.log(() => `Returned ${Fragments.length} fragments`); return Fragments.map((f) => f.copy()); }, - activeFragments: function (ctx: NetscriptContext): IActiveFragment[] { + activeFragments: (_ctx: NetscriptContext) => function (): IActiveFragment[] { checkStanekAPIAccess("activeFragments"); - ctx.log(() => `Returned ${staneksGift.fragments.length} fragments`); + _ctx.log(() => `Returned ${staneksGift.fragments.length} fragments`); return staneksGift.fragments.map((af) => { return { ...af.copy(), ...af.fragment().copy() }; }); }, - clearGift: function (ctx: NetscriptContext): void { + clearGift: (_ctx: NetscriptContext) => function (): void { checkStanekAPIAccess("clearGift"); - ctx.log(() => `Cleared Stanek's Gift.`); + _ctx.log(() => `Cleared Stanek's Gift.`); staneksGift.clear(); }, - canPlaceFragment: function ( - ctx: NetscriptContext, + canPlaceFragment: (_ctx: NetscriptContext) => function ( _rootX: unknown, _rootY: unknown, _rotation: unknown, _fragmentId: unknown, ): boolean { - const rootX = ctx.helper.number("rootX", _rootX); - const rootY = ctx.helper.number("rootY", _rootY); - const rotation = ctx.helper.number("rotation", _rotation); - const fragmentId = ctx.helper.number("fragmentId", _fragmentId); + const rootX = _ctx.helper.number("rootX", _rootX); + const rootY = _ctx.helper.number("rootY", _rootY); + const rotation = _ctx.helper.number("rotation", _rotation); + const fragmentId = _ctx.helper.number("fragmentId", _fragmentId); checkStanekAPIAccess("canPlaceFragment"); const fragment = FragmentById(fragmentId); - if (!fragment) throw ctx.makeRuntimeErrorMsg(`Invalid fragment id: ${fragmentId}`); + if (!fragment) throw _ctx.makeRuntimeErrorMsg(`Invalid fragment id: ${fragmentId}`); const can = staneksGift.canPlace(rootX, rootY, rotation, fragment); return can; }, - placeFragment: function ( - ctx: NetscriptContext, + placeFragment: (_ctx: NetscriptContext) => function ( _rootX: unknown, _rootY: unknown, _rotation: unknown, _fragmentId: unknown, ): boolean { - const rootX = ctx.helper.number("rootX", _rootX); - const rootY = ctx.helper.number("rootY", _rootY); - const rotation = ctx.helper.number("rotation", _rotation); - const fragmentId = ctx.helper.number("fragmentId", _fragmentId); + const rootX = _ctx.helper.number("rootX", _rootX); + const rootY = _ctx.helper.number("rootY", _rootY); + const rotation = _ctx.helper.number("rotation", _rotation); + const fragmentId = _ctx.helper.number("fragmentId", _fragmentId); checkStanekAPIAccess("placeFragment"); const fragment = FragmentById(fragmentId); - if (!fragment) throw ctx.makeRuntimeErrorMsg(`Invalid fragment id: ${fragmentId}`); + if (!fragment) throw _ctx.makeRuntimeErrorMsg(`Invalid fragment id: ${fragmentId}`); return staneksGift.place(rootX, rootY, rotation, fragment); }, - getFragment: function (ctx: NetscriptContext, _rootX: unknown, _rootY: unknown): IActiveFragment | undefined { - const rootX = ctx.helper.number("rootX", _rootX); - const rootY = ctx.helper.number("rootY", _rootY); + getFragment: (_ctx: NetscriptContext) => function (_rootX: unknown, _rootY: unknown): IActiveFragment | undefined { + const rootX = _ctx.helper.number("rootX", _rootX); + const rootY = _ctx.helper.number("rootY", _rootY); checkStanekAPIAccess("getFragment"); const fragment = staneksGift.findFragment(rootX, rootY); if (fragment !== undefined) return fragment.copy(); return undefined; }, - removeFragment: function (ctx: NetscriptContext, _rootX: unknown, _rootY: unknown): boolean { - const rootX = ctx.helper.number("rootX", _rootX); - const rootY = ctx.helper.number("rootY", _rootY); + removeFragment: (_ctx: NetscriptContext) => function (_rootX: unknown, _rootY: unknown): boolean { + const rootX = _ctx.helper.number("rootX", _rootX); + const rootY = _ctx.helper.number("rootY", _rootY); checkStanekAPIAccess("removeFragment"); return staneksGift.delete(rootX, rootY); }, From b2e7817a0bcc72c3b8e2c83710111bae2bbf91de Mon Sep 17 00:00:00 2001 From: TheMas3212 Date: Fri, 8 Apr 2022 10:02:59 +1000 Subject: [PATCH 6/7] format --- src/Netscript/APIWrapper.ts | 6 +- src/NetscriptFunctions/Stanek.ts | 166 +++++++++++++++---------------- 2 files changed, 86 insertions(+), 86 deletions(-) diff --git a/src/Netscript/APIWrapper.ts b/src/Netscript/APIWrapper.ts index f5ed8c860..a17c31392 100644 --- a/src/Netscript/APIWrapper.ts +++ b/src/Netscript/APIWrapper.ts @@ -11,7 +11,7 @@ type ExternalAPI = { }; type InternalFunction unknown> = ( - ctx: NetscriptContext + ctx: NetscriptContext, ) => (...args: unknown[]) => ReturnType; export type InternalAPI = { [Property in keyof API]: API[Property] extends ExternalFunction @@ -65,7 +65,7 @@ function wrapFunction( func: (_ctx: NetscriptContext) => (...args: unknown[]) => unknown, ...tree: string[] ): void { - const functionPath = tree.join('.'); + const functionPath = tree.join("."); const functionName = tree.pop(); if (typeof functionName !== "string") { throw makeRuntimeRejectMsg(workerScript, "Failure occured while wrapping netscript api"); @@ -99,7 +99,7 @@ function wrapFunction( Object.defineProperty(parent, functionName, { value: wrappedFunction, writable: true, - enumerable: true + enumerable: true, }); } diff --git a/src/NetscriptFunctions/Stanek.ts b/src/NetscriptFunctions/Stanek.ts index 644bd9115..2137582ff 100644 --- a/src/NetscriptFunctions/Stanek.ts +++ b/src/NetscriptFunctions/Stanek.ts @@ -26,88 +26,88 @@ export function NetscriptStanek( } return { - giftWidth: (_ctx: NetscriptContext) => function (): number { - checkStanekAPIAccess("giftWidth"); - return staneksGift.width(); - }, - giftHeight: (_ctx: NetscriptContext) => function (): number { - checkStanekAPIAccess("giftHeight"); - return staneksGift.height(); - }, - chargeFragment: (_ctx: NetscriptContext) => function (_rootX: unknown, _rootY: unknown): Promise { - const rootX = _ctx.helper.number("rootX", _rootX); - const rootY = _ctx.helper.number("rootY", _rootY); - checkStanekAPIAccess("chargeFragment"); - const fragment = staneksGift.findFragment(rootX, rootY); - if (!fragment) throw _ctx.makeRuntimeErrorMsg(`No fragment with root (${rootX}, ${rootY}).`); - const time = staneksGift.inBonus() ? 200 : 1000; - return netscriptDelay(time, workerScript).then(function () { - const charge = staneksGift.charge(player, fragment, workerScript.scriptRef.threads); - _ctx.log(() => `Charged fragment for ${charge} charge.`); - return Promise.resolve(); - }); - }, - fragmentDefinitions: (_ctx: NetscriptContext) => function (): IFragment[] { - checkStanekAPIAccess("fragmentDefinitions"); - _ctx.log(() => `Returned ${Fragments.length} fragments`); - return Fragments.map((f) => f.copy()); - }, - activeFragments: (_ctx: NetscriptContext) => function (): IActiveFragment[] { - checkStanekAPIAccess("activeFragments"); - _ctx.log(() => `Returned ${staneksGift.fragments.length} fragments`); - return staneksGift.fragments.map((af) => { - return { ...af.copy(), ...af.fragment().copy() }; - }); - }, - clearGift: (_ctx: NetscriptContext) => function (): void { - checkStanekAPIAccess("clearGift"); - _ctx.log(() => `Cleared Stanek's Gift.`); - staneksGift.clear(); - }, - canPlaceFragment: (_ctx: NetscriptContext) => function ( - _rootX: unknown, - _rootY: unknown, - _rotation: unknown, - _fragmentId: unknown, - ): boolean { - const rootX = _ctx.helper.number("rootX", _rootX); - const rootY = _ctx.helper.number("rootY", _rootY); - const rotation = _ctx.helper.number("rotation", _rotation); - const fragmentId = _ctx.helper.number("fragmentId", _fragmentId); - checkStanekAPIAccess("canPlaceFragment"); - const fragment = FragmentById(fragmentId); - if (!fragment) throw _ctx.makeRuntimeErrorMsg(`Invalid fragment id: ${fragmentId}`); - const can = staneksGift.canPlace(rootX, rootY, rotation, fragment); - return can; - }, - placeFragment: (_ctx: NetscriptContext) => function ( - _rootX: unknown, - _rootY: unknown, - _rotation: unknown, - _fragmentId: unknown, - ): boolean { - const rootX = _ctx.helper.number("rootX", _rootX); - const rootY = _ctx.helper.number("rootY", _rootY); - const rotation = _ctx.helper.number("rotation", _rotation); - const fragmentId = _ctx.helper.number("fragmentId", _fragmentId); - checkStanekAPIAccess("placeFragment"); - const fragment = FragmentById(fragmentId); - if (!fragment) throw _ctx.makeRuntimeErrorMsg(`Invalid fragment id: ${fragmentId}`); - return staneksGift.place(rootX, rootY, rotation, fragment); - }, - getFragment: (_ctx: NetscriptContext) => function (_rootX: unknown, _rootY: unknown): IActiveFragment | undefined { - const rootX = _ctx.helper.number("rootX", _rootX); - const rootY = _ctx.helper.number("rootY", _rootY); - checkStanekAPIAccess("getFragment"); - const fragment = staneksGift.findFragment(rootX, rootY); - if (fragment !== undefined) return fragment.copy(); - return undefined; - }, - removeFragment: (_ctx: NetscriptContext) => function (_rootX: unknown, _rootY: unknown): boolean { - const rootX = _ctx.helper.number("rootX", _rootX); - const rootY = _ctx.helper.number("rootY", _rootY); - checkStanekAPIAccess("removeFragment"); - return staneksGift.delete(rootX, rootY); - }, + giftWidth: (_ctx: NetscriptContext) => + function (): number { + checkStanekAPIAccess("giftWidth"); + return staneksGift.width(); + }, + giftHeight: (_ctx: NetscriptContext) => + function (): number { + checkStanekAPIAccess("giftHeight"); + return staneksGift.height(); + }, + chargeFragment: (_ctx: NetscriptContext) => + function (_rootX: unknown, _rootY: unknown): Promise { + const rootX = _ctx.helper.number("rootX", _rootX); + const rootY = _ctx.helper.number("rootY", _rootY); + checkStanekAPIAccess("chargeFragment"); + const fragment = staneksGift.findFragment(rootX, rootY); + if (!fragment) throw _ctx.makeRuntimeErrorMsg(`No fragment with root (${rootX}, ${rootY}).`); + const time = staneksGift.inBonus() ? 200 : 1000; + return netscriptDelay(time, workerScript).then(function () { + const charge = staneksGift.charge(player, fragment, workerScript.scriptRef.threads); + _ctx.log(() => `Charged fragment for ${charge} charge.`); + return Promise.resolve(); + }); + }, + fragmentDefinitions: (_ctx: NetscriptContext) => + function (): IFragment[] { + checkStanekAPIAccess("fragmentDefinitions"); + _ctx.log(() => `Returned ${Fragments.length} fragments`); + return Fragments.map((f) => f.copy()); + }, + activeFragments: (_ctx: NetscriptContext) => + function (): IActiveFragment[] { + checkStanekAPIAccess("activeFragments"); + _ctx.log(() => `Returned ${staneksGift.fragments.length} fragments`); + return staneksGift.fragments.map((af) => { + return { ...af.copy(), ...af.fragment().copy() }; + }); + }, + clearGift: (_ctx: NetscriptContext) => + function (): void { + checkStanekAPIAccess("clearGift"); + _ctx.log(() => `Cleared Stanek's Gift.`); + staneksGift.clear(); + }, + canPlaceFragment: (_ctx: NetscriptContext) => + function (_rootX: unknown, _rootY: unknown, _rotation: unknown, _fragmentId: unknown): boolean { + const rootX = _ctx.helper.number("rootX", _rootX); + const rootY = _ctx.helper.number("rootY", _rootY); + const rotation = _ctx.helper.number("rotation", _rotation); + const fragmentId = _ctx.helper.number("fragmentId", _fragmentId); + checkStanekAPIAccess("canPlaceFragment"); + const fragment = FragmentById(fragmentId); + if (!fragment) throw _ctx.makeRuntimeErrorMsg(`Invalid fragment id: ${fragmentId}`); + const can = staneksGift.canPlace(rootX, rootY, rotation, fragment); + return can; + }, + placeFragment: (_ctx: NetscriptContext) => + function (_rootX: unknown, _rootY: unknown, _rotation: unknown, _fragmentId: unknown): boolean { + const rootX = _ctx.helper.number("rootX", _rootX); + const rootY = _ctx.helper.number("rootY", _rootY); + const rotation = _ctx.helper.number("rotation", _rotation); + const fragmentId = _ctx.helper.number("fragmentId", _fragmentId); + checkStanekAPIAccess("placeFragment"); + const fragment = FragmentById(fragmentId); + if (!fragment) throw _ctx.makeRuntimeErrorMsg(`Invalid fragment id: ${fragmentId}`); + return staneksGift.place(rootX, rootY, rotation, fragment); + }, + getFragment: (_ctx: NetscriptContext) => + function (_rootX: unknown, _rootY: unknown): IActiveFragment | undefined { + const rootX = _ctx.helper.number("rootX", _rootX); + const rootY = _ctx.helper.number("rootY", _rootY); + checkStanekAPIAccess("getFragment"); + const fragment = staneksGift.findFragment(rootX, rootY); + if (fragment !== undefined) return fragment.copy(); + return undefined; + }, + removeFragment: (_ctx: NetscriptContext) => + function (_rootX: unknown, _rootY: unknown): boolean { + const rootX = _ctx.helper.number("rootX", _rootX); + const rootY = _ctx.helper.number("rootY", _rootY); + checkStanekAPIAccess("removeFragment"); + return staneksGift.delete(rootX, rootY); + }, }; } From f53c90b21c07e5b5b4ade55010107623760bbd2c Mon Sep 17 00:00:00 2001 From: TheMas3212 Date: Sat, 9 Apr 2022 15:15:45 +1000 Subject: [PATCH 7/7] Change Signature of InternalFunction Mark properties of Wrapped NetscriptAPI as readonly --- src/Netscript/APIWrapper.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Netscript/APIWrapper.ts b/src/Netscript/APIWrapper.ts index a17c31392..d3df414c8 100644 --- a/src/Netscript/APIWrapper.ts +++ b/src/Netscript/APIWrapper.ts @@ -10,9 +10,7 @@ type ExternalAPI = { [string: string]: ExternalAPI | ExternalFunction; }; -type InternalFunction unknown> = ( - ctx: NetscriptContext, -) => (...args: unknown[]) => ReturnType; +type InternalFunction unknown> = (ctx: NetscriptContext) => F; export type InternalAPI = { [Property in keyof API]: API[Property] extends ExternalFunction ? InternalFunction @@ -23,7 +21,7 @@ export type InternalAPI = { type WrappedNetscriptFunction = (...args: unknown[]) => unknown; type WrappedNetscriptAPI = { - [string: string]: WrappedNetscriptAPI | WrappedNetscriptFunction; + readonly [string: string]: WrappedNetscriptAPI | WrappedNetscriptFunction; }; export type NetscriptContext = { @@ -47,7 +45,6 @@ type NetscriptHelpers = { }; type WrappedNetscriptHelpers = { - updateDynamicRam: (ramCost: number) => void; makeRuntimeErrorMsg: (msg: string) => string; string: (argName: string, v: unknown) => string; number: (argName: string, v: unknown) => number; @@ -80,7 +77,6 @@ function wrapFunction( workerScript, function: functionName, helper: { - updateDynamicRam: (ramCost: number) => helpers.updateDynamicRam(functionName, ramCost), makeRuntimeErrorMsg: (msg: string) => helpers.makeRuntimeErrorMsg(functionPath, msg), string: (argName: string, v: unknown) => helpers.string(functionPath, argName, v), number: (argName: string, v: unknown) => helpers.number(functionPath, argName, v),