diff --git a/src/Gang/formulas/formulas.ts b/src/Gang/formulas/formulas.ts index 93a793dba..8d05b9247 100644 --- a/src/Gang/formulas/formulas.ts +++ b/src/Gang/formulas/formulas.ts @@ -2,17 +2,17 @@ import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers"; import { GangMember } from "../GangMember"; import { GangMemberTask } from "../GangMemberTask"; -interface Gang { +export interface FormulaGang { respect: number; territory: number; wantedLevel: number; } -export function calculateWantedPenalty(gang: Gang): number { +export function calculateWantedPenalty(gang: FormulaGang): number { return gang.respect / (gang.respect + gang.wantedLevel); } -export function calculateRespectGain(gang: Gang, member: GangMember, task: GangMemberTask): number { +export function calculateRespectGain(gang: FormulaGang, member: GangMember, task: GangMemberTask): number { if (task.baseRespect === 0) return 0; let statWeight = (task.hackWeight / 100) * member.hack + @@ -30,7 +30,7 @@ export function calculateRespectGain(gang: Gang, member: GangMember, task: GangM return Math.pow(11 * task.baseRespect * statWeight * territoryMult * respectMult, territoryPenalty); } -export function calculateWantedLevelGain(gang: Gang, member: GangMember, task: GangMemberTask): number { +export function calculateWantedLevelGain(gang: FormulaGang, member: GangMember, task: GangMemberTask): number { if (task.baseWanted === 0) return 0; let statWeight = (task.hackWeight / 100) * member.hack + @@ -53,7 +53,7 @@ export function calculateWantedLevelGain(gang: Gang, member: GangMember, task: G return Math.min(100, calc); } -export function calculateMoneyGain(gang: Gang, member: GangMember, task: GangMemberTask): number { +export function calculateMoneyGain(gang: FormulaGang, member: GangMember, task: GangMemberTask): number { if (task.baseMoney === 0) return 0; let statWeight = (task.hackWeight / 100) * member.hack + diff --git a/src/Netscript/APIWrapper.ts b/src/Netscript/APIWrapper.ts index e18925957..138cf9418 100644 --- a/src/Netscript/APIWrapper.ts +++ b/src/Netscript/APIWrapper.ts @@ -6,6 +6,12 @@ import { makeRuntimeRejectMsg } from "../NetscriptEvaluator"; import { Player } from "../Player"; import { CityName } from "../Locations/data/CityNames"; import { BasicHGWOptions } from "../ScriptEditor/NetscriptDefinitions"; +import { IPlayer } from "../PersonObjects/IPlayer"; +import { Server } from "../Server/Server"; +import { FormulaGang } from "../Gang/formulas/formulas"; +import { INetscriptHelper } from "../NetscriptFunctions/INetscriptHelper"; +import { GangMember } from "../Gang/GangMember"; +import { GangMemberTask } from "../Gang/GangMemberTask"; type ExternalFunction = (...args: unknown[]) => unknown; export type ExternalAPI = { @@ -35,24 +41,6 @@ export type NetscriptContext = { helper: WrappedNetscriptHelpers; }; -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; - city: (funcName: string, argName: string, v: unknown) => CityName; - boolean: (v: unknown) => boolean; - getServer: (hostname: string, ctx: NetscriptContext) => BaseServer; - checkSingularityAccess: (func: string) => void; - hack: ( - ctx: NetscriptContext, - hostname: string, - manual: boolean, - { threads: requestedThreads, stock }?: BasicHGWOptions, - ) => Promise; - getValidPort: (funcName: string, port: number) => IPort; -}; - type WrappedNetscriptHelpers = { makeRuntimeErrorMsg: (msg: string) => string; string: (argName: string, v: unknown) => string; @@ -63,10 +51,15 @@ type WrappedNetscriptHelpers = { checkSingularityAccess: () => void; hack: (hostname: string, manual: boolean, { threads: requestedThreads, stock }?: BasicHGWOptions) => Promise; getValidPort: (port: number) => IPort; + player(p: unknown): IPlayer; + server(s: unknown): Server; + gang(g: unknown): FormulaGang; + gangMember(m: unknown): GangMember; + gangTask(t: unknown): GangMemberTask; }; function wrapFunction( - helpers: NetscriptHelpers, + helpers: INetscriptHelper, wrappedAPI: ExternalAPI, workerScript: WorkerScript, func: (_ctx: NetscriptContext) => (...args: unknown[]) => unknown, @@ -96,6 +89,11 @@ function wrapFunction( checkSingularityAccess: () => helpers.checkSingularityAccess(functionName), hack: (hostname: string, manual: boolean, extra?: BasicHGWOptions) => helpers.hack(ctx, hostname, manual, extra), getValidPort: (port: number) => helpers.getValidPort(functionPath, port), + player: (p: unknown) => helpers.player(functionPath, p), + server: (s: unknown) => helpers.server(functionPath, s), + gang: (g: unknown) => helpers.gang(functionPath, g), + gangMember: (m: unknown) => helpers.gangMember(functionPath, m), + gangTask: (t: unknown) => helpers.gangTask(functionPath, t), }, }; function wrappedFunction(...args: unknown[]): unknown { @@ -111,7 +109,7 @@ function wrapFunction( } export function wrapAPI( - helpers: NetscriptHelpers, + helpers: INetscriptHelper, wrappedAPI: ExternalAPI, workerScript: WorkerScript, // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types diff --git a/src/NetscriptFunctions.ts b/src/NetscriptFunctions.ts index d9629be5f..f9babe65a 100644 --- a/src/NetscriptFunctions.ts +++ b/src/NetscriptFunctions.ts @@ -57,6 +57,7 @@ import { convertTimeMsToTimeElapsedString } from "./utils/StringHelperFunctions" import { LogBoxEvents, LogBoxCloserEvents } from "./ui/React/LogBoxManager"; import { arrayToString } from "./utils/helpers/arrayToString"; import { isString } from "./utils/helpers/isString"; +import { FormulaGang as FormulaGang } from "./Gang/formulas/formulas"; import { BaseServer } from "./Server/BaseServer"; import { NetscriptGang } from "./NetscriptFunctions/Gang"; @@ -108,6 +109,10 @@ import { recentScripts } from "./Netscript/RecentScripts"; import { CityName } from "./Locations/data/CityNames"; import { InternalAPI, NetscriptContext, wrapAPI } from "./Netscript/APIWrapper"; import { INetscriptHelper } from "./NetscriptFunctions/INetscriptHelper"; +import { IPlayer } from "./PersonObjects/IPlayer"; +import { PlayerObject } from "./PersonObjects/Player/PlayerObject"; +import { GangMember } from "./Gang/GangMember"; +import { GangMemberTask } from "./Gang/GangMemberTask"; interface NS extends INS { [key: string]: any; @@ -463,6 +468,14 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS { return out; }; + const roughlyIs = (expect: object, actual: unknown): boolean => { + if (typeof actual !== "object" || actual == null) return false; + const expects = Object.keys(expect); + const actuals = Object.keys(actual); + for (const expect of expects) if (!actuals.includes(expect)) return false; + return true; + }; + const helper: INetscriptHelper = { updateDynamicRam: updateDynamicRam, makeRuntimeErrorMsg: makeRuntimeErrorMsg, @@ -514,6 +527,28 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS { } return iport; }, + player(funcName: string, p: unknown): IPlayer { + if (!roughlyIs(new PlayerObject(), p)) throw makeRuntimeErrorMsg(funcName, `player should be a Player.`); + return p as IPlayer; + }, + server(funcName: string, s: unknown): Server { + if (!roughlyIs(new Server(), s)) throw makeRuntimeErrorMsg(funcName, `server should be a Server.`); + return s as Server; + }, + gang(funcName: string, g: unknown): FormulaGang { + if (!roughlyIs({ respect: 0, territory: 0, wantedLevel: 0 }, g)) + throw makeRuntimeErrorMsg(funcName, `gang should be a Gang.`); + return g as FormulaGang; + }, + gangMember(funcName: string, m: unknown): GangMember { + if (!roughlyIs(new GangMember(), m)) throw makeRuntimeErrorMsg(funcName, `member should be a GangMember.`); + return m as GangMember; + }, + gangTask(funcName: string, t: unknown): GangMemberTask { + if (!roughlyIs(new GangMemberTask("", "", false, false, {}), t)) + throw makeRuntimeErrorMsg(funcName, `task should be a GangMemberTask.`); + return t as GangMemberTask; + }, }; const singularity = NetscriptSingularity(Player, workerScript); diff --git a/src/NetscriptFunctions/Corporation.ts b/src/NetscriptFunctions/Corporation.ts index 6dc698816..98aeb7e2b 100644 --- a/src/NetscriptFunctions/Corporation.ts +++ b/src/NetscriptFunctions/Corporation.ts @@ -21,6 +21,7 @@ import { WarehouseAPI, OfficeAPI, InvestmentOffer, + Office as NSOffice, } from "../ScriptEditor/NetscriptDefinitions"; import { @@ -733,7 +734,7 @@ export function NetscriptCorporation(player: IPlayer, workerScript: WorkerScript }, hireEmployee: (ctx: NetscriptContext) => - (_divisionName: unknown, _cityName: unknown): any => { + (_divisionName: unknown, _cityName: unknown): NSEmployee | undefined => { checkAccess(ctx, 8); const divisionName = ctx.helper.string("divisionName", _divisionName); const cityName = ctx.helper.city("cityName", _cityName); @@ -817,7 +818,7 @@ export function NetscriptCorporation(player: IPlayer, workerScript: WorkerScript }, getOffice: (ctx: NetscriptContext) => - (_divisionName: unknown, _cityName: unknown): any => { + (_divisionName: unknown, _cityName: unknown): NSOffice => { checkAccess(ctx, 8); const divisionName = ctx.helper.string("divisionName", _divisionName); const cityName = ctx.helper.city("cityName", _cityName); @@ -838,6 +839,7 @@ export function NetscriptCorporation(player: IPlayer, workerScript: WorkerScript Management: office.employeeProd[EmployeePositions.Management], "Research & Development": office.employeeProd[EmployeePositions.RandD], Training: office.employeeProd[EmployeePositions.Training], + Unassigned: 0, }, employeeJobs: { Operations: office.employeeJobs[EmployeePositions.Operations], diff --git a/src/NetscriptFunctions/Formulas.ts b/src/NetscriptFunctions/Formulas.ts index 37d986b6b..f7ed0797d 100644 --- a/src/NetscriptFunctions/Formulas.ts +++ b/src/NetscriptFunctions/Formulas.ts @@ -27,7 +27,11 @@ import { calculateWeakenTime, } from "../Hacking"; import { Programs } from "../Programs/Programs"; -import { Formulas as IFormulas } from "../ScriptEditor/NetscriptDefinitions"; +import { + Formulas as IFormulas, + HacknetNodeConstants as DefHacknetNodeConstants, + HacknetServerConstants as DefHacknetServerConstants, +} from "../ScriptEditor/NetscriptDefinitions"; import { calculateRespectGain, calculateWantedLevelGain, @@ -64,8 +68,9 @@ export function NetscriptFormulas(player: IPlayer, helper: INetscriptHelper): In }, repFromDonation: (ctx: NetscriptContext) => - (_amount: unknown, player: any): number => { + (_amount: unknown, _player: unknown): number => { const amount = ctx.helper.number("amount", _amount); + const player = ctx.helper.player(_player); checkFormulasAccess(ctx); return repFromDonation(amount, player); }, @@ -91,25 +96,33 @@ export function NetscriptFormulas(player: IPlayer, helper: INetscriptHelper): In hacking: { hackChance: (ctx: NetscriptContext) => - (server: any, player: any): number => { + (_server: unknown, _player: unknown): number => { + const server = ctx.helper.server(_server); + const player = ctx.helper.player(_player); checkFormulasAccess(ctx); return calculateHackingChance(server, player); }, hackExp: (ctx: NetscriptContext) => - (server: any, player: any): number => { + (_server: unknown, _player: unknown): number => { + const server = ctx.helper.server(_server); + const player = ctx.helper.player(_player); checkFormulasAccess(ctx); return calculateHackingExpGain(server, player); }, hackPercent: (ctx: NetscriptContext) => - (server: any, player: any): number => { + (_server: unknown, _player: unknown): number => { + const server = ctx.helper.server(_server); + const player = ctx.helper.player(_player); checkFormulasAccess(ctx); return calculatePercentMoneyHacked(server, player); }, growPercent: (ctx: NetscriptContext) => - (server: any, _threads: unknown, player: any, _cores: unknown = 1): number => { + (_server: unknown, _threads: unknown, _player: unknown, _cores: unknown = 1): number => { + const server = ctx.helper.server(_server); + const player = ctx.helper.player(_player); const threads = ctx.helper.number("threads", _threads); const cores = ctx.helper.number("cores", _cores); checkFormulasAccess(ctx); @@ -117,19 +130,25 @@ export function NetscriptFormulas(player: IPlayer, helper: INetscriptHelper): In }, hackTime: (ctx: NetscriptContext) => - (server: any, player: any): number => { + (_server: unknown, _player: unknown): number => { + const server = ctx.helper.server(_server); + const player = ctx.helper.player(_player); checkFormulasAccess(ctx); return calculateHackingTime(server, player) * 1000; }, growTime: (ctx: NetscriptContext) => - (server: any, player: any): number => { + (_server: unknown, _player: unknown): number => { + const server = ctx.helper.server(_server); + const player = ctx.helper.player(_player); checkFormulasAccess(ctx); return calculateGrowTime(server, player) * 1000; }, weakenTime: (ctx: NetscriptContext) => - (server: any, player: any): number => { + (_server: unknown, _player: unknown): number => { + const server = ctx.helper.server(_server); + const player = ctx.helper.player(_player); checkFormulasAccess(ctx); return calculateWeakenTime(server, player) * 1000; }, @@ -180,7 +199,7 @@ export function NetscriptFormulas(player: IPlayer, helper: INetscriptHelper): In checkFormulasAccess(ctx); return calculateNodeCost(n, mult); }, - constants: (ctx: NetscriptContext) => (): any => { + constants: (ctx: NetscriptContext) => (): DefHacknetNodeConstants => { checkFormulasAccess(ctx); return Object.assign({}, HacknetNodeConstants); }, @@ -255,7 +274,7 @@ export function NetscriptFormulas(player: IPlayer, helper: INetscriptHelper): In checkFormulasAccess(ctx); return HScalculateServerCost(n, mult); }, - constants: (ctx: NetscriptContext) => (): any => { + constants: (ctx: NetscriptContext) => (): DefHacknetServerConstants => { checkFormulasAccess(ctx); return Object.assign({}, HacknetServerConstants); }, @@ -263,25 +282,35 @@ export function NetscriptFormulas(player: IPlayer, helper: INetscriptHelper): In gang: { wantedPenalty: (ctx: NetscriptContext) => - (gang: any): number => { + (_gang: unknown): number => { + const gang = ctx.helper.gang(_gang); checkFormulasAccess(ctx); return calculateWantedPenalty(gang); }, respectGain: (ctx: NetscriptContext) => - (gang: any, member: any, task: any): number => { + (_gang: unknown, _member: unknown, _task: unknown): number => { + const gang = ctx.helper.gang(_gang); + const member = ctx.helper.gangMember(_member); + const task = ctx.helper.gangTask(_task); checkFormulasAccess(ctx); return calculateRespectGain(gang, member, task); }, wantedLevelGain: (ctx: NetscriptContext) => - (gang: any, member: any, task: any): number => { + (_gang: unknown, _member: unknown, _task: unknown): number => { + const gang = ctx.helper.gang(_gang); + const member = ctx.helper.gangMember(_member); + const task = ctx.helper.gangTask(_task); checkFormulasAccess(ctx); return calculateWantedLevelGain(gang, member, task); }, moneyGain: (ctx: NetscriptContext) => - (gang: any, member: any, task: any): number => { + (_gang: unknown, _member: unknown, _task: unknown): number => { + const gang = ctx.helper.gang(_gang); + const member = ctx.helper.gangMember(_member); + const task = ctx.helper.gangTask(_task); checkFormulasAccess(ctx); return calculateMoneyGain(gang, member, task); }, diff --git a/src/NetscriptFunctions/INetscriptHelper.ts b/src/NetscriptFunctions/INetscriptHelper.ts index 7fab1c2dd..962fab16a 100644 --- a/src/NetscriptFunctions/INetscriptHelper.ts +++ b/src/NetscriptFunctions/INetscriptHelper.ts @@ -1,7 +1,13 @@ -import { CityName } from "src/Locations/data/CityNames"; -import { NetscriptContext } from "src/Netscript/APIWrapper"; -import { IPort } from "src/NetscriptPort"; +import { CityName } from "../Locations/data/CityNames"; +import { NetscriptContext } from "../Netscript/APIWrapper"; +import { IPort } from "../NetscriptPort"; +import { IPlayer } from "../PersonObjects/IPlayer"; +import { Server } from "../Server/Server"; import { BaseServer } from "../Server/BaseServer"; +import { FormulaGang } from "../Gang/formulas/formulas"; +import { GangMember } from "../Gang/GangMember"; +import { GangMemberTask } from "../Gang/GangMemberTask"; +import { BasicHGWOptions } from "../ScriptEditor/NetscriptDefinitions"; export interface INetscriptHelper { updateDynamicRam(functionName: string, ram: number): void; @@ -12,6 +18,11 @@ export interface INetscriptHelper { boolean(v: unknown): boolean; getServer(ip: string, ctx: NetscriptContext): BaseServer; checkSingularityAccess(func: string): void; - hack(ctx: NetscriptContext, hostname: string, manual: boolean): Promise; + hack(ctx: NetscriptContext, hostname: string, manual: boolean, extra?: BasicHGWOptions): Promise; getValidPort(funcName: string, port: number): IPort; + player(funcName: string, p: unknown): IPlayer; + server(funcName: string, s: unknown): Server; + gang(funcName: string, g: unknown): FormulaGang; + gangMember(funcName: string, m: unknown): GangMember; + gangTask(funcName: string, m: unknown): GangMemberTask; } diff --git a/src/ScriptEditor/NetscriptDefinitions.d.ts b/src/ScriptEditor/NetscriptDefinitions.d.ts index 430ca7bb7..d656239c0 100644 --- a/src/ScriptEditor/NetscriptDefinitions.d.ts +++ b/src/ScriptEditor/NetscriptDefinitions.d.ts @@ -7070,7 +7070,7 @@ interface CorporationInfo { * Employee in an office * @public */ -interface Employee { +export interface Employee { /** Name of the employee */ name: string; /** Morale of the employee */ @@ -7170,7 +7170,7 @@ interface Warehouse { * Office for a division in a city. * @public */ -interface Office { +export interface Office { /** City of the office */ loc: string; /** Maximum number of employee */ diff --git a/src/ScriptEditor/ui/ScriptEditorRoot.tsx b/src/ScriptEditor/ui/ScriptEditorRoot.tsx index c09e5cedd..c6e1116be 100644 --- a/src/ScriptEditor/ui/ScriptEditorRoot.tsx +++ b/src/ScriptEditor/ui/ScriptEditorRoot.tsx @@ -193,9 +193,9 @@ export function Root(props: IProps): React.ReactElement { // setup monaco-vim if (options.vim && editor && !vimEditor) { try { - // This library is not typed // @ts-expect-error window.require(["monaco-vim"], function (MonacoVim: any) { + console.log(MonacoVim); setVimEditor(MonacoVim.initVimMode(editor, vimStatusRef.current)); MonacoVim.VimMode.Vim.defineEx("write", "w", function () { // your own implementation on what you want to do when :w is pressed @@ -212,7 +212,7 @@ export function Root(props: IProps): React.ReactElement { // Setup "go to next tab" and "go to previous tab". This is a little more involved // since these aren't Ex commands (they run in normal mode, not after typing `:`) - MonacoVim.VimMode.Vim.defineAction("nextTabs", function (_cm: any, args: { repeat?: number }) { + MonacoVim.VimMode.Vim.defineAction("nextTabs", function (_cm: unknown, args: { repeat?: number }) { const nTabs = args.repeat ?? 1; // Go to the next tab (to the right). Wraps around when at the rightmost tab const currIndex = currentTabIndex(); @@ -221,7 +221,7 @@ export function Root(props: IProps): React.ReactElement { onTabClick(nextIndex); } }); - MonacoVim.VimMode.Vim.defineAction("prevTabs", function (_cm: any, args: { repeat?: number }) { + MonacoVim.VimMode.Vim.defineAction("prevTabs", function (_cm: unknown, args: { repeat?: number }) { const nTabs = args.repeat ?? 1; // Go to the previous tab (to the left). Wraps around when at the leftmost tab const currIndex = currentTabIndex();