MISC: change all nextUpdates to use one Promise (#1069)

This commit is contained in:
Caldwell 2024-02-10 12:27:47 +01:00 committed by GitHub
parent fbc41d0278
commit 8c2a23f2ba
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 59 additions and 39 deletions

@ -1,3 +1,4 @@
import type { PromisePair } from "../Types/Promises";
import { AugmentationName, CityName, FactionName } from "@enums"; import { AugmentationName, CityName, FactionName } from "@enums";
import { constructorsForReviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../utils/JSONReviver"; import { constructorsForReviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../utils/JSONReviver";
import { ActionIdentifier } from "./ActionIdentifier"; import { ActionIdentifier } from "./ActionIdentifier";
@ -42,8 +43,7 @@ export interface BlackOpsAttempt {
isAvailable?: boolean; isAvailable?: boolean;
action?: BlackOperation; action?: BlackOperation;
} }
export const BladeburnerPromise: PromisePair<number> = { promise: null, resolve: null };
export const BladeburnerResolvers: ((msProcessed: number) => void)[] = [];
export class Bladeburner { export class Bladeburner {
numHosp = 0; numHosp = 0;
@ -2085,9 +2085,11 @@ export class Bladeburner {
} }
} }
// Handle "nextUpdate" resolvers after this update // Handle "nextUpdate" resolver after this update
for (const resolve of BladeburnerResolvers.splice(0)) { if (BladeburnerPromise.resolve) {
resolve(seconds * 1000); BladeburnerPromise.resolve(seconds * 1000);
BladeburnerPromise.resolve = null;
BladeburnerPromise.promise = null;
} }
} }
} }

@ -1,3 +1,4 @@
import type { PromisePair } from "../Types/Promises";
import { Player } from "@player"; import { Player } from "@player";
import { CorpStateName, InvestmentOffer } from "@nsdefs"; import { CorpStateName, InvestmentOffer } from "@nsdefs";
import { CorpUnlockName, CorpUpgradeName, LiteratureName } from "@enums"; import { CorpUnlockName, CorpUpgradeName, LiteratureName } from "@enums";
@ -19,7 +20,7 @@ import { formatMoney } from "../ui/formatNumber";
import { isPositiveInteger } from "../types"; import { isPositiveInteger } from "../types";
import { createEnumKeyedRecord, getRecordValues } from "../Types/Record"; import { createEnumKeyedRecord, getRecordValues } from "../Types/Record";
export const CorporationResolvers: ((prevState: CorpStateName) => void)[] = []; export const CorporationPromise: PromisePair<CorpStateName> = { promise: null, resolve: null };
interface ICorporationParams { interface ICorporationParams {
name?: string; name?: string;
@ -175,9 +176,11 @@ export class Corporation {
this.state.incrementState(); this.state.incrementState();
// Handle "nextUpdate" resolvers after this update // Handle "nextUpdate" resolver after this update
for (const resolve of CorporationResolvers.splice(0)) { if (CorporationPromise.resolve) {
resolve(state); CorporationPromise.resolve(state);
CorporationPromise.resolve = null;
CorporationPromise.promise = null;
} }
} }
} }

@ -3,6 +3,7 @@
* Add police clashes * Add police clashes
* balance point to keep them from running out of control * balance point to keep them from running out of control
*/ */
import type { PromisePair } from "../Types/Promises";
import { Factions } from "../Faction/Factions"; import { Factions } from "../Faction/Factions";
@ -26,8 +27,7 @@ import { PowerMultiplier } from "./data/power";
import { FactionName } from "@enums"; import { FactionName } from "@enums";
import { CONSTANTS } from "../Constants"; import { CONSTANTS } from "../Constants";
type NextUpdateData = { resolver: ((msProcessed: number) => void) | null; promise: Promise<number> | null }; export const GangPromise: PromisePair<number> = { promise: null, resolve: null };
export const GangNextUpdate: NextUpdateData = { resolver: null, promise: null };
export class Gang { export class Gang {
facName: FactionName; facName: FactionName;
@ -108,10 +108,10 @@ export class Gang {
} }
// Handle "nextUpdate" resolver after this update // Handle "nextUpdate" resolver after this update
if (GangNextUpdate.resolver) { if (GangPromise.resolve) {
GangNextUpdate.resolver(cycles * CONSTANTS.MilliPerCycle); GangPromise.resolve(cycles * CONSTANTS.MilliPerCycle);
GangNextUpdate.resolver = null; GangPromise.resolve = null;
GangNextUpdate.promise = null; GangPromise.promise = null;
} }
} }

@ -3,7 +3,7 @@ import type { Action } from "../Bladeburner/Action";
import type { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper"; import type { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
import { Player } from "@player"; import { Player } from "@player";
import { Bladeburner, BladeburnerResolvers } from "../Bladeburner/Bladeburner"; import { Bladeburner, BladeburnerPromise } from "../Bladeburner/Bladeburner";
import { currentNodeMults } from "../BitNode/BitNodeMultipliers"; import { currentNodeMults } from "../BitNode/BitNodeMultipliers";
import { BlackOperation } from "../Bladeburner/BlackOperation"; import { BlackOperation } from "../Bladeburner/BlackOperation";
import { helpers } from "../Netscript/NetscriptHelpers"; import { helpers } from "../Netscript/NetscriptHelpers";
@ -329,8 +329,11 @@ export function NetscriptBladeburner(): InternalAPI<INetscriptBladeburner> {
const bladeburner = getBladeburner(ctx); const bladeburner = getBladeburner(ctx);
return Math.round(bladeburner.storedCycles / 5) * 1000; return Math.round(bladeburner.storedCycles / 5) * 1000;
}, },
nextUpdate: () => () => { nextUpdate: (ctx) => () => {
return new Promise<number>((res) => BladeburnerResolvers.push(res)); checkBladeburnerAccess(ctx);
if (!BladeburnerPromise.promise)
BladeburnerPromise.promise = new Promise<number>((res) => (BladeburnerPromise.resolve = res));
return BladeburnerPromise.promise;
}, },
}; };
} }

@ -5,7 +5,7 @@ import { Product } from "../Corporation/Product";
import { Material } from "../Corporation/Material"; import { Material } from "../Corporation/Material";
import { Warehouse } from "../Corporation/Warehouse"; import { Warehouse } from "../Corporation/Warehouse";
import { Division } from "../Corporation/Division"; import { Division } from "../Corporation/Division";
import { Corporation, CorporationResolvers } from "../Corporation/Corporation"; import { Corporation, CorporationPromise } from "../Corporation/Corporation";
import { omit } from "lodash"; import { omit } from "lodash";
import { setDeprecatedProperties } from "../utils/DeprecationHelper"; import { setDeprecatedProperties } from "../utils/DeprecationHelper";
import { import {
@ -800,7 +800,9 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
}, },
nextUpdate: (ctx) => () => { nextUpdate: (ctx) => () => {
checkAccess(ctx); checkAccess(ctx);
return new Promise<CorpStateName>((res) => CorporationResolvers.push(res)); if (!CorporationPromise.promise)
CorporationPromise.promise = new Promise<CorpStateName>((res) => (CorporationPromise.resolve = res));
return CorporationPromise.promise;
}, },
}; };

@ -4,7 +4,7 @@ import type { GangMember } from "../Gang/GangMember";
import type { GangMemberTask } from "../Gang/GangMemberTask"; import type { GangMemberTask } from "../Gang/GangMemberTask";
import type { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper"; import type { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
import { GangNextUpdate } from "../Gang/Gang"; import { GangPromise } from "../Gang/Gang";
import { Player } from "@player"; import { Player } from "@player";
import { FactionName } from "@enums"; import { FactionName } from "@enums";
import { GangConstants } from "../Gang/data/Constants"; import { GangConstants } from "../Gang/data/Constants";
@ -324,11 +324,10 @@ export function NetscriptGang(): InternalAPI<IGang> {
const gang = getGang(ctx); const gang = getGang(ctx);
return Math.round(gang.storedCycles / 5) * 1000; return Math.round(gang.storedCycles / 5) * 1000;
}, },
nextUpdate: () => () => { nextUpdate: (ctx) => () => {
if (!GangNextUpdate.promise) { getGang(ctx);
GangNextUpdate.promise = new Promise<number>((res) => (GangNextUpdate.resolver = res)); if (!GangPromise.promise) GangPromise.promise = new Promise<number>((res) => (GangPromise.resolve = res));
} return GangPromise.promise;
return GangNextUpdate.promise;
}, },
}; };
} }

@ -6,7 +6,7 @@ import {
placeOrder, placeOrder,
cancelOrder, cancelOrder,
initStockMarket, initStockMarket,
StockMarketResolvers, StockMarketPromise,
} from "../StockMarket/StockMarket"; } from "../StockMarket/StockMarket";
import { getBuyTransactionCost, getSellTransactionGain } from "../StockMarket/StockMarketHelpers"; import { getBuyTransactionCost, getSellTransactionGain } from "../StockMarket/StockMarketHelpers";
import { PositionType, OrderType, StockSymbol } from "@enums"; import { PositionType, OrderType, StockSymbol } from "@enums";
@ -415,7 +415,9 @@ export function NetscriptStockMarket(): InternalAPI<TIX> {
}, },
nextUpdate: (ctx) => () => { nextUpdate: (ctx) => () => {
checkTixApiAccess(ctx); checkTixApiAccess(ctx);
return new Promise<number>((res) => StockMarketResolvers.push(res)); if (!StockMarketPromise.promise)
StockMarketPromise.promise = new Promise<number>((res) => (StockMarketPromise.resolve = res));
return StockMarketPromise.promise;
}, },
}; };
} }

@ -24,11 +24,11 @@ export class SleeveBladeburnerWork extends SleeveWorkClass {
signalCompletion = () => { signalCompletion = () => {
// Intentionally empty function, this is just an initial value and will never be used. // Intentionally empty function, this is just an initial value and will never be used.
}; };
nextCompletion: Promise<void>; nextCompletionPromise: Promise<void> | null;
constructor(params?: SleeveBladeburnerWorkParams) { constructor(params?: SleeveBladeburnerWorkParams) {
super(); super();
this.nextCompletion = new Promise((r) => (this.signalCompletion = r)); this.nextCompletionPromise = null;
this.actionType = params?.type ?? "General"; this.actionType = params?.type ?? "General";
this.actionName = params?.name ?? "Field Analysis"; this.actionName = params?.name ?? "Field Analysis";
} }
@ -40,7 +40,7 @@ export class SleeveBladeburnerWork extends SleeveWorkClass {
} }
finish() { finish() {
this.signalCompletion(); if (this.nextCompletionPromise) this.signalCompletion();
} }
process(sleeve: Sleeve, cycles: number) { process(sleeve: Sleeve, cycles: number) {
@ -73,11 +73,13 @@ export class SleeveBladeburnerWork extends SleeveWorkClass {
this.tasksCompleted++; this.tasksCompleted++;
this.cyclesWorked -= this.cyclesNeeded(sleeve); this.cyclesWorked -= this.cyclesNeeded(sleeve);
// Resolve and reset nextCompletion promise // Resolve and reset nextCompletion promise
const resolver = this.signalCompletion; if (this.nextCompletionPromise) this.signalCompletion();
this.nextCompletion = new Promise((r) => (this.signalCompletion = r));
resolver();
} }
} }
get nextCompletion(): Promise<void> {
if (!this.nextCompletionPromise) this.nextCompletionPromise = new Promise((r) => (this.signalCompletion = r));
return this.nextCompletionPromise;
}
APICopy(sleeve: Sleeve) { APICopy(sleeve: Sleeve) {
return { return {

@ -1,3 +1,4 @@
import type { PromisePair } from "../Types/Promises";
import type { IOrderBook } from "./IOrderBook"; import type { IOrderBook } from "./IOrderBook";
import type { IStockMarket } from "./IStockMarket"; import type { IStockMarket } from "./IStockMarket";
import { Order } from "./Order"; import { Order } from "./Order";
@ -25,7 +26,7 @@ export let StockMarket: IStockMarket = {
// Gross type, needs to be addressed // Gross type, needs to be addressed
export const SymbolToStockMap: Record<string, Stock> = {}; // Maps symbol -> Stock object export const SymbolToStockMap: Record<string, Stock> = {}; // Maps symbol -> Stock object
export const StockMarketResolvers: ((msProcessed: number) => void)[] = []; export const StockMarketPromise: PromisePair<number> = { promise: null, resolve: null };
export function placeOrder( export function placeOrder(
stock: Stock, stock: Stock,
@ -280,9 +281,10 @@ export function processStockPrices(numCycles = 1): void {
// Shares required for price movement gradually approaches max over time // Shares required for price movement gradually approaches max over time
stock.shareTxUntilMovement = Math.min(stock.shareTxUntilMovement + 10, stock.shareTxForMovement); stock.shareTxUntilMovement = Math.min(stock.shareTxUntilMovement + 10, stock.shareTxForMovement);
} }
// Handle "nextUpdate" resolver after this update
// Handle "nextUpdate" resolvers after this update if (StockMarketPromise.resolve) {
for (const resolve of StockMarketResolvers.splice(0)) { StockMarketPromise.resolve(StockMarketConstants.msPerStockUpdate);
resolve(StockMarketConstants.msPerStockUpdate); StockMarketPromise.resolve = null;
StockMarketPromise.promise = null;
} }
} }

5
src/Types/Promises.ts Normal file

@ -0,0 +1,5 @@
// An object that contains a promise and its resolver (or possibly null)
export type PromisePair<ReturnType> = {
promise: Promise<ReturnType> | null;
resolve: ((value: ReturnType) => void) | null;
};