archetype-ecs 1.0.0 → 1.2.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/src/Container.js DELETED
@@ -1,23 +0,0 @@
1
- export function createContainer() {
2
- const factories = new Map();
3
- const instances = new Map();
4
-
5
- return {
6
- register(key, factory) {
7
- factories.set(key, factory);
8
- },
9
-
10
- resolve(key) {
11
- if (instances.has(key)) {
12
- return instances.get(key);
13
- }
14
- const factory = factories.get(key);
15
- if (!factory) {
16
- throw new Error(`No factory registered for key: ${key}`);
17
- }
18
- const instance = factory(this);
19
- instances.set(key, instance);
20
- return instance;
21
- }
22
- };
23
- }
package/src/EventBus.js DELETED
@@ -1,29 +0,0 @@
1
- export function createEventBus() {
2
- const listeners = new Map();
3
-
4
- return {
5
- on(event, callback) {
6
- if (!listeners.has(event)) {
7
- listeners.set(event, []);
8
- }
9
- listeners.get(event).push(callback);
10
- },
11
-
12
- off(event, callback) {
13
- const cbs = listeners.get(event);
14
- if (cbs) {
15
- const idx = cbs.indexOf(callback);
16
- if (idx !== -1) cbs.splice(idx, 1);
17
- }
18
- },
19
-
20
- emit(event, data) {
21
- const cbs = listeners.get(event);
22
- if (cbs) {
23
- for (const cb of cbs) {
24
- cb(data);
25
- }
26
- }
27
- }
28
- };
29
- }
package/src/GameLoop.js DELETED
@@ -1,110 +0,0 @@
1
- import { profiler } from './Profiler.js';
2
-
3
- export function createGameLoop(systems, renderSteps, { tickRate = 20, maxFrameTime = 250 } = {}) {
4
- let running = false;
5
- let lastTime = 0;
6
- let accumulator = 0;
7
- let tickCount = 0;
8
- let frameCount = 0;
9
- let fpsTime = 0;
10
- let fps = 0;
11
- let tps = 0;
12
- let fpsLimit = 0;
13
- let lastRenderTime = 0;
14
- let tickDuration = 1000 / tickRate;
15
- let rafId = 0;
16
-
17
- function loop(currentTime) {
18
- if (!running) return;
19
-
20
- const frameTime = Math.min(currentTime - lastTime, maxFrameTime);
21
- lastTime = currentTime;
22
- accumulator += frameTime;
23
-
24
- // Fixed timestep simulation
25
- while (accumulator >= tickDuration) {
26
- if (profiler.enabled) {
27
- const tickStart = performance.now();
28
- for (const system of systems) {
29
- if (system.update) {
30
- const t0 = performance.now();
31
- system.update(tickDuration);
32
- profiler.end(system.name || 'unnamed', t0);
33
- }
34
- }
35
- profiler.end('Tick Total', tickStart);
36
- } else {
37
- for (const system of systems) {
38
- if (system.update) system.update(tickDuration);
39
- }
40
- }
41
- accumulator -= tickDuration;
42
- tickCount++;
43
- }
44
-
45
- const alpha = accumulator / tickDuration;
46
-
47
- // Render (respecting fps cap)
48
- const minRenderInterval = fpsLimit > 0 ? 1000 / fpsLimit : 0;
49
- if (minRenderInterval === 0 || currentTime - lastRenderTime >= minRenderInterval) {
50
- if (profiler.enabled) {
51
- const renderStart = performance.now();
52
- for (const step of renderSteps) {
53
- const t0 = performance.now();
54
- step.fn(alpha, frameTime);
55
- profiler.end(step.name, t0);
56
- }
57
- profiler.end('Render Total', renderStart);
58
- } else {
59
- for (const step of renderSteps) {
60
- step.fn(alpha, frameTime);
61
- }
62
- }
63
- lastRenderTime = currentTime;
64
- frameCount++;
65
- }
66
-
67
- fpsTime += frameTime;
68
- if (fpsTime >= 1000) {
69
- fps = frameCount;
70
- tps = tickCount;
71
- frameCount = 0;
72
- tickCount = 0;
73
- fpsTime -= 1000;
74
- }
75
-
76
- rafId = requestAnimationFrame(loop);
77
- }
78
-
79
- return {
80
- start() {
81
- if (running) return;
82
- running = true;
83
- lastTime = performance.now();
84
- lastRenderTime = 0;
85
- rafId = requestAnimationFrame(loop);
86
- },
87
-
88
- stop() {
89
- running = false;
90
- cancelAnimationFrame(rafId);
91
- },
92
-
93
- setFpsLimit(limit) {
94
- fpsLimit = limit;
95
- },
96
-
97
- setTickRate(rate) {
98
- tickDuration = 1000 / rate;
99
- accumulator = 0;
100
- },
101
-
102
- setProfilingEnabled(enabled) {
103
- profiler.setEnabled(enabled);
104
- },
105
-
106
- getProfileData() { return profiler.getData(); },
107
- getFps() { return fps; },
108
- getTps() { return tps; }
109
- };
110
- }
@@ -1,38 +0,0 @@
1
- import { describe, test, expect } from '@jest/globals';
2
- import { createContainer } from '../src/Container.js';
3
-
4
- describe('Container', () => {
5
- test('register and resolve returns factory result', () => {
6
- const container = createContainer();
7
- container.register('greeting', () => 'hello');
8
- expect(container.resolve('greeting')).toBe('hello');
9
- });
10
-
11
- test('singleton caching — resolves same instance', () => {
12
- const container = createContainer();
13
- let callCount = 0;
14
- container.register('service', () => {
15
- callCount++;
16
- return { id: callCount };
17
- });
18
- const a = container.resolve('service');
19
- const b = container.resolve('service');
20
- expect(a).toBe(b);
21
- expect(callCount).toBe(1);
22
- });
23
-
24
- test('factory receives container for dependency injection', () => {
25
- const container = createContainer();
26
- container.register('config', () => ({ port: 3000 }));
27
- container.register('server', (c) => {
28
- const config = c.resolve('config');
29
- return { port: config.port };
30
- });
31
- expect(container.resolve('server')).toEqual({ port: 3000 });
32
- });
33
-
34
- test('throws for unregistered key', () => {
35
- const container = createContainer();
36
- expect(() => container.resolve('missing')).toThrow('No factory registered for key: missing');
37
- });
38
- });
@@ -1,41 +0,0 @@
1
- import { describe, test, expect } from '@jest/globals';
2
- import { createEventBus } from '../src/EventBus.js';
3
-
4
- describe('EventBus', () => {
5
- test('on/emit calls listener with data', () => {
6
- const bus = createEventBus();
7
- const received = [];
8
- bus.on('test', (data) => received.push(data));
9
- bus.emit('test', { value: 42 });
10
- expect(received).toEqual([{ value: 42 }]);
11
- });
12
-
13
- test('multiple listeners on same event', () => {
14
- const bus = createEventBus();
15
- const results = [];
16
- bus.on('test', () => results.push('a'));
17
- bus.on('test', () => results.push('b'));
18
- bus.emit('test');
19
- expect(results).toEqual(['a', 'b']);
20
- });
21
-
22
- test('off removes listener', () => {
23
- const bus = createEventBus();
24
- const results = [];
25
- const cb = () => results.push('called');
26
- bus.on('test', cb);
27
- bus.off('test', cb);
28
- bus.emit('test');
29
- expect(results).toEqual([]);
30
- });
31
-
32
- test('emit on non-existent event is a no-op', () => {
33
- const bus = createEventBus();
34
- expect(() => bus.emit('nonexistent', {})).not.toThrow();
35
- });
36
-
37
- test('off on non-existent event is a no-op', () => {
38
- const bus = createEventBus();
39
- expect(() => bus.off('nonexistent', () => {})).not.toThrow();
40
- });
41
- });