-
Notifications
You must be signed in to change notification settings - Fork 0
/
system.ts
64 lines (58 loc) · 2.25 KB
/
system.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
/* Copyright 2022 the Miski authors. All rights reserved. MIT license. */
import type { Query } from "./query/query.js";
import type { ComponentRecord } from "./component/manager.js";
import type { ParametersExceptFirstTwo } from "./utils/utils.js";
import type { Entity, World } from "./world.js";
/**
* A multi-arity function where the first two parameters
* are the components and entities available to
* the system respectively.
*/
export type SystemCallback<
T extends (components: ComponentRecord, entities: Entity[], ...args: unknown[]) => ReturnType<T>,
U extends ParametersExceptFirstTwo<T>,
> = (components: ComponentRecord, entities: Entity[], ...args: U) => ReturnType<T>;
export interface SystemSpec<
T extends (components: ComponentRecord, entities: Entity[], ...args: unknown[]) => ReturnType<T>,
U extends ParametersExceptFirstTwo<T>,
> {
/** The core function of the system. Called when this.exec is called. */
system: SystemCallback<T, U>;
/** The query which will provide the components and entities to the system. */
query: Query;
}
export class System<
T extends (components: ComponentRecord, entities: Entity[], ...args: unknown[]) => ReturnType<T>,
U extends ParametersExceptFirstTwo<T>,
> {
/** The core function of the system. Called when this.exec is called. */
system: SystemCallback<T, U>;
/** The query which will provide the components and entities to the system. */
query: Query;
/**
* Creates a new system.
*
* Systems are the behaviours which affect components.
*
* @param spec the system's specification object
*/
constructor(spec: SystemSpec<T, U>) {
const { system, query } = spec;
this.system = system;
this.query = query;
}
/**
* Initialize the system for a given world
* @param world the world to execute the system in
* @returns an initialized system function
*/
init(world: World): (...args: U) => ReturnType<T> {
const components = world.getQueryComponents(this.query);
const entities: Entity[] = [];
/**
* @param args arguments to pass to the system's callback function
* @returns the result of the system's callback function
*/
return (...args: U) => this.system(components, world.getQueryEntities(this.query, entities), ...args);
}
}