@latticexyz/recs 2.2.18-90aac1d4acce19ac592d47a090732dd11c1c3e7a → 2.2.18-9fa07c8489f1fbf167d0db01cd9aaa645a29c8e2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,163 @@
1
- import{d as h,m as O,n as T,o as a,r as c,x as v}from"../chunk-2YR7WENB.js";var b=(s=>(s.Requested="Requested",s.Executing="Executing",s.WaitingForTxEvents="WaitingForTxEvents",s.Complete="Complete",s.Failed="Failed",s.Cancelled="Cancelled",s.TxReduced="TxReduced",s))(b||{});import{merge as S}from"rxjs";import{mapObject as D,awaitStreamValue as F,uuid as R}from"@latticexyz/utils";function A(d){return O(d,{state:5,on:14,metadata:18,overrides:12,txHash:6},{id:"Action"})}function L(d,x,C){let o=A(d),m={},u=new Map,f=new Map;d.registerDisposer(()=>{for(let{dispose:t}of f.values())t()});function s(t){let n=m[t.id]||v(t);return m[t.id]||(m[t.id]=n),n}function E(t){if(d.hasEntity(t.id))return console.warn(`Action with id ${t.id} is already requested.`),t.id;let i=h(d,void 0,{id:t.id});T(o,i,{state:"Requested",on:t.on,metadata:t.metadata,overrides:void 0,txHash:void 0});for(let r of Object.values(t.components))m[r.id]||(m[r.id]=v(r));let e={...t,entity:i,componentsWithOptimisticUpdates:D(t.components,r=>s(r))};u.set(e.id,e);let p=S(...Object.values(e.componentsWithOptimisticUpdates).map(r=>r.update$)).subscribe(()=>g(e));return g(e),f.set(e.id,{dispose:()=>p?.unsubscribe()}),i}function g(t){if(c(o,t.entity)?.state!=="Requested")return;let n=t.requirement(t.componentsWithOptimisticUpdates);n&&w(t,n)}async function w(t,n){if(c(o,t.entity)?.state!=="Requested")return;a(o,t.entity,{state:"Executing"});let i=t.updates(t.componentsWithOptimisticUpdates,n).map(e=>({...e,id:R()}));a(o,t.entity,{overrides:i.map(e=>`${e.id}/${e.component.id}`)});for(let{component:e,value:p,entity:r,id:y}of i)m[e.id].addOverride(y,{entity:r,value:p});try{let e=await t.execute(n);if(e&&(a(o,t.entity,{state:"WaitingForTxEvents",txHash:e}),await F(x,p=>p===e),a(o,t.entity,{state:"TxReduced"}),t.awaitConfirmation))if(C)await C(e);else throw new Error("action has awaitConfirmation but no waitForTransaction specified in createActionSystem");a(o,t.entity,{state:"Complete"})}catch(e){M(e,t)}l(t.id)}function M(t,n){console.error(t),a(o,n.entity,{state:"Failed"}),l(n.id)}function W(t){let n=u.get(t);return!n||c(o,n.entity)?.state!=="Requested"?(console.warn(`Action ${t} was not found or is not in the "Requested" state.`),!1):(a(o,n.entity,{state:"Cancelled"}),l(t),!0)}function l(t){if(!u.get(t)){console.warn(`Trying to remove action ${t} that does not exist.`);return}let i=t,e=i!=null&&c(o,i)?.overrides||[];for(let p of e){let[r,y]=p.split("/");m[y].removeOverride(r)}f.get(t)?.dispose(),f.delete(t),u.delete(t),i!=null&&setTimeout(()=>d.deleteEntity(i),5e3)}return{add:E,cancel:W,withOptimisticUpdates:s,Action:o}}export{b as ActionState,L as createActionSystem};
1
+ import {
2
+ createEntity,
3
+ defineComponent,
4
+ getComponentValue,
5
+ overridableComponent,
6
+ setComponent,
7
+ updateComponent
8
+ } from "../chunk-A6GOEGXN.js";
9
+
10
+ // src/deprecated/constants.ts
11
+ var ActionState = /* @__PURE__ */ ((ActionState2) => {
12
+ ActionState2["Requested"] = "Requested";
13
+ ActionState2["Executing"] = "Executing";
14
+ ActionState2["WaitingForTxEvents"] = "WaitingForTxEvents";
15
+ ActionState2["Complete"] = "Complete";
16
+ ActionState2["Failed"] = "Failed";
17
+ ActionState2["Cancelled"] = "Cancelled";
18
+ ActionState2["TxReduced"] = "TxReduced";
19
+ return ActionState2;
20
+ })(ActionState || {});
21
+
22
+ // src/deprecated/createActionSystem.ts
23
+ import { merge } from "rxjs";
24
+ import { mapObject, awaitStreamValue, uuid } from "@latticexyz/utils";
25
+
26
+ // src/deprecated/defineActionComponent.ts
27
+ function defineActionComponent(world) {
28
+ const Action = defineComponent(
29
+ world,
30
+ {
31
+ state: 5 /* String */,
32
+ on: 14 /* OptionalEntity */,
33
+ metadata: 18 /* OptionalT */,
34
+ overrides: 12 /* OptionalStringArray */,
35
+ txHash: 6 /* OptionalString */
36
+ },
37
+ { id: "Action" }
38
+ );
39
+ return Action;
40
+ }
41
+
42
+ // src/deprecated/createActionSystem.ts
43
+ function createActionSystem(world, txReduced$, waitForTransaction) {
44
+ const Action = defineActionComponent(world);
45
+ const componentsWithOptimisticUpdates = {};
46
+ const actionData = /* @__PURE__ */ new Map();
47
+ const disposer = /* @__PURE__ */ new Map();
48
+ world.registerDisposer(() => {
49
+ for (const { dispose } of disposer.values()) dispose();
50
+ });
51
+ function withOptimisticUpdates(component) {
52
+ const optimisticComponent = componentsWithOptimisticUpdates[component.id] || overridableComponent(component);
53
+ if (!componentsWithOptimisticUpdates[component.id]) {
54
+ componentsWithOptimisticUpdates[component.id] = optimisticComponent;
55
+ }
56
+ return optimisticComponent;
57
+ }
58
+ function add(actionRequest) {
59
+ const existingAction = world.hasEntity(actionRequest.id);
60
+ if (existingAction) {
61
+ console.warn(`Action with id ${actionRequest.id} is already requested.`);
62
+ return actionRequest.id;
63
+ }
64
+ const entity = createEntity(world, void 0, {
65
+ id: actionRequest.id
66
+ });
67
+ setComponent(Action, entity, {
68
+ state: "Requested" /* Requested */,
69
+ on: actionRequest.on,
70
+ metadata: actionRequest.metadata,
71
+ overrides: void 0,
72
+ txHash: void 0
73
+ });
74
+ for (const component of Object.values(actionRequest.components)) {
75
+ if (!componentsWithOptimisticUpdates[component.id])
76
+ componentsWithOptimisticUpdates[component.id] = overridableComponent(component);
77
+ }
78
+ const action = {
79
+ ...actionRequest,
80
+ entity,
81
+ componentsWithOptimisticUpdates: mapObject(actionRequest.components, (c) => withOptimisticUpdates(c))
82
+ };
83
+ actionData.set(action.id, action);
84
+ const subscription = merge(
85
+ ...Object.values(action.componentsWithOptimisticUpdates).map((c) => c.update$)
86
+ ).subscribe(() => checkRequirement(action));
87
+ checkRequirement(action);
88
+ disposer.set(action.id, { dispose: () => subscription?.unsubscribe() });
89
+ return entity;
90
+ }
91
+ function checkRequirement(action) {
92
+ if (getComponentValue(Action, action.entity)?.state !== "Requested" /* Requested */) return;
93
+ const requirementResult = action.requirement(action.componentsWithOptimisticUpdates);
94
+ if (requirementResult) executeAction(action, requirementResult);
95
+ }
96
+ async function executeAction(action, requirementResult) {
97
+ if (getComponentValue(Action, action.entity)?.state !== "Requested" /* Requested */) return;
98
+ updateComponent(Action, action.entity, { state: "Executing" /* Executing */ });
99
+ const overrides = action.updates(action.componentsWithOptimisticUpdates, requirementResult).map((o) => ({ ...o, id: uuid() }));
100
+ updateComponent(Action, action.entity, { overrides: overrides.map((o) => `${o.id}/${o.component.id}`) });
101
+ for (const { component, value, entity, id } of overrides) {
102
+ componentsWithOptimisticUpdates[component.id].addOverride(id, { entity, value });
103
+ }
104
+ try {
105
+ const tx = await action.execute(requirementResult);
106
+ if (tx) {
107
+ updateComponent(Action, action.entity, { state: "WaitingForTxEvents" /* WaitingForTxEvents */, txHash: tx });
108
+ await awaitStreamValue(txReduced$, (v) => v === tx);
109
+ updateComponent(Action, action.entity, { state: "TxReduced" /* TxReduced */ });
110
+ if (action.awaitConfirmation) {
111
+ if (waitForTransaction) {
112
+ await waitForTransaction(tx);
113
+ } else {
114
+ throw new Error("action has awaitConfirmation but no waitForTransaction specified in createActionSystem");
115
+ }
116
+ }
117
+ }
118
+ updateComponent(Action, action.entity, { state: "Complete" /* Complete */ });
119
+ } catch (e) {
120
+ handleError(e, action);
121
+ }
122
+ remove(action.id);
123
+ }
124
+ function handleError(e, action) {
125
+ console.error(e);
126
+ updateComponent(Action, action.entity, { state: "Failed" /* Failed */ });
127
+ remove(action.id);
128
+ }
129
+ function cancel(actionId) {
130
+ const action = actionData.get(actionId);
131
+ if (!action || getComponentValue(Action, action.entity)?.state !== "Requested" /* Requested */) {
132
+ console.warn(`Action ${actionId} was not found or is not in the "Requested" state.`);
133
+ return false;
134
+ }
135
+ updateComponent(Action, action.entity, { state: "Cancelled" /* Cancelled */ });
136
+ remove(actionId);
137
+ return true;
138
+ }
139
+ function remove(actionId) {
140
+ const action = actionData.get(actionId);
141
+ if (!action) {
142
+ console.warn(`Trying to remove action ${actionId} that does not exist.`);
143
+ return;
144
+ }
145
+ const actionEntity = actionId;
146
+ const overrides = actionEntity != null && getComponentValue(Action, actionEntity)?.overrides || [];
147
+ for (const override of overrides) {
148
+ const [id, componentId] = override.split("/");
149
+ const component = componentsWithOptimisticUpdates[componentId];
150
+ component.removeOverride(id);
151
+ }
152
+ disposer.get(actionId)?.dispose();
153
+ disposer.delete(actionId);
154
+ actionData.delete(actionId);
155
+ actionEntity != null && setTimeout(() => world.deleteEntity(actionEntity), 5e3);
156
+ }
157
+ return { add, cancel, withOptimisticUpdates, Action };
158
+ }
159
+ export {
160
+ ActionState,
161
+ createActionSystem
162
+ };
2
163
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/deprecated/constants.ts","../../src/deprecated/createActionSystem.ts","../../src/deprecated/defineActionComponent.ts"],"sourcesContent":["export enum ActionState {\n Requested = \"Requested\",\n Executing = \"Executing\",\n WaitingForTxEvents = \"WaitingForTxEvents\",\n Complete = \"Complete\",\n Failed = \"Failed\",\n Cancelled = \"Cancelled\",\n TxReduced = \"TxReduced\",\n}\n","import { merge, Observable } from \"rxjs\";\nimport { mapObject, awaitStreamValue, uuid } from \"@latticexyz/utils\";\nimport { ActionState } from \"./constants\";\nimport { ActionData, ActionRequest } from \"./types\";\nimport { defineActionComponent } from \"./defineActionComponent\";\nimport { overridableComponent, setComponent, getComponentValue, updateComponent } from \"../Component\";\nimport { createEntity } from \"../Entity\";\nimport { World, OverridableComponent, Metadata, Component, Components, Entity, Schema } from \"../types\";\n\nexport type ActionSystem = ReturnType<typeof createActionSystem>;\n\n/**\n * @deprecated For now, we suggest using `overridableComponent(Component)` and `addOverride`/`removeOverride` to manage overrides yourself.\n */\nexport function createActionSystem<M = unknown>(\n world: World,\n txReduced$: Observable<string>,\n waitForTransaction?: (tx: string) => Promise<void>,\n) {\n // Action component\n const Action = defineActionComponent<M>(world);\n\n // Components that scheduled actions depend on including pending updates\n const componentsWithOptimisticUpdates: { [id: string]: OverridableComponent<Schema> } = {};\n\n // ActionData contains requirements and execute logic of scheduled actions.\n // We also store the relevant subset of all componentsWithOptimisticUpdates in the action data,\n // to recheck requirements only if relevant components updated.\n const actionData = new Map<string, ActionData>();\n\n // Disposers of requirement check autoruns for all pending actions\n const disposer = new Map<string, { dispose: () => void }>();\n world.registerDisposer(() => {\n for (const { dispose } of disposer.values()) dispose();\n });\n\n /**\n * Maps all components in a given components map to the respective components including pending updates\n * @param component Component to be mapped to components including pending updates\n * @returns Components including pending updates\n */\n function withOptimisticUpdates<S extends Schema, M extends Metadata, T>(\n component: Component<S, M, T>,\n ): OverridableComponent<S, M, T> {\n const optimisticComponent = componentsWithOptimisticUpdates[component.id] || overridableComponent(component);\n\n // If the component is not tracked yet, add it to the map of overridable components\n if (!componentsWithOptimisticUpdates[component.id]) {\n componentsWithOptimisticUpdates[component.id] = optimisticComponent;\n }\n\n // Typescript can't know that the optimistic component with this id has the same type as C\n return optimisticComponent as OverridableComponent<S, M, T>;\n }\n\n /**\n * Schedules an action. The action will be executed once its requirement is fulfilled.\n * Note: the requirement will only be rechecked automatically if the requirement is based on components\n * (or other mobx-observable values).\n * @param actionRequest Action to be scheduled\n * @returns index of the entity created for the action\n */\n function add<C extends Components, T>(actionRequest: ActionRequest<C, T, M>): Entity {\n // Prevent the same actions from being scheduled multiple times\n const existingAction = world.hasEntity(actionRequest.id as Entity);\n if (existingAction) {\n console.warn(`Action with id ${actionRequest.id} is already requested.`);\n return actionRequest.id as Entity;\n }\n\n // Set the action component\n const entity = createEntity(world, undefined, {\n id: actionRequest.id,\n });\n\n setComponent(Action, entity, {\n state: ActionState.Requested,\n on: actionRequest.on,\n metadata: actionRequest.metadata,\n overrides: undefined,\n txHash: undefined,\n });\n\n // Add components that are not tracked yet to internal overridable component map.\n // Pending updates will be applied to internal overridable components.\n for (const component of Object.values(actionRequest.components)) {\n if (!componentsWithOptimisticUpdates[component.id])\n componentsWithOptimisticUpdates[component.id] = overridableComponent(component);\n }\n\n // Store relevant components with pending updates along the action's requirement and execution logic\n const action = {\n ...actionRequest,\n entity,\n componentsWithOptimisticUpdates: mapObject(actionRequest.components, (c) => withOptimisticUpdates(c)),\n } as unknown as ActionData;\n actionData.set(action.id, action);\n\n // This subscriotion makes sure the action requirement is checked again every time\n // one of the referenced components changes or the pending updates map changes\n const subscription = merge(\n ...Object.values(action.componentsWithOptimisticUpdates).map((c) => c.update$),\n ).subscribe(() => checkRequirement(action));\n checkRequirement(action);\n disposer.set(action.id, { dispose: () => subscription?.unsubscribe() });\n\n return entity;\n }\n\n /**\n * Checks the requirement of a given action and executes the action if the requirement is fulfilled\n * @param action Action to check the requirement of\n * @returns void\n */\n function checkRequirement(action: ActionData) {\n // Only check requirements of requested actions\n if (getComponentValue(Action, action.entity)?.state !== ActionState.Requested) return;\n\n // Check requirement on components including pending updates\n const requirementResult = action.requirement(action.componentsWithOptimisticUpdates);\n\n // Execute the action if the requirements are met\n if (requirementResult) executeAction(action, requirementResult);\n }\n\n /**\n * Executes the given action and sets the corresponding Action component\n * @param action ActionData of the action to be executed\n * @param requirementResult Result of the action's requirement function\n * @returns void\n */\n async function executeAction<T>(action: ActionData, requirementResult: T) {\n // Only execute actions that were requested before\n if (getComponentValue(Action, action.entity)?.state !== ActionState.Requested) return;\n\n // Update the action state\n updateComponent(Action, action.entity, { state: ActionState.Executing });\n\n // Compute overrides\n const overrides = action\n .updates(action.componentsWithOptimisticUpdates, requirementResult)\n .map((o) => ({ ...o, id: uuid() }));\n\n // Store overrides on Action component to be able to remove when action is done\n updateComponent(Action, action.entity, { overrides: overrides.map((o) => `${o.id}/${o.component.id}`) });\n\n // Set all pending updates of this action\n for (const { component, value, entity, id } of overrides) {\n componentsWithOptimisticUpdates[component.id].addOverride(id, { entity, value });\n }\n\n try {\n // Execute the action\n const tx = await action.execute(requirementResult);\n\n // If the result includes a hash key (single tx) or hashes (multiple tx) key, wait for the transactions to complete before removing the pending actions\n if (tx) {\n // Wait for all tx events to be reduced\n updateComponent(Action, action.entity, { state: ActionState.WaitingForTxEvents, txHash: tx });\n await awaitStreamValue(txReduced$, (v) => v === tx);\n updateComponent(Action, action.entity, { state: ActionState.TxReduced });\n // TODO: extend ActionData type to be aware of whether waitForTransaction is set\n if (action.awaitConfirmation) {\n if (waitForTransaction) {\n await waitForTransaction(tx);\n } else {\n throw new Error(\"action has awaitConfirmation but no waitForTransaction specified in createActionSystem\");\n }\n }\n }\n\n updateComponent(Action, action.entity, { state: ActionState.Complete });\n } catch (e) {\n handleError(e, action);\n }\n\n // After the action is done executing (failed or completed), remove its actionData and remove the Action component\n remove(action.id);\n }\n\n // Set the action's state to ActionState.Failed\n function handleError(e: unknown, action: ActionData) {\n console.error(e);\n updateComponent(Action, action.entity, { state: ActionState.Failed });\n remove(action.id);\n }\n\n /**\n * Cancels the action with the given ID if it is in the \"Requested\" state.\n * @param actionId ID of the action to be cancelled\n * @returns void\n */\n function cancel(actionId: string): boolean {\n const action = actionData.get(actionId);\n if (!action || getComponentValue(Action, action.entity)?.state !== ActionState.Requested) {\n console.warn(`Action ${actionId} was not found or is not in the \"Requested\" state.`);\n return false;\n }\n updateComponent(Action, action.entity, { state: ActionState.Cancelled });\n remove(actionId);\n return true;\n }\n\n /**\n * Removes actionData disposer of the action with the given ID and removes its pending updates.\n * @param actionId ID of the action to be removed\n */\n function remove(actionId: string) {\n const action = actionData.get(actionId);\n if (!action) {\n console.warn(`Trying to remove action ${actionId} that does not exist.`);\n return;\n }\n\n // Remove this action's pending updates\n const actionEntity = actionId as Entity;\n const overrides = (actionEntity != null && getComponentValue(Action, actionEntity)?.overrides) || [];\n for (const override of overrides) {\n const [id, componentId] = override.split(\"/\");\n const component = componentsWithOptimisticUpdates[componentId];\n component.removeOverride(id);\n }\n\n // Remove this action's autorun and corresponding disposer\n disposer.get(actionId)?.dispose();\n disposer.delete(actionId);\n\n // Remove the action data\n actionData.delete(actionId);\n\n // Remove the action entity after some time\n actionEntity != null && setTimeout(() => world.deleteEntity(actionEntity), 5000);\n }\n\n return { add, cancel, withOptimisticUpdates, Action };\n}\n","import { defineComponent } from \"../Component\";\nimport { Type } from \"../constants\";\nimport { World, Component, SchemaOf, Metadata } from \"../types\";\n\nexport function defineActionComponent<T = unknown>(world: World) {\n const Action = defineComponent(\n world,\n {\n state: Type.String,\n on: Type.OptionalEntity,\n metadata: Type.OptionalT,\n overrides: Type.OptionalStringArray,\n txHash: Type.OptionalString,\n },\n { id: \"Action\" },\n );\n return Action as Component<SchemaOf<typeof Action>, Metadata, T>;\n}\n"],"mappings":"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","names":["ActionState","merge","mapObject","awaitStreamValue","uuid","defineActionComponent","world","defineComponent","createActionSystem","world","txReduced$","waitForTransaction","Action","defineActionComponent","componentsWithOptimisticUpdates","actionData","disposer","dispose","withOptimisticUpdates","component","optimisticComponent","overridableComponent","add","actionRequest","entity","createEntity","setComponent","action","mapObject","c","subscription","merge","checkRequirement","getComponentValue","requirementResult","executeAction","updateComponent","overrides","o","uuid","value","id","tx","awaitStreamValue","v","handleError","remove","e","cancel","actionId","actionEntity","override","componentId"]}
1
+ {"version":3,"sources":["../../src/deprecated/constants.ts","../../src/deprecated/createActionSystem.ts","../../src/deprecated/defineActionComponent.ts"],"sourcesContent":["export enum ActionState {\n Requested = \"Requested\",\n Executing = \"Executing\",\n WaitingForTxEvents = \"WaitingForTxEvents\",\n Complete = \"Complete\",\n Failed = \"Failed\",\n Cancelled = \"Cancelled\",\n TxReduced = \"TxReduced\",\n}\n","import { merge, Observable } from \"rxjs\";\nimport { mapObject, awaitStreamValue, uuid } from \"@latticexyz/utils\";\nimport { ActionState } from \"./constants\";\nimport { ActionData, ActionRequest } from \"./types\";\nimport { defineActionComponent } from \"./defineActionComponent\";\nimport { overridableComponent, setComponent, getComponentValue, updateComponent } from \"../Component\";\nimport { createEntity } from \"../Entity\";\nimport { World, OverridableComponent, Metadata, Component, Components, Entity, Schema } from \"../types\";\n\nexport type ActionSystem = ReturnType<typeof createActionSystem>;\n\n/**\n * @deprecated For now, we suggest using `overridableComponent(Component)` and `addOverride`/`removeOverride` to manage overrides yourself.\n */\nexport function createActionSystem<M = unknown>(\n world: World,\n txReduced$: Observable<string>,\n waitForTransaction?: (tx: string) => Promise<void>,\n) {\n // Action component\n const Action = defineActionComponent<M>(world);\n\n // Components that scheduled actions depend on including pending updates\n const componentsWithOptimisticUpdates: { [id: string]: OverridableComponent<Schema> } = {};\n\n // ActionData contains requirements and execute logic of scheduled actions.\n // We also store the relevant subset of all componentsWithOptimisticUpdates in the action data,\n // to recheck requirements only if relevant components updated.\n const actionData = new Map<string, ActionData>();\n\n // Disposers of requirement check autoruns for all pending actions\n const disposer = new Map<string, { dispose: () => void }>();\n world.registerDisposer(() => {\n for (const { dispose } of disposer.values()) dispose();\n });\n\n /**\n * Maps all components in a given components map to the respective components including pending updates\n * @param component Component to be mapped to components including pending updates\n * @returns Components including pending updates\n */\n function withOptimisticUpdates<S extends Schema, M extends Metadata, T>(\n component: Component<S, M, T>,\n ): OverridableComponent<S, M, T> {\n const optimisticComponent = componentsWithOptimisticUpdates[component.id] || overridableComponent(component);\n\n // If the component is not tracked yet, add it to the map of overridable components\n if (!componentsWithOptimisticUpdates[component.id]) {\n componentsWithOptimisticUpdates[component.id] = optimisticComponent;\n }\n\n // Typescript can't know that the optimistic component with this id has the same type as C\n return optimisticComponent as OverridableComponent<S, M, T>;\n }\n\n /**\n * Schedules an action. The action will be executed once its requirement is fulfilled.\n * Note: the requirement will only be rechecked automatically if the requirement is based on components\n * (or other mobx-observable values).\n * @param actionRequest Action to be scheduled\n * @returns index of the entity created for the action\n */\n function add<C extends Components, T>(actionRequest: ActionRequest<C, T, M>): Entity {\n // Prevent the same actions from being scheduled multiple times\n const existingAction = world.hasEntity(actionRequest.id as Entity);\n if (existingAction) {\n console.warn(`Action with id ${actionRequest.id} is already requested.`);\n return actionRequest.id as Entity;\n }\n\n // Set the action component\n const entity = createEntity(world, undefined, {\n id: actionRequest.id,\n });\n\n setComponent(Action, entity, {\n state: ActionState.Requested,\n on: actionRequest.on,\n metadata: actionRequest.metadata,\n overrides: undefined,\n txHash: undefined,\n });\n\n // Add components that are not tracked yet to internal overridable component map.\n // Pending updates will be applied to internal overridable components.\n for (const component of Object.values(actionRequest.components)) {\n if (!componentsWithOptimisticUpdates[component.id])\n componentsWithOptimisticUpdates[component.id] = overridableComponent(component);\n }\n\n // Store relevant components with pending updates along the action's requirement and execution logic\n const action = {\n ...actionRequest,\n entity,\n componentsWithOptimisticUpdates: mapObject(actionRequest.components, (c) => withOptimisticUpdates(c)),\n } as unknown as ActionData;\n actionData.set(action.id, action);\n\n // This subscriotion makes sure the action requirement is checked again every time\n // one of the referenced components changes or the pending updates map changes\n const subscription = merge(\n ...Object.values(action.componentsWithOptimisticUpdates).map((c) => c.update$),\n ).subscribe(() => checkRequirement(action));\n checkRequirement(action);\n disposer.set(action.id, { dispose: () => subscription?.unsubscribe() });\n\n return entity;\n }\n\n /**\n * Checks the requirement of a given action and executes the action if the requirement is fulfilled\n * @param action Action to check the requirement of\n * @returns void\n */\n function checkRequirement(action: ActionData) {\n // Only check requirements of requested actions\n if (getComponentValue(Action, action.entity)?.state !== ActionState.Requested) return;\n\n // Check requirement on components including pending updates\n const requirementResult = action.requirement(action.componentsWithOptimisticUpdates);\n\n // Execute the action if the requirements are met\n if (requirementResult) executeAction(action, requirementResult);\n }\n\n /**\n * Executes the given action and sets the corresponding Action component\n * @param action ActionData of the action to be executed\n * @param requirementResult Result of the action's requirement function\n * @returns void\n */\n async function executeAction<T>(action: ActionData, requirementResult: T) {\n // Only execute actions that were requested before\n if (getComponentValue(Action, action.entity)?.state !== ActionState.Requested) return;\n\n // Update the action state\n updateComponent(Action, action.entity, { state: ActionState.Executing });\n\n // Compute overrides\n const overrides = action\n .updates(action.componentsWithOptimisticUpdates, requirementResult)\n .map((o) => ({ ...o, id: uuid() }));\n\n // Store overrides on Action component to be able to remove when action is done\n updateComponent(Action, action.entity, { overrides: overrides.map((o) => `${o.id}/${o.component.id}`) });\n\n // Set all pending updates of this action\n for (const { component, value, entity, id } of overrides) {\n componentsWithOptimisticUpdates[component.id].addOverride(id, { entity, value });\n }\n\n try {\n // Execute the action\n const tx = await action.execute(requirementResult);\n\n // If the result includes a hash key (single tx) or hashes (multiple tx) key, wait for the transactions to complete before removing the pending actions\n if (tx) {\n // Wait for all tx events to be reduced\n updateComponent(Action, action.entity, { state: ActionState.WaitingForTxEvents, txHash: tx });\n await awaitStreamValue(txReduced$, (v) => v === tx);\n updateComponent(Action, action.entity, { state: ActionState.TxReduced });\n // TODO: extend ActionData type to be aware of whether waitForTransaction is set\n if (action.awaitConfirmation) {\n if (waitForTransaction) {\n await waitForTransaction(tx);\n } else {\n throw new Error(\"action has awaitConfirmation but no waitForTransaction specified in createActionSystem\");\n }\n }\n }\n\n updateComponent(Action, action.entity, { state: ActionState.Complete });\n } catch (e) {\n handleError(e, action);\n }\n\n // After the action is done executing (failed or completed), remove its actionData and remove the Action component\n remove(action.id);\n }\n\n // Set the action's state to ActionState.Failed\n function handleError(e: unknown, action: ActionData) {\n console.error(e);\n updateComponent(Action, action.entity, { state: ActionState.Failed });\n remove(action.id);\n }\n\n /**\n * Cancels the action with the given ID if it is in the \"Requested\" state.\n * @param actionId ID of the action to be cancelled\n * @returns void\n */\n function cancel(actionId: string): boolean {\n const action = actionData.get(actionId);\n if (!action || getComponentValue(Action, action.entity)?.state !== ActionState.Requested) {\n console.warn(`Action ${actionId} was not found or is not in the \"Requested\" state.`);\n return false;\n }\n updateComponent(Action, action.entity, { state: ActionState.Cancelled });\n remove(actionId);\n return true;\n }\n\n /**\n * Removes actionData disposer of the action with the given ID and removes its pending updates.\n * @param actionId ID of the action to be removed\n */\n function remove(actionId: string) {\n const action = actionData.get(actionId);\n if (!action) {\n console.warn(`Trying to remove action ${actionId} that does not exist.`);\n return;\n }\n\n // Remove this action's pending updates\n const actionEntity = actionId as Entity;\n const overrides = (actionEntity != null && getComponentValue(Action, actionEntity)?.overrides) || [];\n for (const override of overrides) {\n const [id, componentId] = override.split(\"/\");\n const component = componentsWithOptimisticUpdates[componentId];\n component.removeOverride(id);\n }\n\n // Remove this action's autorun and corresponding disposer\n disposer.get(actionId)?.dispose();\n disposer.delete(actionId);\n\n // Remove the action data\n actionData.delete(actionId);\n\n // Remove the action entity after some time\n actionEntity != null && setTimeout(() => world.deleteEntity(actionEntity), 5000);\n }\n\n return { add, cancel, withOptimisticUpdates, Action };\n}\n","import { defineComponent } from \"../Component\";\nimport { Type } from \"../constants\";\nimport { World, Component, SchemaOf, Metadata } from \"../types\";\n\nexport function defineActionComponent<T = unknown>(world: World) {\n const Action = defineComponent(\n world,\n {\n state: Type.String,\n on: Type.OptionalEntity,\n metadata: Type.OptionalT,\n overrides: Type.OptionalStringArray,\n txHash: Type.OptionalString,\n },\n { id: \"Action\" },\n );\n return Action as Component<SchemaOf<typeof Action>, Metadata, T>;\n}\n"],"mappings":"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","names":["ActionState"]}