@latticexyz/recs 2.2.18-f0433092876e2ac9b5b12cd0ecae9c120a2d0368 → 2.2.18

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-PAKOIJAK.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"]}
package/dist/index.js CHANGED
@@ -1,2 +1,412 @@
1
- import{a as W,b as v,c as te,d as ne,e as g,f as V,g as re,h as oe,i as ie,j as S,k as pe,l as ae,m as ye,n as C,o as ue,p as E,q as s,r as l,s as me,t as h,u as de,v as O,w as b,x as se,y as le,z as ce}from"./chunk-2YR7WENB.js";import{concat as K,EMPTY as X,from as Z}from"rxjs";import{filterNullish as R}from"@latticexyz/utils";import{observable as B}from"mobx";import{concat as $,concatMap as q,filter as F,from as D,map as j,merge as L,of as z,share as Y}from"rxjs";var N=(o=>(o[o.Has=0]="Has",o[o.HasValue=1]="HasValue",o[o.Not=2]="Not",o[o.NotValue=3]="NotValue",o[o.ProxyRead=4]="ProxyRead",o[o.ProxyExpand=5]="ProxyExpand",o))(N||{});function xe(e){return[2,4,6,14,16,8,10,12].includes(e)}function Te(e){return[7,8,9,10,11,12,15,16].includes(e)}function ge(e){return[1,2].includes(e)}function Se(e){return[13,14].includes(e)}function Le(e){return{type:0,component:e}}function ze(e){return{type:2,component:e}}function Ye(e,t){return{type:1,component:e,value:t}}function Ge(e,t){return{type:3,component:e,value:t}}function Je(e,t){return{type:4,component:e,depth:t}}function Ke(e,t){return{type:5,component:e,depth:t}}function c(e,t){if(t.type===0)return s(t.component,e);if(t.type===1)return h(t.value,l(t.component,e));if(t.type===2)return!s(t.component,e);if(t.type===3)return!h(t.value,l(t.component,e));throw new Error("Unknown query fragment")}function G(e){return e.type===0||e.type==1}function P(e){return e.type===2||e.type==3}function J(e){return e.type===5||e.type==4}function U(e,t){return e&&G(t)||!e&&P(t)}function I(e,t,n){let r=e,a=!1;for(let y=0;y<n.depth;y++){let o=l(n.component,r);if(!o)return null;let p=o.value;if(!p)return null;if(r=p,a=c(r,t),U(a,t))return a}return a}function Q(e,t,n){if(n===0)return new Set;let r=O(t,{value:e});if(n===1)return r;let a=[...r].map(y=>[...Q(y,t,n-1)]).flat();return new Set([...r,...a])}function A(e,t){let n=t?new Set([...t]):void 0,r,a;for(let y=0;y<e.length;y++){let o=e[y];if(J(o))o.type===4&&(r=o),o.type===5&&(a=o);else if(n)for(let p of[...n]){let m=c(p,o);if(r&&r.depth>0&&!U(m,o)&&(m=I(p,o,r)??m),m||n.delete(p),a&&a.depth>0){let d=Q(p,a.component,a.depth);for(let i of d)(c(i,o)||r&&r.depth>0&&I(i,o,r))&&n.add(i)}}else{if(P(o))throw new Error("First EntityQueryFragment must be Has or HasValue");if(n=o.type===0?new Set([...b(o.component)]):O(o.component,o.value),a&&a.depth>0)for(let p of[...n])for(let m of Q(p,a.component,a.depth))n.add(m)}}return n??new Set}function f(e,t){let n=t?.runOnInit||t?.initialSet?A(e,t.initialSet):new Set,r=B(n),a=D(r).pipe(S(e[0].component)),y=e.findIndex(p=>[5,4].includes(p.type))!==-1,o=L(...e.map(p=>p.component.update$)).pipe(y?q(p=>{let m=A(e,t?.initialSet),d=[];for(let i of r)m.has(i)||(r.delete(i),d.push({entity:i,type:1,component:p.component,value:[void 0,void 0]}));for(let i of m)r.has(i)?d.push({entity:i,type:2,component:p.component,value:[l(p.component,i),void 0]}):(r.add(i),d.push({entity:i,type:0,component:p.component,value:[l(p.component,i),void 0]}));return z(...d)}):j(p=>{if(r.has(p.entity))return e.filter(u=>u.component.id===p.component.id).every(u=>c(p.entity,u))?{...p,type:2}:(r.delete(p.entity),{...p,type:1});if(e.every(d=>c(p.entity,d)))return r.add(p.entity),{...p,type:0}}),R());return{matching:r,update$:$(a,o).pipe(Y())}}function H(e,t){return f(e,t).update$.pipe(F(n=>n.type===2))}function w(e,t){return f(e,t).update$.pipe(F(n=>n.type===0))}function k(e,t){return f(e,t).update$.pipe(F(n=>n.type===1))}function x(e,t,n){let r=t.subscribe(n);e.registerDisposer(()=>r?.unsubscribe())}function ot(e,t,n,r={runOnInit:!0}){x(e,H(t,r),n)}function it(e,t,n,r={runOnInit:!0}){x(e,w(t,r),n)}function pt(e,t,n,r={runOnInit:!0}){x(e,k(t,r),n)}function _(e,t,n,r={runOnInit:!0}){x(e,f(t,r).update$,n)}function at(e,t,n,r={runOnInit:!0}){let a=r?.runOnInit?Z(b(t)).pipe(S(t)):X;x(e,K(a,t.update$),n)}function yt(e,t,n,r,a={update:!1,runOnInit:!0}){_(e,t,({entity:y,type:o})=>{o===0&&C(n(y),y,r(y)),o===1&&E(n(y),y),a?.update&&o===2&&C(n(y),y,r(y))},a)}import{transformIterator as ee}from"@latticexyz/utils";function lt(){let e=new Set,t=[],n=[];function r({id:i,idSuffix:u}={}){let T=i||e.size+(u?"-"+u:""),M=g(T);return e.add(M),T}function a(){return ee(e.values(),V)}function y(i){t.push(i)}function o(i){for(let[,u]of n.filter(T=>!i||T[0]===i))u();n=n.filter(u=>i&&u[0]!==i)}function p(i,u=""){n.push([u,i])}function m(i){let u=g(i);return e.has(u)}function d(i){for(let u of t)s(u,i)&&E(u,i);e.delete(g(i))}return{registerEntity:r,components:t,registerComponent:y,dispose:o,registerDisposer:p,hasEntity:m,getEntities:a,entitySymbols:e,deleteEntity:d}}function ct(e,t){return{...e,registerDisposer:n=>e.registerDisposer(n,t),dispose:()=>e.dispose(t)}}function ft(e,t){return e.components.filter(n=>s(n,t))}export{Le as Has,Ye as HasValue,ze as Not,Ge as NotValue,te as OptionalTypes,Ke as ProxyExpand,Je as ProxyRead,N as QueryFragmentType,W as Type,v as UpdateType,le as clearLocalCache,h as componentValueEquals,ne as createEntity,re as createIndexer,ce as createLocalCache,lt as createWorld,ye as defineComponent,at as defineComponentSystem,w as defineEnterQuery,it as defineEnterSystem,k as defineExitQuery,pt as defineExitSystem,f as defineQuery,x as defineRxSystem,yt as defineSyncSystem,_ as defineSystem,H as defineUpdateQuery,ot as defineUpdateSystem,Q as getChildEntities,b as getComponentEntities,l as getComponentValue,me as getComponentValueStrict,O as getEntitiesWithValue,ft as getEntityComponents,V as getEntityString,g as getEntitySymbol,s as hasComponent,Te as isArrayType,oe as isComponentUpdate,Se as isEntityType,ae as isFullComponentValue,pe as isIndexer,ge as isNumberType,xe as isOptionalType,ct as namespaceWorld,se as overridableComponent,E as removeComponent,A as runQuery,C as setComponent,ie as toUpdate,S as toUpdateStream,ue as updateComponent,de as withValue};
1
+ import {
2
+ OptionalTypes,
3
+ Type,
4
+ UpdateType,
5
+ clearLocalCache,
6
+ componentValueEquals,
7
+ createEntity,
8
+ createIndexer,
9
+ createLocalCache,
10
+ defineComponent,
11
+ getComponentEntities,
12
+ getComponentValue,
13
+ getComponentValueStrict,
14
+ getEntitiesWithValue,
15
+ getEntityString,
16
+ getEntitySymbol,
17
+ hasComponent,
18
+ isComponentUpdate,
19
+ isFullComponentValue,
20
+ isIndexer,
21
+ overridableComponent,
22
+ removeComponent,
23
+ setComponent,
24
+ toUpdate,
25
+ toUpdateStream,
26
+ updateComponent,
27
+ withValue
28
+ } from "./chunk-PAKOIJAK.js";
29
+
30
+ // src/System.ts
31
+ import { concat as concat2, EMPTY, from as from2 } from "rxjs";
32
+
33
+ // src/Query.ts
34
+ import { filterNullish } from "@latticexyz/utils";
35
+ import { observable } from "mobx";
36
+ import { concat, concatMap, filter, from, map, merge, of, share } from "rxjs";
37
+
38
+ // src/types.ts
39
+ var QueryFragmentType = /* @__PURE__ */ ((QueryFragmentType2) => {
40
+ QueryFragmentType2[QueryFragmentType2["Has"] = 0] = "Has";
41
+ QueryFragmentType2[QueryFragmentType2["HasValue"] = 1] = "HasValue";
42
+ QueryFragmentType2[QueryFragmentType2["Not"] = 2] = "Not";
43
+ QueryFragmentType2[QueryFragmentType2["NotValue"] = 3] = "NotValue";
44
+ QueryFragmentType2[QueryFragmentType2["ProxyRead"] = 4] = "ProxyRead";
45
+ QueryFragmentType2[QueryFragmentType2["ProxyExpand"] = 5] = "ProxyExpand";
46
+ return QueryFragmentType2;
47
+ })(QueryFragmentType || {});
48
+ function isOptionalType(t) {
49
+ return [
50
+ 2 /* OptionalNumber */,
51
+ 4 /* OptionalBigInt */,
52
+ 6 /* OptionalString */,
53
+ 14 /* OptionalEntity */,
54
+ 16 /* OptionalEntityArray */,
55
+ 8 /* OptionalNumberArray */,
56
+ 10 /* OptionalBigIntArray */,
57
+ 12 /* OptionalStringArray */
58
+ ].includes(t);
59
+ }
60
+ function isArrayType(t) {
61
+ return [
62
+ 7 /* NumberArray */,
63
+ 8 /* OptionalNumberArray */,
64
+ 9 /* BigIntArray */,
65
+ 10 /* OptionalBigIntArray */,
66
+ 11 /* StringArray */,
67
+ 12 /* OptionalStringArray */,
68
+ 15 /* EntityArray */,
69
+ 16 /* OptionalEntityArray */
70
+ ].includes(t);
71
+ }
72
+ function isNumberType(t) {
73
+ return [1 /* Number */, 2 /* OptionalNumber */].includes(t);
74
+ }
75
+ function isEntityType(t) {
76
+ return [13 /* Entity */, 14 /* OptionalEntity */].includes(t);
77
+ }
78
+
79
+ // src/Query.ts
80
+ function Has(component) {
81
+ return { type: 0 /* Has */, component };
82
+ }
83
+ function Not(component) {
84
+ return { type: 2 /* Not */, component };
85
+ }
86
+ function HasValue(component, value) {
87
+ return { type: 1 /* HasValue */, component, value };
88
+ }
89
+ function NotValue(component, value) {
90
+ return { type: 3 /* NotValue */, component, value };
91
+ }
92
+ function ProxyRead(component, depth) {
93
+ return { type: 4 /* ProxyRead */, component, depth };
94
+ }
95
+ function ProxyExpand(component, depth) {
96
+ return { type: 5 /* ProxyExpand */, component, depth };
97
+ }
98
+ function passesQueryFragment(entity, fragment) {
99
+ if (fragment.type === 0 /* Has */) {
100
+ return hasComponent(fragment.component, entity);
101
+ }
102
+ if (fragment.type === 1 /* HasValue */) {
103
+ return componentValueEquals(fragment.value, getComponentValue(fragment.component, entity));
104
+ }
105
+ if (fragment.type === 2 /* Not */) {
106
+ return !hasComponent(fragment.component, entity);
107
+ }
108
+ if (fragment.type === 3 /* NotValue */) {
109
+ return !componentValueEquals(fragment.value, getComponentValue(fragment.component, entity));
110
+ }
111
+ throw new Error("Unknown query fragment");
112
+ }
113
+ function isPositiveFragment(fragment) {
114
+ return fragment.type === 0 /* Has */ || fragment.type == 1 /* HasValue */;
115
+ }
116
+ function isNegativeFragment(fragment) {
117
+ return fragment.type === 2 /* Not */ || fragment.type == 3 /* NotValue */;
118
+ }
119
+ function isSettingFragment(fragment) {
120
+ return fragment.type === 5 /* ProxyExpand */ || fragment.type == 4 /* ProxyRead */;
121
+ }
122
+ function isBreakingPassState(passes, fragment) {
123
+ return passes && isPositiveFragment(fragment) || !passes && isNegativeFragment(fragment);
124
+ }
125
+ function passesQueryFragmentProxy(entity, fragment, proxyRead) {
126
+ let proxyEntity = entity;
127
+ let passes = false;
128
+ for (let i = 0; i < proxyRead.depth; i++) {
129
+ const value = getComponentValue(proxyRead.component, proxyEntity);
130
+ if (!value) return null;
131
+ const entity2 = value.value;
132
+ if (!entity2) return null;
133
+ proxyEntity = entity2;
134
+ passes = passesQueryFragment(proxyEntity, fragment);
135
+ if (isBreakingPassState(passes, fragment)) {
136
+ return passes;
137
+ }
138
+ }
139
+ return passes;
140
+ }
141
+ function getChildEntities(entity, component, depth) {
142
+ if (depth === 0) return /* @__PURE__ */ new Set();
143
+ const directChildEntities = getEntitiesWithValue(component, { value: entity });
144
+ if (depth === 1) return directChildEntities;
145
+ const indirectChildEntities = [...directChildEntities].map((childEntity) => [...getChildEntities(childEntity, component, depth - 1)]).flat();
146
+ return /* @__PURE__ */ new Set([...directChildEntities, ...indirectChildEntities]);
147
+ }
148
+ function runQuery(fragments, initialSet) {
149
+ let entities = initialSet ? /* @__PURE__ */ new Set([...initialSet]) : void 0;
150
+ let proxyRead = void 0;
151
+ let proxyExpand = void 0;
152
+ for (let i = 0; i < fragments.length; i++) {
153
+ const fragment = fragments[i];
154
+ if (isSettingFragment(fragment)) {
155
+ if (fragment.type === 4 /* ProxyRead */) proxyRead = fragment;
156
+ if (fragment.type === 5 /* ProxyExpand */) proxyExpand = fragment;
157
+ } else if (!entities) {
158
+ if (isNegativeFragment(fragment)) {
159
+ throw new Error("First EntityQueryFragment must be Has or HasValue");
160
+ }
161
+ entities = fragment.type === 0 /* Has */ ? /* @__PURE__ */ new Set([...getComponentEntities(fragment.component)]) : getEntitiesWithValue(fragment.component, fragment.value);
162
+ if (proxyExpand && proxyExpand.depth > 0) {
163
+ for (const entity of [...entities]) {
164
+ for (const childEntity of getChildEntities(entity, proxyExpand.component, proxyExpand.depth)) {
165
+ entities.add(childEntity);
166
+ }
167
+ }
168
+ }
169
+ } else {
170
+ for (const entity of [...entities]) {
171
+ let passes = passesQueryFragment(entity, fragment);
172
+ if (proxyRead && proxyRead.depth > 0 && !isBreakingPassState(passes, fragment)) {
173
+ passes = passesQueryFragmentProxy(entity, fragment, proxyRead) ?? passes;
174
+ }
175
+ if (!passes) entities.delete(entity);
176
+ if (proxyExpand && proxyExpand.depth > 0) {
177
+ const childEntities = getChildEntities(entity, proxyExpand.component, proxyExpand.depth);
178
+ for (const childEntity of childEntities) {
179
+ if (passesQueryFragment(childEntity, fragment) || proxyRead && proxyRead.depth > 0 && passesQueryFragmentProxy(childEntity, fragment, proxyRead))
180
+ entities.add(childEntity);
181
+ }
182
+ }
183
+ }
184
+ }
185
+ }
186
+ return entities ?? /* @__PURE__ */ new Set();
187
+ }
188
+ function defineQuery(fragments, options) {
189
+ const initialSet = options?.runOnInit || options?.initialSet ? runQuery(fragments, options.initialSet) : /* @__PURE__ */ new Set();
190
+ const matching = observable(initialSet);
191
+ const initial$ = from(matching).pipe(toUpdateStream(fragments[0].component));
192
+ const containsProxy = fragments.findIndex((v) => [5 /* ProxyExpand */, 4 /* ProxyRead */].includes(v.type)) !== -1;
193
+ const internal$ = merge(...fragments.map((f) => f.component.update$)).pipe(
194
+ containsProxy ? concatMap((update) => {
195
+ const newMatchingSet = runQuery(fragments, options?.initialSet);
196
+ const updates = [];
197
+ for (const previouslyMatchingEntity of matching) {
198
+ if (!newMatchingSet.has(previouslyMatchingEntity)) {
199
+ matching.delete(previouslyMatchingEntity);
200
+ updates.push({
201
+ entity: previouslyMatchingEntity,
202
+ type: 1 /* Exit */,
203
+ component: update.component,
204
+ value: [void 0, void 0]
205
+ });
206
+ }
207
+ }
208
+ for (const matchingEntity of newMatchingSet) {
209
+ if (matching.has(matchingEntity)) {
210
+ updates.push({
211
+ entity: matchingEntity,
212
+ type: 2 /* Update */,
213
+ component: update.component,
214
+ value: [getComponentValue(update.component, matchingEntity), void 0]
215
+ });
216
+ } else {
217
+ matching.add(matchingEntity);
218
+ updates.push({
219
+ entity: matchingEntity,
220
+ type: 0 /* Enter */,
221
+ component: update.component,
222
+ value: [getComponentValue(update.component, matchingEntity), void 0]
223
+ });
224
+ }
225
+ }
226
+ return of(...updates);
227
+ }) : (
228
+ // Query does not contain proxies
229
+ map((update) => {
230
+ if (matching.has(update.entity)) {
231
+ const relevantFragments = fragments.filter((f) => f.component.id === update.component.id);
232
+ const pass2 = relevantFragments.every((f) => passesQueryFragment(update.entity, f));
233
+ if (pass2) {
234
+ return { ...update, type: 2 /* Update */ };
235
+ } else {
236
+ matching.delete(update.entity);
237
+ return { ...update, type: 1 /* Exit */ };
238
+ }
239
+ }
240
+ const pass = fragments.every((f) => passesQueryFragment(update.entity, f));
241
+ if (pass) {
242
+ matching.add(update.entity);
243
+ return { ...update, type: 0 /* Enter */ };
244
+ }
245
+ })
246
+ ),
247
+ filterNullish()
248
+ );
249
+ return {
250
+ matching,
251
+ update$: concat(initial$, internal$).pipe(share())
252
+ };
253
+ }
254
+ function defineUpdateQuery(fragments, options) {
255
+ return defineQuery(fragments, options).update$.pipe(filter((e) => e.type === 2 /* Update */));
256
+ }
257
+ function defineEnterQuery(fragments, options) {
258
+ return defineQuery(fragments, options).update$.pipe(filter((e) => e.type === 0 /* Enter */));
259
+ }
260
+ function defineExitQuery(fragments, options) {
261
+ return defineQuery(fragments, options).update$.pipe(filter((e) => e.type === 1 /* Exit */));
262
+ }
263
+
264
+ // src/System.ts
265
+ function defineRxSystem(world, observable$, system) {
266
+ const subscription = observable$.subscribe(system);
267
+ world.registerDisposer(() => subscription?.unsubscribe());
268
+ }
269
+ function defineUpdateSystem(world, query, system, options = { runOnInit: true }) {
270
+ defineRxSystem(world, defineUpdateQuery(query, options), system);
271
+ }
272
+ function defineEnterSystem(world, query, system, options = { runOnInit: true }) {
273
+ defineRxSystem(world, defineEnterQuery(query, options), system);
274
+ }
275
+ function defineExitSystem(world, query, system, options = { runOnInit: true }) {
276
+ defineRxSystem(world, defineExitQuery(query, options), system);
277
+ }
278
+ function defineSystem(world, query, system, options = { runOnInit: true }) {
279
+ defineRxSystem(world, defineQuery(query, options).update$, system);
280
+ }
281
+ function defineComponentSystem(world, component, system, options = { runOnInit: true }) {
282
+ const initial$ = options?.runOnInit ? from2(getComponentEntities(component)).pipe(toUpdateStream(component)) : EMPTY;
283
+ defineRxSystem(world, concat2(initial$, component.update$), system);
284
+ }
285
+ function defineSyncSystem(world, query, component, value, options = { update: false, runOnInit: true }) {
286
+ defineSystem(
287
+ world,
288
+ query,
289
+ ({ entity, type }) => {
290
+ if (type === 0 /* Enter */) setComponent(component(entity), entity, value(entity));
291
+ if (type === 1 /* Exit */) removeComponent(component(entity), entity);
292
+ if (options?.update && type === 2 /* Update */) setComponent(component(entity), entity, value(entity));
293
+ },
294
+ options
295
+ );
296
+ }
297
+
298
+ // src/World.ts
299
+ import { transformIterator } from "@latticexyz/utils";
300
+ function createWorld() {
301
+ const entitySymbols = /* @__PURE__ */ new Set();
302
+ const components = [];
303
+ let disposers = [];
304
+ function registerEntity({ id, idSuffix } = {}) {
305
+ const entity = id || entitySymbols.size + (idSuffix ? "-" + idSuffix : "");
306
+ const entitySymbol = getEntitySymbol(entity);
307
+ entitySymbols.add(entitySymbol);
308
+ return entity;
309
+ }
310
+ function getEntities() {
311
+ return transformIterator(entitySymbols.values(), getEntityString);
312
+ }
313
+ function registerComponent(component) {
314
+ components.push(component);
315
+ }
316
+ function dispose(namespace) {
317
+ for (const [, disposer] of disposers.filter((d) => !namespace || d[0] === namespace)) {
318
+ disposer();
319
+ }
320
+ disposers = disposers.filter((d) => namespace && d[0] !== namespace);
321
+ }
322
+ function registerDisposer(disposer, namespace = "") {
323
+ disposers.push([namespace, disposer]);
324
+ }
325
+ function hasEntity(entity) {
326
+ const entitySymbol = getEntitySymbol(entity);
327
+ return entitySymbols.has(entitySymbol);
328
+ }
329
+ function deleteEntity(entity) {
330
+ for (const component of components) {
331
+ if (hasComponent(component, entity)) removeComponent(component, entity);
332
+ }
333
+ entitySymbols.delete(getEntitySymbol(entity));
334
+ }
335
+ return {
336
+ registerEntity,
337
+ components,
338
+ registerComponent,
339
+ dispose,
340
+ registerDisposer,
341
+ hasEntity,
342
+ getEntities,
343
+ entitySymbols,
344
+ deleteEntity
345
+ };
346
+ }
347
+ function namespaceWorld(world, namespace) {
348
+ return {
349
+ ...world,
350
+ registerDisposer: (disposer) => world.registerDisposer(disposer, namespace),
351
+ dispose: () => world.dispose(namespace)
352
+ };
353
+ }
354
+ function getEntityComponents(world, entity) {
355
+ return world.components.filter((component) => hasComponent(component, entity));
356
+ }
357
+ export {
358
+ Has,
359
+ HasValue,
360
+ Not,
361
+ NotValue,
362
+ OptionalTypes,
363
+ ProxyExpand,
364
+ ProxyRead,
365
+ QueryFragmentType,
366
+ Type,
367
+ UpdateType,
368
+ clearLocalCache,
369
+ componentValueEquals,
370
+ createEntity,
371
+ createIndexer,
372
+ createLocalCache,
373
+ createWorld,
374
+ defineComponent,
375
+ defineComponentSystem,
376
+ defineEnterQuery,
377
+ defineEnterSystem,
378
+ defineExitQuery,
379
+ defineExitSystem,
380
+ defineQuery,
381
+ defineRxSystem,
382
+ defineSyncSystem,
383
+ defineSystem,
384
+ defineUpdateQuery,
385
+ defineUpdateSystem,
386
+ getChildEntities,
387
+ getComponentEntities,
388
+ getComponentValue,
389
+ getComponentValueStrict,
390
+ getEntitiesWithValue,
391
+ getEntityComponents,
392
+ getEntityString,
393
+ getEntitySymbol,
394
+ hasComponent,
395
+ isArrayType,
396
+ isComponentUpdate,
397
+ isEntityType,
398
+ isFullComponentValue,
399
+ isIndexer,
400
+ isNumberType,
401
+ isOptionalType,
402
+ namespaceWorld,
403
+ overridableComponent,
404
+ removeComponent,
405
+ runQuery,
406
+ setComponent,
407
+ toUpdate,
408
+ toUpdateStream,
409
+ updateComponent,
410
+ withValue
411
+ };
2
412
  //# sourceMappingURL=index.js.map