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 { constructorsForReviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../utils/JSONReviver";
import { ActionIdentifier } from "./ActionIdentifier";
@ -42,8 +43,7 @@ export interface BlackOpsAttempt {
isAvailable?: boolean;
action?: BlackOperation;
}
export const BladeburnerResolvers: ((msProcessed: number) => void)[] = [];
export const BladeburnerPromise: PromisePair<number> = { promise: null, resolve: null };
export class Bladeburner {
numHosp = 0;
@ -2085,9 +2085,11 @@ export class Bladeburner {
}
}
// Handle "nextUpdate" resolvers after this update
for (const resolve of BladeburnerResolvers.splice(0)) {
resolve(seconds * 1000);
// Handle "nextUpdate" resolver after this update
if (BladeburnerPromise.resolve) {
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 { CorpStateName, InvestmentOffer } from "@nsdefs";
import { CorpUnlockName, CorpUpgradeName, LiteratureName } from "@enums";
@ -19,7 +20,7 @@ import { formatMoney } from "../ui/formatNumber";
import { isPositiveInteger } from "../types";
import { createEnumKeyedRecord, getRecordValues } from "../Types/Record";
export const CorporationResolvers: ((prevState: CorpStateName) => void)[] = [];
export const CorporationPromise: PromisePair<CorpStateName> = { promise: null, resolve: null };
interface ICorporationParams {
name?: string;
@ -175,9 +176,11 @@ export class Corporation {
this.state.incrementState();
// Handle "nextUpdate" resolvers after this update
for (const resolve of CorporationResolvers.splice(0)) {
resolve(state);
// Handle "nextUpdate" resolver after this update
if (CorporationPromise.resolve) {
CorporationPromise.resolve(state);
CorporationPromise.resolve = null;
CorporationPromise.promise = null;
}
}
}

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

@ -3,7 +3,7 @@ import type { Action } from "../Bladeburner/Action";
import type { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
import { Player } from "@player";
import { Bladeburner, BladeburnerResolvers } from "../Bladeburner/Bladeburner";
import { Bladeburner, BladeburnerPromise } from "../Bladeburner/Bladeburner";
import { currentNodeMults } from "../BitNode/BitNodeMultipliers";
import { BlackOperation } from "../Bladeburner/BlackOperation";
import { helpers } from "../Netscript/NetscriptHelpers";
@ -329,8 +329,11 @@ export function NetscriptBladeburner(): InternalAPI<INetscriptBladeburner> {
const bladeburner = getBladeburner(ctx);
return Math.round(bladeburner.storedCycles / 5) * 1000;
},
nextUpdate: () => () => {
return new Promise<number>((res) => BladeburnerResolvers.push(res));
nextUpdate: (ctx) => () => {
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 { Warehouse } from "../Corporation/Warehouse";
import { Division } from "../Corporation/Division";
import { Corporation, CorporationResolvers } from "../Corporation/Corporation";
import { Corporation, CorporationPromise } from "../Corporation/Corporation";
import { omit } from "lodash";
import { setDeprecatedProperties } from "../utils/DeprecationHelper";
import {
@ -800,7 +800,9 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
},
nextUpdate: (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 { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
import { GangNextUpdate } from "../Gang/Gang";
import { GangPromise } from "../Gang/Gang";
import { Player } from "@player";
import { FactionName } from "@enums";
import { GangConstants } from "../Gang/data/Constants";
@ -324,11 +324,10 @@ export function NetscriptGang(): InternalAPI<IGang> {
const gang = getGang(ctx);
return Math.round(gang.storedCycles / 5) * 1000;
},
nextUpdate: () => () => {
if (!GangNextUpdate.promise) {
GangNextUpdate.promise = new Promise<number>((res) => (GangNextUpdate.resolver = res));
}
return GangNextUpdate.promise;
nextUpdate: (ctx) => () => {
getGang(ctx);
if (!GangPromise.promise) GangPromise.promise = new Promise<number>((res) => (GangPromise.resolve = res));
return GangPromise.promise;
},
};
}

@ -6,7 +6,7 @@ import {
placeOrder,
cancelOrder,
initStockMarket,
StockMarketResolvers,
StockMarketPromise,
} from "../StockMarket/StockMarket";
import { getBuyTransactionCost, getSellTransactionGain } from "../StockMarket/StockMarketHelpers";
import { PositionType, OrderType, StockSymbol } from "@enums";
@ -415,7 +415,9 @@ export function NetscriptStockMarket(): InternalAPI<TIX> {
},
nextUpdate: (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 = () => {
// Intentionally empty function, this is just an initial value and will never be used.
};
nextCompletion: Promise<void>;
nextCompletionPromise: Promise<void> | null;
constructor(params?: SleeveBladeburnerWorkParams) {
super();
this.nextCompletion = new Promise((r) => (this.signalCompletion = r));
this.nextCompletionPromise = null;
this.actionType = params?.type ?? "General";
this.actionName = params?.name ?? "Field Analysis";
}
@ -40,7 +40,7 @@ export class SleeveBladeburnerWork extends SleeveWorkClass {
}
finish() {
this.signalCompletion();
if (this.nextCompletionPromise) this.signalCompletion();
}
process(sleeve: Sleeve, cycles: number) {
@ -73,11 +73,13 @@ export class SleeveBladeburnerWork extends SleeveWorkClass {
this.tasksCompleted++;
this.cyclesWorked -= this.cyclesNeeded(sleeve);
// Resolve and reset nextCompletion promise
const resolver = this.signalCompletion;
this.nextCompletion = new Promise((r) => (this.signalCompletion = r));
resolver();
if (this.nextCompletionPromise) this.signalCompletion();
}
}
get nextCompletion(): Promise<void> {
if (!this.nextCompletionPromise) this.nextCompletionPromise = new Promise((r) => (this.signalCompletion = r));
return this.nextCompletionPromise;
}
APICopy(sleeve: Sleeve) {
return {

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