@byloth/core 2.0.0-rc.5 → 2.0.0-rc.7
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/dist/core.js +230 -242
- package/dist/core.js.map +1 -1
- package/dist/core.umd.cjs +2 -2
- package/dist/core.umd.cjs.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +1 -1
- package/src/models/aggregators/aggregated-async-iterator.ts +1 -6
- package/src/models/aggregators/aggregated-iterator.ts +1 -6
- package/src/models/publisher.ts +18 -11
- package/src/models/timers/clock.ts +19 -14
- package/src/models/timers/countdown.ts +21 -18
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@byloth/core",
|
|
3
|
-
"version": "2.0.0-rc.
|
|
3
|
+
"version": "2.0.0-rc.7",
|
|
4
4
|
"description": "An unopinionated collection of useful functions and classes that I use widely in all my projects. 🔧",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Core",
|
|
@@ -48,10 +48,10 @@
|
|
|
48
48
|
"types": "./src/index.ts",
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@byloth/eslint-config-typescript": "^3.0.1",
|
|
51
|
-
"@types/node": "^
|
|
51
|
+
"@types/node": "^22.9.0",
|
|
52
52
|
"husky": "^9.1.6",
|
|
53
53
|
"typescript": "^5.6.3",
|
|
54
|
-
"vite": "^5.4.
|
|
54
|
+
"vite": "^5.4.11"
|
|
55
55
|
},
|
|
56
56
|
"scripts": {
|
|
57
57
|
"dev": "vite",
|
package/src/index.ts
CHANGED
|
@@ -190,12 +190,7 @@ export default class AggregatedAsyncIterator<K extends PropertyKey, T>
|
|
|
190
190
|
for await (const [key, element] of elements)
|
|
191
191
|
{
|
|
192
192
|
const index = indexes.get(key) ?? 0;
|
|
193
|
-
if (index >= limit)
|
|
194
|
-
{
|
|
195
|
-
if (indexes.values().every((value) => value >= limit)) { break; }
|
|
196
|
-
|
|
197
|
-
continue;
|
|
198
|
-
}
|
|
193
|
+
if (index >= limit) { continue; }
|
|
199
194
|
|
|
200
195
|
yield [key, element];
|
|
201
196
|
|
|
@@ -178,12 +178,7 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
178
178
|
for (const [key, element] of elements)
|
|
179
179
|
{
|
|
180
180
|
const index = indexes.get(key) ?? 0;
|
|
181
|
-
if (index >= limit)
|
|
182
|
-
{
|
|
183
|
-
if (indexes.values().every((value) => value >= limit)) { break; }
|
|
184
|
-
|
|
185
|
-
continue;
|
|
186
|
-
}
|
|
181
|
+
if (index >= limit) { continue; }
|
|
187
182
|
|
|
188
183
|
yield [key, element];
|
|
189
184
|
|
package/src/models/publisher.ts
CHANGED
|
@@ -2,37 +2,44 @@ import { ReferenceException } from "./exceptions/index.js";
|
|
|
2
2
|
|
|
3
3
|
export type Subscriber<A extends unknown[] = [], R = void> = (...args: A) => R;
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
|
|
6
|
+
export default class Publisher<T extends { [K in keyof T]: [unknown[], unknown] } = Record<string, [[], void]>>
|
|
6
7
|
{
|
|
7
|
-
protected _subscribers: Subscriber<
|
|
8
|
+
protected _subscribers: Map<keyof T, Subscriber<unknown[], unknown>[]>;
|
|
8
9
|
|
|
9
10
|
public constructor()
|
|
10
11
|
{
|
|
11
|
-
this._subscribers =
|
|
12
|
+
this._subscribers = new Map();
|
|
12
13
|
}
|
|
13
14
|
|
|
14
|
-
public subscribe(subscriber: Subscriber<A, R>)
|
|
15
|
+
public subscribe<K extends keyof T, A extends T[K][0], R extends T[K][1]>(event: K, subscriber: Subscriber<A, R>)
|
|
16
|
+
: () => void
|
|
15
17
|
{
|
|
16
|
-
this._subscribers.
|
|
18
|
+
if (!(this._subscribers.has(event))) { this._subscribers.set(event, []); }
|
|
19
|
+
|
|
20
|
+
const subscribers = this._subscribers.get(event)!;
|
|
21
|
+
subscribers.push(subscriber as Subscriber<unknown[], unknown>);
|
|
17
22
|
|
|
18
23
|
return () =>
|
|
19
24
|
{
|
|
20
|
-
const index =
|
|
25
|
+
const index = subscribers.indexOf(subscriber as Subscriber<unknown[], unknown>);
|
|
21
26
|
if (index < 0)
|
|
22
27
|
{
|
|
23
28
|
throw new ReferenceException("Unable to unsubscribe the required subscriber. " +
|
|
24
29
|
"The subscription was already unsubscribed.");
|
|
25
30
|
}
|
|
26
31
|
|
|
27
|
-
|
|
32
|
+
subscribers.splice(index, 1);
|
|
28
33
|
};
|
|
29
34
|
}
|
|
30
35
|
|
|
31
|
-
public publish(...args: A): R[]
|
|
36
|
+
public publish<K extends keyof T, A extends T[K][0], R extends T[K][1]>(event: K, ...args: A): R[]
|
|
32
37
|
{
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
38
|
+
const subscribers = this._subscribers.get(event);
|
|
39
|
+
if (!(subscribers)) { return []; }
|
|
40
|
+
|
|
41
|
+
return subscribers.slice()
|
|
42
|
+
.map((subscriber) => subscriber(...args)) as R[];
|
|
36
43
|
}
|
|
37
44
|
|
|
38
45
|
public readonly [Symbol.toStringTag]: string = "Publisher";
|
|
@@ -1,22 +1,27 @@
|
|
|
1
1
|
import { TimeUnit } from "../../utils/date.js";
|
|
2
|
-
|
|
3
2
|
import { RangeException, RuntimeException } from "../exceptions/index.js";
|
|
3
|
+
|
|
4
4
|
import GameLoop from "../game-loop.js";
|
|
5
5
|
import Publisher from "../publisher.js";
|
|
6
6
|
|
|
7
|
+
interface ClockEvents
|
|
8
|
+
{
|
|
9
|
+
/* eslint-disable @typescript-eslint/no-invalid-void-type */
|
|
10
|
+
|
|
11
|
+
start: [[], void];
|
|
12
|
+
stop: [[], void];
|
|
13
|
+
tick: [[number], void];
|
|
14
|
+
}
|
|
15
|
+
|
|
7
16
|
export default class Clock extends GameLoop
|
|
8
17
|
{
|
|
9
|
-
protected
|
|
10
|
-
protected _stopper: Publisher;
|
|
11
|
-
protected _ticker: Publisher<[number]>;
|
|
18
|
+
protected _publisher: Publisher<ClockEvents>;
|
|
12
19
|
|
|
13
20
|
public constructor(msIfNotBrowser: number = TimeUnit.Second)
|
|
14
21
|
{
|
|
15
|
-
super((elapsedTime) => this.
|
|
22
|
+
super((elapsedTime) => this._publisher.publish("tick", elapsedTime), msIfNotBrowser);
|
|
16
23
|
|
|
17
|
-
this.
|
|
18
|
-
this._stopper = new Publisher();
|
|
19
|
-
this._ticker = new Publisher();
|
|
24
|
+
this._publisher = new Publisher();
|
|
20
25
|
}
|
|
21
26
|
|
|
22
27
|
public start(elapsedTime = 0): void
|
|
@@ -25,7 +30,7 @@ export default class Clock extends GameLoop
|
|
|
25
30
|
|
|
26
31
|
super.start(elapsedTime);
|
|
27
32
|
|
|
28
|
-
this.
|
|
33
|
+
this._publisher.publish("start");
|
|
29
34
|
}
|
|
30
35
|
|
|
31
36
|
public stop(): void
|
|
@@ -34,26 +39,26 @@ export default class Clock extends GameLoop
|
|
|
34
39
|
|
|
35
40
|
super.stop();
|
|
36
41
|
|
|
37
|
-
this.
|
|
42
|
+
this._publisher.publish("stop");
|
|
38
43
|
}
|
|
39
44
|
|
|
40
45
|
public onStart(callback: () => void): () => void
|
|
41
46
|
{
|
|
42
|
-
return this.
|
|
47
|
+
return this._publisher.subscribe("start", callback);
|
|
43
48
|
}
|
|
44
49
|
public onStop(callback: () => void): () => void
|
|
45
50
|
{
|
|
46
|
-
return this.
|
|
51
|
+
return this._publisher.subscribe("stop", callback);
|
|
47
52
|
}
|
|
48
53
|
|
|
49
54
|
public onTick(callback: (elapsedTime: number) => void, tickStep = 0): () => void
|
|
50
55
|
{
|
|
51
56
|
if (tickStep < 0) { throw new RangeException("The tick step must be a non-negative number."); }
|
|
52
|
-
if (tickStep === 0) { return this.
|
|
57
|
+
if (tickStep === 0) { return this._publisher.subscribe("tick", callback); }
|
|
53
58
|
|
|
54
59
|
let lastTick = 0;
|
|
55
60
|
|
|
56
|
-
return this.
|
|
61
|
+
return this._publisher.subscribe("tick", (elapsedTime: number) =>
|
|
57
62
|
{
|
|
58
63
|
if ((elapsedTime - lastTick) < tickStep) { return; }
|
|
59
64
|
|
|
@@ -6,14 +6,21 @@ import { DeferredPromise, SmartPromise } from "../promises/index.js";
|
|
|
6
6
|
import GameLoop from "../game-loop.js";
|
|
7
7
|
import Publisher from "../publisher.js";
|
|
8
8
|
|
|
9
|
+
interface CountdownEvents
|
|
10
|
+
{
|
|
11
|
+
/* eslint-disable @typescript-eslint/no-invalid-void-type */
|
|
12
|
+
|
|
13
|
+
start: [[], void];
|
|
14
|
+
stop: [[unknown], void];
|
|
15
|
+
tick: [[number], void];
|
|
16
|
+
expire: [[], void];
|
|
17
|
+
}
|
|
18
|
+
|
|
9
19
|
export default class Countdown extends GameLoop
|
|
10
20
|
{
|
|
11
21
|
protected _deferrer?: DeferredPromise<void>;
|
|
12
22
|
|
|
13
|
-
protected
|
|
14
|
-
protected _starter: Publisher;
|
|
15
|
-
protected _stopper: Publisher<[unknown]>;
|
|
16
|
-
protected _ticker: Publisher<[number]>;
|
|
23
|
+
protected _publisher: Publisher<CountdownEvents>;
|
|
17
24
|
|
|
18
25
|
protected _duration: number;
|
|
19
26
|
public get duration(): number
|
|
@@ -31,23 +38,19 @@ export default class Countdown extends GameLoop
|
|
|
31
38
|
const callback = () =>
|
|
32
39
|
{
|
|
33
40
|
const remainingTime = this.remainingTime;
|
|
34
|
-
this.
|
|
41
|
+
this._publisher.publish("tick", remainingTime);
|
|
35
42
|
|
|
36
43
|
if (remainingTime <= 0)
|
|
37
44
|
{
|
|
38
45
|
this._deferrerStop();
|
|
39
46
|
|
|
40
|
-
this.
|
|
47
|
+
this._publisher.publish("expire");
|
|
41
48
|
}
|
|
42
49
|
};
|
|
43
50
|
|
|
44
51
|
super(callback, msIfNotBrowser);
|
|
45
52
|
|
|
46
|
-
this.
|
|
47
|
-
this._starter = new Publisher();
|
|
48
|
-
this._stopper = new Publisher();
|
|
49
|
-
this._ticker = new Publisher();
|
|
50
|
-
|
|
53
|
+
this._publisher = new Publisher();
|
|
51
54
|
this._duration = duration;
|
|
52
55
|
}
|
|
53
56
|
|
|
@@ -72,7 +75,7 @@ export default class Countdown extends GameLoop
|
|
|
72
75
|
this._deferrer = new DeferredPromise();
|
|
73
76
|
super.start(this.duration - remainingTime);
|
|
74
77
|
|
|
75
|
-
this.
|
|
78
|
+
this._publisher.publish("start");
|
|
76
79
|
|
|
77
80
|
return this._deferrer;
|
|
78
81
|
}
|
|
@@ -80,31 +83,31 @@ export default class Countdown extends GameLoop
|
|
|
80
83
|
{
|
|
81
84
|
this._deferrerStop(reason);
|
|
82
85
|
|
|
83
|
-
this.
|
|
86
|
+
this._publisher.publish("stop", reason);
|
|
84
87
|
}
|
|
85
88
|
|
|
86
89
|
public onExpire(callback: () => void): () => void
|
|
87
90
|
{
|
|
88
|
-
return this.
|
|
91
|
+
return this._publisher.subscribe("expire", callback);
|
|
89
92
|
}
|
|
90
93
|
|
|
91
94
|
public onStart(callback: () => void): () => void
|
|
92
95
|
{
|
|
93
|
-
return this.
|
|
96
|
+
return this._publisher.subscribe("start", callback);
|
|
94
97
|
}
|
|
95
98
|
public onStop(callback: (reason?: unknown) => void): () => void
|
|
96
99
|
{
|
|
97
|
-
return this.
|
|
100
|
+
return this._publisher.subscribe("stop", callback);
|
|
98
101
|
}
|
|
99
102
|
|
|
100
103
|
public onTick(callback: (remainingTime: number) => void, tickStep = 0): () => void
|
|
101
104
|
{
|
|
102
105
|
if (tickStep < 0) { throw new RangeException("The tick step must be a non-negative number."); }
|
|
103
|
-
if (tickStep === 0) { return this.
|
|
106
|
+
if (tickStep === 0) { return this._publisher.subscribe("tick", callback); }
|
|
104
107
|
|
|
105
108
|
let lastTick = 0;
|
|
106
109
|
|
|
107
|
-
return this.
|
|
110
|
+
return this._publisher.subscribe("tick", (remainingTime: number) =>
|
|
108
111
|
{
|
|
109
112
|
if ((lastTick - remainingTime) < tickStep) { return; }
|
|
110
113
|
|