diff --git a/markdown/bitburner.grafting.getaugmentationgrafttime.md b/markdown/bitburner.grafting.getaugmentationgrafttime.md index 12f39dcb7..915d6b78a 100644 --- a/markdown/bitburner.grafting.getaugmentationgrafttime.md +++ b/markdown/bitburner.grafting.getaugmentationgrafttime.md @@ -4,7 +4,7 @@ ## Grafting.getAugmentationGraftTime() method -Retrieves the time required to graft an aug. +Retrieves the time required to graft an aug. Do not use this value to determine when the ongoing grafting finishes. The ongoing grafting is affected by current intelligence level and focus bonus. You should use [waitForOngoingGrafting](./bitburner.grafting.waitforongoinggrafting.md) for that purpose. **Signature:** @@ -22,7 +22,7 @@ getAugmentationGraftTime(augName: string): number; number -The time required, in millis, to graft the named augmentation. +The time required, in milliseconds, to graft the named augmentation. ## Exceptions diff --git a/markdown/bitburner.grafting.graftaugmentation.md b/markdown/bitburner.grafting.graftaugmentation.md index 2e203ae59..344107893 100644 --- a/markdown/bitburner.grafting.graftaugmentation.md +++ b/markdown/bitburner.grafting.graftaugmentation.md @@ -4,7 +4,7 @@ ## Grafting.graftAugmentation() method -Begins grafting the named aug. You must be in New Tokyo to use this. +Begins grafting the named aug. You must be in New Tokyo to use this. When you call this API, the current work (grafting or other actions) will be canceled. **Signature:** diff --git a/markdown/bitburner.grafting.md b/markdown/bitburner.grafting.md index af939323c..5761c5228 100644 --- a/markdown/bitburner.grafting.md +++ b/markdown/bitburner.grafting.md @@ -21,7 +21,8 @@ This API requires Source-File 10 to use. | Method | Description | | --- | --- | | [getAugmentationGraftPrice(augName)](./bitburner.grafting.getaugmentationgraftprice.md) | Retrieve the grafting cost of an aug. | -| [getAugmentationGraftTime(augName)](./bitburner.grafting.getaugmentationgrafttime.md) | Retrieves the time required to graft an aug. | +| [getAugmentationGraftTime(augName)](./bitburner.grafting.getaugmentationgrafttime.md) | Retrieves the time required to graft an aug. Do not use this value to determine when the ongoing grafting finishes. The ongoing grafting is affected by current intelligence level and focus bonus. You should use [waitForOngoingGrafting](./bitburner.grafting.waitforongoinggrafting.md) for that purpose. | | [getGraftableAugmentations()](./bitburner.grafting.getgraftableaugmentations.md) | Retrieves a list of Augmentations that can be grafted. | -| [graftAugmentation(augName, focus)](./bitburner.grafting.graftaugmentation.md) | Begins grafting the named aug. You must be in New Tokyo to use this. | +| [graftAugmentation(augName, focus)](./bitburner.grafting.graftaugmentation.md) | Begins grafting the named aug. You must be in New Tokyo to use this. When you call this API, the current work (grafting or other actions) will be canceled. | +| [waitForOngoingGrafting()](./bitburner.grafting.waitforongoinggrafting.md) | Wait until the ongoing grafting finishes or is canceled. | diff --git a/markdown/bitburner.grafting.waitforongoinggrafting.md b/markdown/bitburner.grafting.waitforongoinggrafting.md new file mode 100644 index 000000000..66ff59f9d --- /dev/null +++ b/markdown/bitburner.grafting.waitforongoinggrafting.md @@ -0,0 +1,23 @@ + + +[Home](./index.md) > [bitburner](./bitburner.md) > [Grafting](./bitburner.grafting.md) > [waitForOngoingGrafting](./bitburner.grafting.waitforongoinggrafting.md) + +## Grafting.waitForOngoingGrafting() method + +Wait until the ongoing grafting finishes or is canceled. + +**Signature:** + +```typescript +waitForOngoingGrafting(): Promise; +``` +**Returns:** + +Promise<void> + +A promise that resolves when the current grafting finishes or is canceled. If there is no current work, the promise resolves immediately. If the current work is not a grafting work, the promise rejects immediately. + +## Remarks + +RAM cost: 1 GB + diff --git a/markdown/bitburner.graftingtask.completion.md b/markdown/bitburner.graftingtask.completion.md new file mode 100644 index 000000000..62a4ab4cd --- /dev/null +++ b/markdown/bitburner.graftingtask.completion.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [bitburner](./bitburner.md) > [GraftingTask](./bitburner.graftingtask.md) > [completion](./bitburner.graftingtask.completion.md) + +## GraftingTask.completion property + +**Signature:** + +```typescript +completion: Promise; +``` diff --git a/markdown/bitburner.graftingtask.md b/markdown/bitburner.graftingtask.md index 0044f7c21..204e9962b 100644 --- a/markdown/bitburner.graftingtask.md +++ b/markdown/bitburner.graftingtask.md @@ -21,6 +21,7 @@ An object representing the current grafting status | Property | Modifiers | Type | Description | | --- | --- | --- | --- | | [augmentation](./bitburner.graftingtask.augmentation.md) | | string | | +| [completion](./bitburner.graftingtask.completion.md) | | Promise<void> | | | [cyclesWorked](./bitburner.graftingtask.cyclesworked.md) | | number | | | [type](./bitburner.graftingtask.type.md) | | "GRAFTING" | | diff --git a/src/Netscript/RamCostGenerator.ts b/src/Netscript/RamCostGenerator.ts index e0b16e3f9..c8d3f044e 100644 --- a/src/Netscript/RamCostGenerator.ts +++ b/src/Netscript/RamCostGenerator.ts @@ -388,6 +388,7 @@ const grafting = { getAugmentationGraftTime: 3.75, getGraftableAugmentations: 5, graftAugmentation: 7.5, + waitForOngoingGrafting: 1, } as const; const corporation = { diff --git a/src/NetscriptFunctions/Grafting.ts b/src/NetscriptFunctions/Grafting.ts index 8e1efad68..616691bbb 100644 --- a/src/NetscriptFunctions/Grafting.ts +++ b/src/NetscriptFunctions/Grafting.ts @@ -97,5 +97,18 @@ export function NetscriptGrafting(): InternalAPI { helpers.log(ctx, () => `Began grafting Augmentation ${augName}.`); return true; }, + + waitForOngoingGrafting: (ctx) => () => { + checkGraftingAPIAccess(ctx); + if (!Player.currentWork) { + return Promise.resolve(); + } + if (!(Player.currentWork instanceof GraftingWork)) { + return Promise.reject( + `The current work is not a grafting work. Type of current work: ${Player.currentWork.type}.`, + ); + } + return Player.currentWork.completion; + }, }; } diff --git a/src/ScriptEditor/NetscriptDefinitions.d.ts b/src/ScriptEditor/NetscriptDefinitions.d.ts index c3f34fd77..2be6007b9 100644 --- a/src/ScriptEditor/NetscriptDefinitions.d.ts +++ b/src/ScriptEditor/NetscriptDefinitions.d.ts @@ -1690,6 +1690,7 @@ export interface GraftingTask { type: "GRAFTING"; cyclesWorked: number; augmentation: string; + completion: Promise; } /** @@ -4634,18 +4635,22 @@ export interface Grafting { getAugmentationGraftPrice(augName: string): number; /** - * Retrieves the time required to graft an aug. + * Retrieves the time required to graft an aug. Do not use this value to determine when the ongoing grafting finishes. + * The ongoing grafting is affected by current intelligence level and focus bonus. You should use + * {@link Grafting.waitForOngoingGrafting | waitForOngoingGrafting} for that purpose. + * * @remarks * RAM cost: 3.75 GB * * @param augName - Name of the aug to check the grafting time of. Must be an exact match. - * @returns The time required, in millis, to graft the named augmentation. + * @returns The time required, in milliseconds, to graft the named augmentation. * @throws Will error if an invalid Augmentation name is provided. */ getAugmentationGraftTime(augName: string): number; /** * Retrieves a list of Augmentations that can be grafted. + * * @remarks * RAM cost: 5 GB * @@ -4657,7 +4662,9 @@ export interface Grafting { getGraftableAugmentations(): string[]; /** - * Begins grafting the named aug. You must be in New Tokyo to use this. + * Begins grafting the named aug. You must be in New Tokyo to use this. When you call this API, the current work + * (grafting or other actions) will be canceled. + * * @remarks * RAM cost: 7.5 GB * @@ -4668,6 +4675,17 @@ export interface Grafting { * @throws Will error if called while you are not in New Tokyo. */ graftAugmentation(augName: string, focus?: boolean): boolean; + + /** + * Wait until the ongoing grafting finishes or is canceled. + * + * @remarks + * RAM cost: 1 GB + * + * @returns A promise that resolves when the current grafting finishes or is canceled. If there is no current work, + * the promise resolves immediately. If the current work is not a grafting work, the promise rejects immediately. + */ + waitForOngoingGrafting(): Promise; } /** diff --git a/src/Work/GraftingWork.tsx b/src/Work/GraftingWork.tsx index 3ee202015..ddf910a47 100644 --- a/src/Work/GraftingWork.tsx +++ b/src/Work/GraftingWork.tsx @@ -10,6 +10,8 @@ import { dialogBoxCreate } from "../ui/React/DialogBox"; import { constructorsForReviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../utils/JSONReviver"; import { GraftableAugmentation } from "../PersonObjects/Grafting/GraftableAugmentation"; import { Augmentations } from "../Augmentation/Augmentations"; +import { PromisePair } from "../Types/Promises"; +import { getKeyList } from "../utils/helpers/getKeyList"; export const isGraftingWork = (w: Work | null): w is GraftingWork => w !== null && w.type === WorkType.GRAFTING; @@ -22,6 +24,14 @@ export class GraftingWork extends Work { augmentation: AugmentationName; unitCompleted: number; unitRate: number; + completionPromisePair: PromisePair = { promise: null, resolve: null }; + + get completion(): Promise { + if (!this.completionPromisePair.promise) { + this.completionPromisePair.promise = new Promise((r) => (this.completionPromisePair.resolve = r)); + } + return this.completionPromisePair.promise; + } constructor(params?: GraftingWorkParams) { super(WorkType.GRAFTING, params?.singularity ?? true); @@ -79,6 +89,12 @@ export class GraftingWork extends Work { (CONSTANTS.IntelligenceGraftBaseExpGain * this.cyclesWorked * CONSTANTS.MilliPerCycle) / 10000, ); } + + if (this.completionPromisePair.resolve) { + this.completionPromisePair.resolve(); + this.completionPromisePair.resolve = null; + this.completionPromisePair.promise = null; + } } APICopy() { @@ -86,17 +102,20 @@ export class GraftingWork extends Work { type: WorkType.GRAFTING as const, cyclesWorked: this.cyclesWorked, augmentation: this.augmentation, + completion: this.completion, }; } + static savedKeys = getKeyList(GraftingWork, { removedKeys: ["completionPromisePair"] }); + /** Serialize the current object to a JSON save state. */ toJSON(): IReviverValue { - return Generic_toJSON("GraftingWork", this); + return Generic_toJSON("GraftingWork", this, GraftingWork.savedKeys); } /** Initializes a GraftingWork object from a JSON save state. */ static fromJSON(value: IReviverValue): GraftingWork { - return Generic_fromJSON(GraftingWork, value.data); + return Generic_fromJSON(GraftingWork, value.data, GraftingWork.savedKeys); } }