@vworlds/vecs 1.0.0

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.
Files changed (58) hide show
  1. package/.claude/settings.json +12 -0
  2. package/.devcontainer/devcontainer.json +22 -0
  3. package/.github/workflows/publish.yml +32 -0
  4. package/README.md +464 -0
  5. package/dist/component.d.ts +135 -0
  6. package/dist/component.js +101 -0
  7. package/dist/component.js.map +1 -0
  8. package/dist/entity.d.ts +157 -0
  9. package/dist/entity.js +199 -0
  10. package/dist/entity.js.map +1 -0
  11. package/dist/index.d.ts +6 -0
  12. package/dist/index.js +4 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/package.json +25 -0
  15. package/dist/phase.d.ts +47 -0
  16. package/dist/phase.js +23 -0
  17. package/dist/phase.js.map +1 -0
  18. package/dist/system.d.ts +361 -0
  19. package/dist/system.js +396 -0
  20. package/dist/system.js.map +1 -0
  21. package/dist/util/array_map.d.ts +58 -0
  22. package/dist/util/array_map.js +84 -0
  23. package/dist/util/array_map.js.map +1 -0
  24. package/dist/util/bitset.d.ts +117 -0
  25. package/dist/util/bitset.js +177 -0
  26. package/dist/util/bitset.js.map +1 -0
  27. package/dist/util/events.d.ts +27 -0
  28. package/dist/util/events.js +43 -0
  29. package/dist/util/events.js.map +1 -0
  30. package/dist/util/ordered_set.d.ts +17 -0
  31. package/dist/util/ordered_set.js +69 -0
  32. package/dist/util/ordered_set.js.map +1 -0
  33. package/dist/world.d.ts +279 -0
  34. package/dist/world.js +453 -0
  35. package/dist/world.js.map +1 -0
  36. package/package.json +25 -0
  37. package/src/component.ts +180 -0
  38. package/src/entity.ts +276 -0
  39. package/src/index.ts +6 -0
  40. package/src/phase.ts +49 -0
  41. package/src/system.ts +693 -0
  42. package/src/util/array_map.ts +93 -0
  43. package/src/util/bitset.ts +199 -0
  44. package/src/util/events.ts +95 -0
  45. package/src/util/ordered_set.ts +82 -0
  46. package/src/world.ts +534 -0
  47. package/tests/_helpers.ts +30 -0
  48. package/tests/array_map.test.ts +68 -0
  49. package/tests/bitset.test.ts +127 -0
  50. package/tests/component.test.ts +104 -0
  51. package/tests/entity.test.ts +179 -0
  52. package/tests/events.test.ts +48 -0
  53. package/tests/ordered_set.test.ts +153 -0
  54. package/tests/setup.ts +6 -0
  55. package/tests/system.test.ts +800 -0
  56. package/tests/world.test.ts +174 -0
  57. package/tsconfig.json +21 -0
  58. package/vitest.config.ts +9 -0
@@ -0,0 +1,101 @@
1
+ import { BitPtr, Bitset } from "./util/bitset.js";
2
+ /**
3
+ * Internal bookkeeping record for a registered component class.
4
+ *
5
+ * Every component class that is passed to {@link World.registerComponent} gets
6
+ * a `ComponentMeta` that maps it to a numeric type id, a string name, and a
7
+ * pre-computed {@link BitPtr} used for fast archetype checks.
8
+ *
9
+ * `ComponentMeta` also implements {@link Hook}, so you can attach lifecycle
10
+ * callbacks directly on the meta object (as `World.hook()` returns it).
11
+ */
12
+ export class ComponentMeta {
13
+ constructor(Class, type, componentName) {
14
+ this.Class = Class;
15
+ this.type = type;
16
+ this.componentName = componentName;
17
+ this.bitPtr = new BitPtr(type);
18
+ }
19
+ /** @inheritdoc */
20
+ onAdd(handler) {
21
+ this.onAddHandler = handler;
22
+ return this;
23
+ }
24
+ /** @inheritdoc */
25
+ onRemove(handler) {
26
+ this.onRemoveHandler = handler;
27
+ return this;
28
+ }
29
+ /** @inheritdoc */
30
+ onSet(handler) {
31
+ this.onSetHandler = handler;
32
+ return this;
33
+ }
34
+ }
35
+ /**
36
+ * Base class for all ECS components.
37
+ *
38
+ * Extend this class to define data that can be attached to an {@link Entity}:
39
+ *
40
+ * ```ts
41
+ * class Position extends Component {
42
+ * x = 0;
43
+ * y = 0;
44
+ * }
45
+ *
46
+ * world.registerComponent(Position);
47
+ * const pos = entity.add(Position);
48
+ * pos.x = 100;
49
+ * pos.modified(); // notify watching systems
50
+ * ```
51
+ *
52
+ * A component instance is always bound to a single entity and is created by
53
+ * the world when {@link Entity.add} is called.
54
+ */
55
+ export class Component {
56
+ constructor(
57
+ /** The entity this component belongs to. */
58
+ entity,
59
+ /** Registration metadata (type id, name, bit-pointer). */
60
+ meta) {
61
+ this.entity = entity;
62
+ this.meta = meta;
63
+ this.dirty = false;
64
+ }
65
+ /** Numeric type id — shorthand for `this.meta.type`. */
66
+ get type() {
67
+ return this.meta.type;
68
+ }
69
+ /** Pre-computed bit-pointer — shorthand for `this.meta.bitPtr`. */
70
+ get bitPtr() {
71
+ return this.meta.bitPtr;
72
+ }
73
+ /**
74
+ * Notify the world that this component's data has changed.
75
+ *
76
+ * Queues the component for delivery to all {@link System.update} callbacks
77
+ * that watch this component type. Call this after mutating the component's
78
+ * fields to ensure systems react to the new values.
79
+ */
80
+ modified() {
81
+ this.entity.world._queueUpdatedComponent(this);
82
+ }
83
+ /** Returns the component's registered name, e.g. `"Position"`. */
84
+ toString() {
85
+ return this.meta.componentName;
86
+ }
87
+ }
88
+ /**
89
+ * Compute a {@link Bitset} that has a bit set for every component class or
90
+ * type id in `classes`.
91
+ *
92
+ * @internal Used internally to build archetype masks for system queries.
93
+ */
94
+ export function calculateComponentBitmask(classes, world) {
95
+ const bitmask = new Bitset();
96
+ classes.forEach((C) => {
97
+ bitmask.add(world.getComponentType(C));
98
+ });
99
+ return bitmask;
100
+ }
101
+ //# sourceMappingURL=component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"component.js","sourceRoot":"","sources":["../src/component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAoDlD;;;;;;;;;GASG;AACH,MAAM,OAAO,aAAa;IAaxB,YAAY,KAAuB,EAAE,IAAY,EAAE,aAAqB;QACtE,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;QACnC,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAED,kBAAkB;IACX,KAAK,CAAC,OAA+B;QAC1C,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC;QAC5B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,kBAAkB;IACX,QAAQ,CAAC,OAA+B;QAC7C,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC;QAC/B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,kBAAkB;IACX,KAAK,CAAC,OAA+B;QAC1C,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC;QAC5B,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAQD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,OAAO,SAAS;IAGpB;IACE,4CAA4C;IAC5B,MAAc;IAC9B,0DAA0D;IAC1C,IAAmB;QAFnB,WAAM,GAAN,MAAM,CAAQ;QAEd,SAAI,GAAJ,IAAI,CAAe;QAN7B,UAAK,GAAY,KAAK,CAAC;IAO5B,CAAC;IAEJ,wDAAwD;IACxD,IAAW,IAAI;QACb,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;IACxB,CAAC;IAED,mEAAmE;IACnE,IAAW,MAAM;QACf,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;IAC1B,CAAC;IAED;;;;;;OAMG;IACI,QAAQ;QACb,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC;IACjD,CAAC;IAED,kEAAkE;IAC3D,QAAQ;QACb,OAAO,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC;IACjC,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,UAAU,yBAAyB,CACvC,OAA4B,EAC5B,KAAY;IAEZ,MAAM,OAAO,GAAG,IAAI,MAAM,EAAE,CAAC;IAC7B,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;QACpB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IACH,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,157 @@
1
+ import { Component } from "./component.js";
2
+ import type { World } from "./world.js";
3
+ import { type System } from "./system.js";
4
+ import { Events } from "./util/events.js";
5
+ import { Bitset } from "./util/bitset.js";
6
+ type EntityEvents = Events<{
7
+ destroy(): void;
8
+ }>;
9
+ /**
10
+ * A game object — a unique identifier with an arbitrary set of
11
+ * {@link Component | components} attached to it.
12
+ *
13
+ * You never construct an `Entity` directly. Use {@link World.createEntity} for
14
+ * locally-owned entities or {@link World.getOrCreateEntity} when the id is
15
+ * assigned by an external authority (e.g. the server):
16
+ *
17
+ * ```ts
18
+ * const e = world.createEntity();
19
+ * const pos = e.add(Position);
20
+ * pos.x = 100;
21
+ * pos.modified();
22
+ * ```
23
+ *
24
+ * Entities support a parent–child hierarchy. When a parent is destroyed its
25
+ * children are destroyed recursively. The `children` set is created lazily.
26
+ */
27
+ export declare class Entity {
28
+ /** The {@link World} that owns this entity. */
29
+ readonly world: World;
30
+ /** Unique numeric entity id assigned at creation time. */
31
+ readonly eid: number;
32
+ private components;
33
+ private deletedComponents;
34
+ /**
35
+ * Bitmask representing the set of component types currently attached to this
36
+ * entity. Used by the world to efficiently match entities against system
37
+ * queries.
38
+ */
39
+ readonly componentBitmask: Bitset;
40
+ private readonly systems;
41
+ private readonly newSystems;
42
+ /**
43
+ * A free-form property bag that modules can use to associate arbitrary data
44
+ * with an entity without registering a component.
45
+ */
46
+ properties: Map<string, any>;
47
+ _events: EntityEvents;
48
+ /** Parent entity in the scene hierarchy, or `undefined` if root. */
49
+ parent: Entity | undefined;
50
+ private _children;
51
+ _archetypeChanged: boolean;
52
+ private destroyed;
53
+ constructor(
54
+ /** The {@link World} that owns this entity. */
55
+ world: World,
56
+ /** Unique numeric entity id assigned at creation time. */
57
+ eid: number);
58
+ /**
59
+ * The set of direct child entities in the scene hierarchy.
60
+ *
61
+ * The set is created lazily on first access. Mutate it only through
62
+ * {@link Entity.destroy} or by setting {@link Entity.parent} on a child —
63
+ * both will keep the parent–child links consistent.
64
+ */
65
+ get children(): Set<Entity>;
66
+ /**
67
+ * Add a component of type `Class` to this entity and return the instance.
68
+ *
69
+ * If the component is already present the existing instance is returned and
70
+ * no callback is fired. Pass `markAsModified = false` to suppress the
71
+ * initial `onSet` / `update` notification (useful when bulk-loading
72
+ * network snapshots before systems are running).
73
+ *
74
+ * @param Class - The component class to instantiate.
75
+ * @param markAsModified - Whether to immediately queue an `update`
76
+ * notification. Defaults to `true`.
77
+ * @returns The new (or existing) component instance, typed as
78
+ * `InstanceType<Class>`.
79
+ */
80
+ add<C extends typeof Component>(Class: C, markAsModified?: boolean): InstanceType<C>;
81
+ /**
82
+ * Add a component by its numeric type id.
83
+ *
84
+ * @param type - Numeric component type id (as returned by
85
+ * {@link World.getComponentType}).
86
+ * @param markAsModified - Whether to queue an update notification.
87
+ */
88
+ add(type: number, markAsModified?: boolean): Component;
89
+ /**
90
+ * Remove the component of the given class from this entity.
91
+ *
92
+ * The `onRemove` hook and any `exit` callbacks on matching systems are
93
+ * called when archetype changes are flushed at the end of the next system
94
+ * run. Does nothing if the component is not present.
95
+ *
96
+ * @param Class - The component class to remove.
97
+ */
98
+ remove<C extends typeof Component>(Class: C): void;
99
+ /**
100
+ * Remove a component by its numeric type id.
101
+ *
102
+ * @param type - Numeric component type id.
103
+ */
104
+ remove(type: number): void;
105
+ /** @internal Called by systems to deliver update notifications. */
106
+ _notifyModified(component: Component): void;
107
+ /**
108
+ * Retrieve the component of type `Class`, or `undefined` if not present.
109
+ *
110
+ * @param typeOrClass - Component class or numeric type id.
111
+ * @param get_deleted - If `true`, also search components that were removed
112
+ * in the current frame but not yet garbage-collected. Useful inside
113
+ * `exit` callbacks to read final component values.
114
+ * @returns The component instance or `undefined`.
115
+ */
116
+ get<C extends typeof Component>(typeOrClass: number | C, get_deleted?: boolean): InstanceType<C> | undefined;
117
+ /**
118
+ * Typed event emitter for entity-level lifecycle events.
119
+ *
120
+ * Currently emits one event:
121
+ * - `"destroy"` — fired just before the entity is fully torn down.
122
+ *
123
+ * The emitter is created lazily on first access.
124
+ */
125
+ get events(): EntityEvents;
126
+ /** @internal */
127
+ _hasSystem(s: System): boolean;
128
+ /** @internal */
129
+ _addSystem(s: System): void;
130
+ /** @internal */
131
+ _removeSystem(s: System): void;
132
+ /** @internal */
133
+ _updateSystems(): void;
134
+ /** `true` when the entity has no components attached. */
135
+ get empty(): boolean;
136
+ private _destroy;
137
+ /**
138
+ * Destroy this entity and recursively destroy all of its children.
139
+ *
140
+ * All components are removed (triggering `onRemove` hooks and `exit`
141
+ * callbacks), the entity is unregistered from the world, and the `"destroy"`
142
+ * event is emitted. The entity must not be used after calling this method.
143
+ */
144
+ destroy(): void;
145
+ /** @internal */
146
+ clearDeletedComponents(): void;
147
+ /**
148
+ * Iterate over every component currently attached to this entity.
149
+ *
150
+ * @param callback - Called with each component instance. Iteration order is
151
+ * not guaranteed.
152
+ */
153
+ forEachComponent(callback: (c: Component) => void): void;
154
+ /** Returns `"EntityN"` where N is the entity id. */
155
+ toString(): string;
156
+ }
157
+ export {};
package/dist/entity.js ADDED
@@ -0,0 +1,199 @@
1
+ import { ArrayMap } from "./util/array_map.js";
2
+ import { Events } from "./util/events.js";
3
+ import { Bitset } from "./util/bitset.js";
4
+ /**
5
+ * A game object — a unique identifier with an arbitrary set of
6
+ * {@link Component | components} attached to it.
7
+ *
8
+ * You never construct an `Entity` directly. Use {@link World.createEntity} for
9
+ * locally-owned entities or {@link World.getOrCreateEntity} when the id is
10
+ * assigned by an external authority (e.g. the server):
11
+ *
12
+ * ```ts
13
+ * const e = world.createEntity();
14
+ * const pos = e.add(Position);
15
+ * pos.x = 100;
16
+ * pos.modified();
17
+ * ```
18
+ *
19
+ * Entities support a parent–child hierarchy. When a parent is destroyed its
20
+ * children are destroyed recursively. The `children` set is created lazily.
21
+ */
22
+ export class Entity {
23
+ constructor(
24
+ /** The {@link World} that owns this entity. */
25
+ world,
26
+ /** Unique numeric entity id assigned at creation time. */
27
+ eid) {
28
+ this.world = world;
29
+ this.eid = eid;
30
+ this.components = new ArrayMap(); //maps component types to Components
31
+ this.deletedComponents = new ArrayMap(); //maps deleted component types to Components
32
+ /**
33
+ * Bitmask representing the set of component types currently attached to this
34
+ * entity. Used by the world to efficiently match entities against system
35
+ * queries.
36
+ */
37
+ this.componentBitmask = new Bitset();
38
+ this.systems = new Set();
39
+ this.newSystems = [];
40
+ /**
41
+ * A free-form property bag that modules can use to associate arbitrary data
42
+ * with an entity without registering a component.
43
+ */
44
+ this.properties = new Map();
45
+ this._archetypeChanged = false;
46
+ this.destroyed = false;
47
+ }
48
+ /**
49
+ * The set of direct child entities in the scene hierarchy.
50
+ *
51
+ * The set is created lazily on first access. Mutate it only through
52
+ * {@link Entity.destroy} or by setting {@link Entity.parent} on a child —
53
+ * both will keep the parent–child links consistent.
54
+ */
55
+ get children() {
56
+ if (!this._children)
57
+ this._children = new Set();
58
+ return this._children;
59
+ }
60
+ add(typeOrClass, markAsModified = true) {
61
+ const type = this.world.getComponentType(typeOrClass);
62
+ let c = this.components.get(type);
63
+ if (c) {
64
+ return c;
65
+ }
66
+ c = this.world["getComponentInstance"](typeOrClass, this);
67
+ this.components.set(type, c);
68
+ this.componentBitmask.add(type);
69
+ this.world._notifyComponentAdded(this, c);
70
+ if (markAsModified)
71
+ this.world._queueUpdatedComponent(c);
72
+ return c;
73
+ }
74
+ remove(typeOrClass) {
75
+ const type = this.world.getComponentType(typeOrClass);
76
+ const c = this.components.get(type);
77
+ if (c) {
78
+ this.components.delete(type);
79
+ this.deletedComponents.set(type, c);
80
+ this.componentBitmask.delete(type);
81
+ this.world._notifyComponentRemoved(this, c);
82
+ }
83
+ }
84
+ /** @internal Called by systems to deliver update notifications. */
85
+ _notifyModified(component) {
86
+ this.systems.forEach((s) => {
87
+ s.notifyModified(component);
88
+ });
89
+ }
90
+ /**
91
+ * Retrieve the component of type `Class`, or `undefined` if not present.
92
+ *
93
+ * @param typeOrClass - Component class or numeric type id.
94
+ * @param get_deleted - If `true`, also search components that were removed
95
+ * in the current frame but not yet garbage-collected. Useful inside
96
+ * `exit` callbacks to read final component values.
97
+ * @returns The component instance or `undefined`.
98
+ */
99
+ get(typeOrClass, get_deleted = false) {
100
+ const type = this.world.getComponentType(typeOrClass);
101
+ const c = this.components.get(type);
102
+ if (!c && get_deleted) {
103
+ return this.deletedComponents.get(type);
104
+ }
105
+ return c;
106
+ }
107
+ /**
108
+ * Typed event emitter for entity-level lifecycle events.
109
+ *
110
+ * Currently emits one event:
111
+ * - `"destroy"` — fired just before the entity is fully torn down.
112
+ *
113
+ * The emitter is created lazily on first access.
114
+ */
115
+ get events() {
116
+ if (!this._events) {
117
+ this._events = new Events();
118
+ }
119
+ return this._events;
120
+ }
121
+ /** @internal */
122
+ _hasSystem(s) {
123
+ return this.systems.has(s);
124
+ }
125
+ /** @internal */
126
+ _addSystem(s) {
127
+ if (!this.systems.has(s)) {
128
+ this.newSystems.push(s);
129
+ s._enter(this);
130
+ }
131
+ }
132
+ /** @internal */
133
+ _removeSystem(s) {
134
+ if (this.systems.delete(s)) {
135
+ s._exit(this);
136
+ }
137
+ }
138
+ /** @internal */
139
+ _updateSystems() {
140
+ this.newSystems.forEach((s) => {
141
+ this.systems.add(s);
142
+ });
143
+ this.newSystems.length = 0;
144
+ }
145
+ /** `true` when the entity has no components attached. */
146
+ get empty() {
147
+ return this.components.size == 0;
148
+ }
149
+ _destroy() {
150
+ if (this.destroyed)
151
+ return;
152
+ this.destroyed = true;
153
+ this.systems.forEach((s) => {
154
+ s._exit(this);
155
+ });
156
+ this.systems.clear();
157
+ if (this._events) {
158
+ this._events.emit("destroy");
159
+ this._events.removeAllListeners("destroy");
160
+ }
161
+ }
162
+ /**
163
+ * Destroy this entity and recursively destroy all of its children.
164
+ *
165
+ * All components are removed (triggering `onRemove` hooks and `exit`
166
+ * callbacks), the entity is unregistered from the world, and the `"destroy"`
167
+ * event is emitted. The entity must not be used after calling this method.
168
+ */
169
+ destroy() {
170
+ this.world._notifyEntityDestroyed(this);
171
+ this.children.forEach((child) => {
172
+ child.destroy();
173
+ });
174
+ this.children.clear();
175
+ if (this.parent) {
176
+ this.parent.children.delete(this);
177
+ this.world.archetypeChanged(this.parent);
178
+ this.parent = undefined;
179
+ }
180
+ }
181
+ /** @internal */
182
+ clearDeletedComponents() {
183
+ this.deletedComponents.clear();
184
+ }
185
+ /**
186
+ * Iterate over every component currently attached to this entity.
187
+ *
188
+ * @param callback - Called with each component instance. Iteration order is
189
+ * not guaranteed.
190
+ */
191
+ forEachComponent(callback) {
192
+ this.components.forEach(callback);
193
+ }
194
+ /** Returns `"EntityN"` where N is the entity id. */
195
+ toString() {
196
+ return `Entity${this.eid}`;
197
+ }
198
+ }
199
+ //# sourceMappingURL=entity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entity.js","sourceRoot":"","sources":["../src/entity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export { type System } from "./system.js";
2
+ export { World } from "./world.js";
3
+ export { Component, type ComponentMeta } from "./component.js";
4
+ export { type Entity } from "./entity.js";
5
+ export { type IPhase } from "./phase.js";
6
+ export { Bitset } from "./util/bitset.js";
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { World } from "./world.js";
2
+ export { Component } from "./component.js";
3
+ export { Bitset } from "./util/bitset.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,SAAS,EAAsB,MAAM,gBAAgB,CAAC;AAG/D,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "@vworlds/vecs",
3
+ "version": "1.0.0",
4
+ "main": "dist/index.js",
5
+ "types": "dist/index.d.ts",
6
+ "type": "module",
7
+ "scripts": {
8
+ "clean": "rimraf dist && rimraf tsconfig.tsbuildinfo",
9
+ "prepack": "yarn build",
10
+ "build": "yarn clean && yarn compile",
11
+ "compile": "tsc --build && cp \"./package.json\" ./dist/",
12
+ "test": "vitest run",
13
+ "test:watch": "vitest"
14
+ },
15
+ "devDependencies": {
16
+ "@types/node": "^20.0.0",
17
+ "rimraf": "^5.0.0",
18
+ "typescript": "^4.8.4",
19
+ "vitest": "^1.6.0"
20
+ },
21
+ "dependencies": {
22
+ "eventemitter3": "^4.0.7"
23
+ },
24
+ "license": "UNLICENSED"
25
+ }
@@ -0,0 +1,47 @@
1
+ import { type System } from "./system.js";
2
+ import { type World } from "./world.js";
3
+ /**
4
+ * A named, ordered bucket of {@link System | systems} within the world's
5
+ * update pipeline.
6
+ *
7
+ * Created internally by {@link World.addPhase}. The systems in a phase run in
8
+ * the order they were registered. Between each system run the world flushes
9
+ * pending archetype changes, so `enter` / `exit` callbacks are always
10
+ * delivered before the next system executes.
11
+ *
12
+ * @internal The concrete class is not part of the public API. Use
13
+ * {@link IPhase} to refer to phases in user code.
14
+ */
15
+ export declare class Phase {
16
+ /** Name used to look up the phase in the pipeline. */
17
+ readonly name: string;
18
+ world: World;
19
+ /** Systems that belong to this phase, in execution order. */
20
+ systems: System[];
21
+ constructor(
22
+ /** Name used to look up the phase in the pipeline. */
23
+ name: string, world: World);
24
+ }
25
+ /**
26
+ * Public interface for a pipeline phase returned by {@link World.addPhase}.
27
+ *
28
+ * Pass an `IPhase` to {@link System.phase} to assign a system to that phase,
29
+ * or to {@link World.runPhase} to execute it:
30
+ *
31
+ * ```ts
32
+ * const preUpdate = world.addPhase("preupdate");
33
+ * const send = world.addPhase("send");
34
+ *
35
+ * world.system("NetworkUpdate").phase(preUpdate).run(tick);
36
+ *
37
+ * // each frame:
38
+ * world.runPhase(preUpdate, now, delta);
39
+ * world.runPhase(send, now, delta);
40
+ * ```
41
+ */
42
+ export interface IPhase {
43
+ /** The name this phase was registered under. */
44
+ get name(): string;
45
+ /** The world that owns this phase. */
46
+ get world(): World;
47
+ }
package/dist/phase.js ADDED
@@ -0,0 +1,23 @@
1
+ /**
2
+ * A named, ordered bucket of {@link System | systems} within the world's
3
+ * update pipeline.
4
+ *
5
+ * Created internally by {@link World.addPhase}. The systems in a phase run in
6
+ * the order they were registered. Between each system run the world flushes
7
+ * pending archetype changes, so `enter` / `exit` callbacks are always
8
+ * delivered before the next system executes.
9
+ *
10
+ * @internal The concrete class is not part of the public API. Use
11
+ * {@link IPhase} to refer to phases in user code.
12
+ */
13
+ export class Phase {
14
+ constructor(
15
+ /** Name used to look up the phase in the pipeline. */
16
+ name, world) {
17
+ this.name = name;
18
+ this.world = world;
19
+ /** Systems that belong to this phase, in execution order. */
20
+ this.systems = [];
21
+ }
22
+ }
23
+ //# sourceMappingURL=phase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"phase.js","sourceRoot":"","sources":["../src/phase.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,KAAK;IAIhB;IACE,sDAAsD;IACtC,IAAY,EACrB,KAAY;QADH,SAAI,GAAJ,IAAI,CAAQ;QACrB,UAAK,GAAL,KAAK,CAAO;QANrB,6DAA6D;QACtD,YAAO,GAAa,EAAE,CAAC;IAM3B,CAAC;CACL"}