feat(engine): add action queue state and enqueue APIs
This commit is contained in:
+37
-2
@@ -14,6 +14,8 @@ export interface GameState {
|
||||
activeActionId: string | null;
|
||||
/** Progress of the active action, in milliseconds. */
|
||||
actionElapsedMs: number;
|
||||
/** Action ids waiting to run after the active action finishes. */
|
||||
actionQueue: string[];
|
||||
}
|
||||
|
||||
export function createGameState(content: Content): GameState {
|
||||
@@ -21,10 +23,14 @@ export function createGameState(content: Content): GameState {
|
||||
for (const resource of content.resources) {
|
||||
resources[resource.id] = resource.startAmount;
|
||||
}
|
||||
return { resources, activeActionId: null, actionElapsedMs: 0 };
|
||||
return { resources, activeActionId: null, actionElapsedMs: 0, actionQueue: [] };
|
||||
}
|
||||
|
||||
/** Begin running an action, resetting its progress. Throws on an unknown id. */
|
||||
/**
|
||||
* Begin running an action, resetting its progress. Throws on an unknown id.
|
||||
*
|
||||
* @deprecated Prefer `enqueueAction` — it starts immediately when idle and queues otherwise.
|
||||
*/
|
||||
export function startAction(state: GameState, content: Content, actionId: string): void {
|
||||
if (!content.actionsById[actionId]) {
|
||||
throw new Error(`Unknown action "${actionId}"`);
|
||||
@@ -33,6 +39,35 @@ export function startAction(state: GameState, content: Content, actionId: string
|
||||
state.actionElapsedMs = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start an action immediately when idle, otherwise append it to the queue.
|
||||
* Throws on an unknown id. Cost/unlock checks are not applied yet.
|
||||
*/
|
||||
export function enqueueAction(state: GameState, content: Content, actionId: string): void {
|
||||
if (!content.actionsById[actionId]) {
|
||||
throw new Error(`Unknown action "${actionId}"`);
|
||||
}
|
||||
if (state.activeActionId === null) {
|
||||
state.activeActionId = actionId;
|
||||
state.actionElapsedMs = 0;
|
||||
return;
|
||||
}
|
||||
state.actionQueue.push(actionId);
|
||||
}
|
||||
|
||||
/** Remove a queued action by index. Throws RangeError when out of range. */
|
||||
export function cancelQueuedAction(state: GameState, index: number): void {
|
||||
if (index < 0 || index >= state.actionQueue.length) {
|
||||
throw new RangeError(`Queue index ${index} is out of range`);
|
||||
}
|
||||
state.actionQueue.splice(index, 1);
|
||||
}
|
||||
|
||||
/** Clear all queued actions without stopping the active action. */
|
||||
export function clearQueue(state: GameState): void {
|
||||
state.actionQueue.length = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Advance the active action by `tickMs`. Each time it reaches its duration it
|
||||
* grants its yield and repeats, carrying the remainder — so one large tick (the
|
||||
|
||||
Reference in New Issue
Block a user