@funderforge/ecs 0.1.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.
- package/LICENSE +21 -0
- package/README.md +412 -0
- package/dist/component.d.ts +135 -0
- package/dist/component.d.ts.map +1 -0
- package/dist/component.js +176 -0
- package/dist/component.js.map +1 -0
- package/dist/entity.d.ts +222 -0
- package/dist/entity.d.ts.map +1 -0
- package/dist/entity.js +418 -0
- package/dist/entity.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/package.json +52 -0
package/dist/entity.js
ADDED
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents an entity in a hierarchical tree structure that can contain child entities and components.
|
|
3
|
+
* Entities form the backbone of the component framework, allowing you to build flexible hierarchies
|
|
4
|
+
* where each entity can have multiple components attached to it.
|
|
5
|
+
*
|
|
6
|
+
* Key features:
|
|
7
|
+
* - Hierarchical parent-child relationships
|
|
8
|
+
* - Cascading enabled/disabled state management with caching
|
|
9
|
+
* - Component attachment and management
|
|
10
|
+
* - Efficient traversal of entities and components
|
|
11
|
+
* - Method-based architecture through component virtual methods
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* const root = new Entity({ id: 'root' });
|
|
16
|
+
* const child = new Entity({ id: 'child', parent: root });
|
|
17
|
+
* root.addChild(child);
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export default class Entity {
|
|
21
|
+
_children = [];
|
|
22
|
+
_parent = null;
|
|
23
|
+
_enabledSelf = true;
|
|
24
|
+
_enabledCache = null; // Cache for enabled property
|
|
25
|
+
/** Unique identifier for this entity. Can be a string or number. If not provided in constructor, an auto-incrementing number is assigned. */
|
|
26
|
+
id;
|
|
27
|
+
static _idCounter = Number.MIN_SAFE_INTEGER;
|
|
28
|
+
_components = [];
|
|
29
|
+
// biome-ignore lint/complexity/noBannedTypes: On purpose, we need to support any constructor
|
|
30
|
+
_componentMap = new Map();
|
|
31
|
+
/**
|
|
32
|
+
* Creates a new Entity instance.
|
|
33
|
+
* @param preset - Optional configuration object for the entity.
|
|
34
|
+
* @param preset.id - Optional unique identifier. If not provided, an auto-incrementing number is assigned.
|
|
35
|
+
* @param preset.enabledSelf - Whether the entity is enabled by default. Defaults to `true`.
|
|
36
|
+
* @param preset.parent - Optional parent entity. If provided, this entity will be added as a child of the parent.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```typescript
|
|
40
|
+
* // Create a root entity with a custom ID
|
|
41
|
+
* const root = new Entity({ id: 'scene' });
|
|
42
|
+
*
|
|
43
|
+
* // Create a child entity with a parent
|
|
44
|
+
* const child = new Entity({ id: 'player', parent: root, enabledSelf: true });
|
|
45
|
+
*
|
|
46
|
+
* // Create an entity that will be auto-assigned an ID
|
|
47
|
+
* const entity = new Entity();
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
constructor(preset = {}) {
|
|
51
|
+
this.id = preset.id ?? Entity._idCounter++;
|
|
52
|
+
this._enabledSelf = preset.enabledSelf ?? true;
|
|
53
|
+
if (preset.parent) {
|
|
54
|
+
this.setParent(preset.parent);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Gets whether this entity itself is enabled, independent of its parent's state.
|
|
59
|
+
* @returns `true` if this entity is enabled, `false` otherwise.
|
|
60
|
+
*/
|
|
61
|
+
get enabledSelf() {
|
|
62
|
+
return this._enabledSelf;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Sets whether this entity itself is enabled. When set to `false`, this entity and all its descendants become disabled.
|
|
66
|
+
* Invalidates the enabled cache for this entity and all descendants, and calls `onEnabledChanged` on affected components.
|
|
67
|
+
* @param value - `true` to enable this entity, `false` to disable it.
|
|
68
|
+
*/
|
|
69
|
+
set enabledSelf(value) {
|
|
70
|
+
if (value === this._enabledSelf)
|
|
71
|
+
return;
|
|
72
|
+
const oldEnabled = this.enabled;
|
|
73
|
+
this._enabledSelf = value;
|
|
74
|
+
// Invalidate enabled cache for this entity and all descendants
|
|
75
|
+
this._invalidateEnabledCache();
|
|
76
|
+
const newEnabled = this.enabled;
|
|
77
|
+
if (newEnabled === oldEnabled) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
for (const component of this._components) {
|
|
81
|
+
if (component.enabledSelf) {
|
|
82
|
+
// biome-ignore lint/suspicious/noExplicitAny: Override protected guard
|
|
83
|
+
component.onEnabledChanged(newEnabled);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
for (const child of this.traverseChildren((child) => child.enabledSelf)) {
|
|
87
|
+
for (const component of child._components) {
|
|
88
|
+
if (component.enabledSelf) {
|
|
89
|
+
// biome-ignore lint/suspicious/noExplicitAny: Override protected guard
|
|
90
|
+
component.onEnabledChanged(newEnabled);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Gets the effective enabled state of this entity, considering both its own `enabledSelf` value and all parent entities' enabled states.
|
|
97
|
+
* The result is cached for performance and automatically invalidated when necessary.
|
|
98
|
+
* @returns `true` only if this entity's `enabledSelf` is `true` and all parent entities (up to the root) have `enabledSelf` set to `true`.
|
|
99
|
+
*/
|
|
100
|
+
get enabled() {
|
|
101
|
+
// Return cached value if available
|
|
102
|
+
if (this._enabledCache !== null) {
|
|
103
|
+
return this._enabledCache;
|
|
104
|
+
}
|
|
105
|
+
// iterate through self and parents until a parent is found false
|
|
106
|
+
let current = this;
|
|
107
|
+
while (current) {
|
|
108
|
+
if (!current.enabledSelf) {
|
|
109
|
+
this._enabledCache = false;
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
current = current.parent;
|
|
113
|
+
}
|
|
114
|
+
this._enabledCache = true;
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Invalidates the enabled cache for this entity and all its descendants.
|
|
119
|
+
* This is called when enabledSelf changes or when parent changes.
|
|
120
|
+
* Uses an iterative approach with a stack to avoid potential stack overflow for deep trees.
|
|
121
|
+
*/
|
|
122
|
+
_invalidateEnabledCache() {
|
|
123
|
+
const stack = [this];
|
|
124
|
+
while (stack.length) {
|
|
125
|
+
// biome-ignore lint/style/noNonNullAssertion: stack is not null
|
|
126
|
+
const entity = stack.pop();
|
|
127
|
+
entity._enabledCache = null;
|
|
128
|
+
// Push all children onto the stack
|
|
129
|
+
for (let i = entity._children.length - 1; i >= 0; i--) {
|
|
130
|
+
stack.push(entity._children[i]);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Adds a child entity to this entity. If the child already has a parent, it will be removed from its previous parent first.
|
|
136
|
+
* @param child - The entity to add as a child.
|
|
137
|
+
*/
|
|
138
|
+
addChild(child) {
|
|
139
|
+
this._children.push(child);
|
|
140
|
+
if (child.parent) {
|
|
141
|
+
child.parent.removeChild(child);
|
|
142
|
+
}
|
|
143
|
+
child._parent = this;
|
|
144
|
+
child._invalidateEnabledCache();
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Removes a child entity by its index in the children array. The removed child's parent will be set to `null`.
|
|
148
|
+
* @param index - The index of the child to remove.
|
|
149
|
+
*/
|
|
150
|
+
removeChildByIndex(index) {
|
|
151
|
+
const child = this._children.splice(index, 1);
|
|
152
|
+
child[0].setParent(null);
|
|
153
|
+
child[0]._invalidateEnabledCache();
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Removes a child entity. The removed child's parent will be set to `null`.
|
|
157
|
+
* @param child - The child entity to remove.
|
|
158
|
+
*/
|
|
159
|
+
removeChild(child) {
|
|
160
|
+
const index = this._children.indexOf(child);
|
|
161
|
+
if (index !== -1) {
|
|
162
|
+
this._children.splice(index, 1);
|
|
163
|
+
child.setParent(null);
|
|
164
|
+
child._invalidateEnabledCache();
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Gets the number of direct child entities.
|
|
169
|
+
* @returns The number of children.
|
|
170
|
+
*/
|
|
171
|
+
childrenLength() {
|
|
172
|
+
return this._children.length;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Gets a child entity by its index in the children array.
|
|
176
|
+
* @template T - The type of entity to return. Defaults to `Entity`.
|
|
177
|
+
* @param index - The index of the child to retrieve.
|
|
178
|
+
* @returns The child entity at the specified index, or `undefined` if the index is out of bounds.
|
|
179
|
+
*/
|
|
180
|
+
childByIdx(index) {
|
|
181
|
+
return this._children[index];
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Finds the first child entity that matches the given predicate.
|
|
185
|
+
* @template T - The type of entity to return. Defaults to `Entity`.
|
|
186
|
+
* @param predicate - A function that returns `true` for the child to find.
|
|
187
|
+
* @returns The first matching child entity, or `undefined` if no match is found.
|
|
188
|
+
*/
|
|
189
|
+
getChild(predicate) {
|
|
190
|
+
return this._children.find(predicate);
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Gets the index of a child entity in the children array.
|
|
194
|
+
* @param child - The child entity to find the index of.
|
|
195
|
+
* @returns The index of the child, or `-1` if not found.
|
|
196
|
+
*/
|
|
197
|
+
indexOfChild(child) {
|
|
198
|
+
return this._children.indexOf(child);
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Gets all child entities that match the given filter function.
|
|
202
|
+
* @template T - The type of entity to return. Defaults to `Entity`.
|
|
203
|
+
* @param filter - A function that returns `true` for children to include.
|
|
204
|
+
* @returns An array of matching child entities.
|
|
205
|
+
*/
|
|
206
|
+
getChildren(filter) {
|
|
207
|
+
return this._children.filter(filter);
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Traverses the children of this entity and all its descendants using a depth-first approach.
|
|
211
|
+
* @template T - The type of entity to yield. Defaults to `Entity`.
|
|
212
|
+
* @param predicate - Optional predicate to filter the children. If provided and returns `true`, the child will be yielded and its descendants will be traversed. If omitted, all children are traversed.
|
|
213
|
+
* @returns A generator that yields entities in the traversal order.
|
|
214
|
+
*/
|
|
215
|
+
*traverseChildren(predicate) {
|
|
216
|
+
const stack = [];
|
|
217
|
+
for (let i = this._children.length - 1; i >= 0; i--) {
|
|
218
|
+
stack.push(this._children[i]);
|
|
219
|
+
}
|
|
220
|
+
while (stack.length) {
|
|
221
|
+
// biome-ignore lint/style/noNonNullAssertion: stack is not null
|
|
222
|
+
const e = stack.pop();
|
|
223
|
+
if (predicate && !predicate(e))
|
|
224
|
+
continue;
|
|
225
|
+
yield e;
|
|
226
|
+
const c = e._children;
|
|
227
|
+
for (let i = c.length - 1; i >= 0; i--) {
|
|
228
|
+
stack.push(c[i]);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Traverses the components of this entity and all its descendants using a pre-order depth-first approach.
|
|
234
|
+
* Only traverses enabled entities. Components are yielded before their entity's children.
|
|
235
|
+
* @template T - The type of component to yield. Defaults to `Component`.
|
|
236
|
+
* @param predicate - Optional predicate to filter the components. If provided and returns `true`, the component will be yielded. If omitted, all components are traversed.
|
|
237
|
+
* @returns A generator that yields components in the traversal order.
|
|
238
|
+
*/
|
|
239
|
+
*traverseComponents(predicate) {
|
|
240
|
+
const stack = [];
|
|
241
|
+
// push root
|
|
242
|
+
stack.push(this);
|
|
243
|
+
const hasPredicate = predicate !== undefined;
|
|
244
|
+
while (stack.length) {
|
|
245
|
+
// biome-ignore lint/style/noNonNullAssertion: stack is not null
|
|
246
|
+
const entity = stack.pop();
|
|
247
|
+
// yield components first (pre-order)
|
|
248
|
+
const components = entity._components;
|
|
249
|
+
for (let i = 0; i < components.length; i++) {
|
|
250
|
+
const component = components[i];
|
|
251
|
+
if (!hasPredicate || predicate(component)) {
|
|
252
|
+
yield component;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
// push children in reverse to preserve order
|
|
256
|
+
const children = entity._children;
|
|
257
|
+
for (let i = children.length - 1; i >= 0; i--) {
|
|
258
|
+
const child = children[i];
|
|
259
|
+
if (child.enabledSelf) {
|
|
260
|
+
stack.push(child);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Sets or clears the parent entity. If setting a new parent, this entity will be removed from its previous parent and added to the new one.
|
|
267
|
+
* Invalidates the enabled cache when the parent changes.
|
|
268
|
+
* @param parent - The new parent entity, or `null` to remove the parent.
|
|
269
|
+
*/
|
|
270
|
+
setParent(parent) {
|
|
271
|
+
if (this._parent) {
|
|
272
|
+
this._parent.removeChild(this);
|
|
273
|
+
}
|
|
274
|
+
this._parent = parent;
|
|
275
|
+
if (parent) {
|
|
276
|
+
parent._children.push(this);
|
|
277
|
+
}
|
|
278
|
+
// Invalidate enabled cache when parent changes
|
|
279
|
+
this._invalidateEnabledCache();
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Gets the parent entity in the hierarchy.
|
|
283
|
+
* @returns The parent entity, or `null` if this entity has no parent (i.e., it's a root entity).
|
|
284
|
+
*/
|
|
285
|
+
get parent() {
|
|
286
|
+
return this._parent;
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Gets the depth level of this entity in the hierarchy. Root entities have a level of 0.
|
|
290
|
+
* @returns The number of ancestors (parent entities) in the hierarchy chain.
|
|
291
|
+
*/
|
|
292
|
+
hierarchyLevel() {
|
|
293
|
+
let level = 0;
|
|
294
|
+
let current = this._parent;
|
|
295
|
+
while (current) {
|
|
296
|
+
level++;
|
|
297
|
+
current = current.parent;
|
|
298
|
+
}
|
|
299
|
+
return level;
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Gets the number of components attached to this entity.
|
|
303
|
+
* @returns The number of components.
|
|
304
|
+
*/
|
|
305
|
+
componentsLength() {
|
|
306
|
+
return this._components.length;
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Gets a component by its index in the components array.
|
|
310
|
+
* @template T - The type of component to return. Defaults to `Component`.
|
|
311
|
+
* @param index - The index of the component to retrieve.
|
|
312
|
+
* @returns The component at the specified index, or `undefined` if the index is out of bounds.
|
|
313
|
+
*/
|
|
314
|
+
componentByIdx(index) {
|
|
315
|
+
return this._components[index];
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Finds the first component that matches the given predicate.
|
|
319
|
+
* @template T - The type of component to return. Defaults to `Component`.
|
|
320
|
+
* @param predicate - A function that returns `true` for the component to find.
|
|
321
|
+
* @returns The first matching component, or `undefined` if no match is found.
|
|
322
|
+
*/
|
|
323
|
+
getComponent(predicate) {
|
|
324
|
+
return this._components.find(predicate);
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Finds the first component of the specified type. Uses an optimized type map for fast lookups when available.
|
|
328
|
+
*
|
|
329
|
+
* **Performance Note:** Components are only added to the internal type map for optimized lookups when they are
|
|
330
|
+
* created with `precacheTypeLookup: true`. If a component is created with `precacheTypeLookup: false` (the default),
|
|
331
|
+
* it will not be in the type map and the lookup will fall back to iterating through all components, which is slower
|
|
332
|
+
* but avoids the overhead of maintaining the map for components that are rarely looked up by type.
|
|
333
|
+
*
|
|
334
|
+
* @template T - The type of component to return.
|
|
335
|
+
* @param type - The constructor function of the component type to find.
|
|
336
|
+
* @returns The first matching component of the specified type, or `undefined` if not found.
|
|
337
|
+
*
|
|
338
|
+
* @example
|
|
339
|
+
* ```typescript
|
|
340
|
+
* class TransformComponent extends Component {}
|
|
341
|
+
* const entity = new Entity();
|
|
342
|
+
* // Component is NOT added to type map by default (precacheTypeLookup defaults to false)
|
|
343
|
+
* const transform = new TransformComponent(entity);
|
|
344
|
+
* const found = entity.getComponentByType(TransformComponent); // Slower, iterates through components
|
|
345
|
+
*
|
|
346
|
+
* // Component is added to type map for fast lookups (precacheTypeLookup: true)
|
|
347
|
+
* const render = new RenderComponent(entity, { precacheTypeLookup: true });
|
|
348
|
+
* const foundRender = entity.getComponentByType(RenderComponent); // Fast O(1) lookup
|
|
349
|
+
* ```
|
|
350
|
+
*/
|
|
351
|
+
getComponentByType(
|
|
352
|
+
// biome-ignore lint/suspicious/noExplicitAny: It's fine, we need to support any constructor
|
|
353
|
+
type) {
|
|
354
|
+
const direct = this._componentMap.get(type);
|
|
355
|
+
if (direct) {
|
|
356
|
+
return direct;
|
|
357
|
+
}
|
|
358
|
+
// No map entry, iterate to find first component
|
|
359
|
+
for (const c of this._components) {
|
|
360
|
+
if (c instanceof type) {
|
|
361
|
+
this._componentMap.set(type, c);
|
|
362
|
+
return c;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
return undefined;
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Gets all components that match the given filter function.
|
|
369
|
+
* @template T - The type of component to return. Defaults to `Component`.
|
|
370
|
+
* @param filter - A function that returns `true` for components to include.
|
|
371
|
+
* @returns An array of matching components.
|
|
372
|
+
*/
|
|
373
|
+
getComponents(filter) {
|
|
374
|
+
// Writing filter manually, as this is supposedly faster than using the built in filter method or generator
|
|
375
|
+
const result = [];
|
|
376
|
+
const components = this._components;
|
|
377
|
+
for (let i = 0, l = components.length; i < l; i++) {
|
|
378
|
+
const c = components[i];
|
|
379
|
+
if (filter(c)) {
|
|
380
|
+
result.push(c);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
return result;
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Gets the index of a component in the components array.
|
|
387
|
+
* @param component - The component to find the index of.
|
|
388
|
+
* @returns The index of the component, or `-1` if not found.
|
|
389
|
+
*/
|
|
390
|
+
indexOfComponent(component) {
|
|
391
|
+
return this._components.indexOf(component);
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Ticks this entity and all its descendants, calling `onTick` on all enabled components.
|
|
395
|
+
* This should ONLY be called from the root of an Entity tree. Will traverse the full depth of the tree.
|
|
396
|
+
* Disabled entity subtrees and disabled components are skipped during traversal.
|
|
397
|
+
* @param deltaTime - The time elapsed since the last tick in milliseconds.
|
|
398
|
+
*/
|
|
399
|
+
_tick(deltaTime) {
|
|
400
|
+
if (!this._enabledSelf)
|
|
401
|
+
return;
|
|
402
|
+
this._components.forEach((component) => {
|
|
403
|
+
if (!component.enabledSelf)
|
|
404
|
+
return;
|
|
405
|
+
// biome-ignore lint/suspicious/noExplicitAny: Override protected guard
|
|
406
|
+
component.onTick(deltaTime);
|
|
407
|
+
});
|
|
408
|
+
for (const child of this.traverseChildren((child) => child.enabledSelf)) {
|
|
409
|
+
child._components.forEach((component) => {
|
|
410
|
+
if (!component.enabledSelf)
|
|
411
|
+
return;
|
|
412
|
+
// biome-ignore lint/suspicious/noExplicitAny: Override protected guard
|
|
413
|
+
component.onTick(deltaTime);
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
//# sourceMappingURL=entity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entity.js","sourceRoot":"","sources":["../src/entity.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,UAAU,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,UAAU,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@funderforge/ecs",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A generic component framework implementing an Entity-Component System (ECS) pattern, optimized for performance and simplicity",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"README.md",
|
|
17
|
+
"LICENSE"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsc",
|
|
21
|
+
"dev": "tsc --watch",
|
|
22
|
+
"typecheck": "tsc --noEmit",
|
|
23
|
+
"test": "vitest run",
|
|
24
|
+
"test:watch": "vitest",
|
|
25
|
+
"lint": "biome check .",
|
|
26
|
+
"lint:fix": "pnpm exec biome check --write",
|
|
27
|
+
"prepublishOnly": "pnpm run build",
|
|
28
|
+
"publish": "pnpm publish"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"ecs",
|
|
32
|
+
"entity-component-system",
|
|
33
|
+
"component",
|
|
34
|
+
"entity",
|
|
35
|
+
"framework",
|
|
36
|
+
"game-engine",
|
|
37
|
+
"hierarchy",
|
|
38
|
+
"typescript"
|
|
39
|
+
],
|
|
40
|
+
"author": "funder75",
|
|
41
|
+
"license": "MIT",
|
|
42
|
+
"repository": {
|
|
43
|
+
"type": "git",
|
|
44
|
+
"url": "https://github.com/funder75/ecs"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@biomejs/biome": "2.3.8",
|
|
48
|
+
"@types/node": "^25.0.3",
|
|
49
|
+
"typescript": "~5.9.3",
|
|
50
|
+
"vitest": "4.0.16"
|
|
51
|
+
}
|
|
52
|
+
}
|