@rbxts/planck 0.3.0-alpha.2 → 0.3.0-rc.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rbxts/planck",
3
- "version": "0.3.0-alpha.2",
3
+ "version": "0.3.0-rc.1",
4
4
  "description": "An Agnostic Scheduler for ECS",
5
5
  "main": "src",
6
6
  "repository": {
@@ -1,19 +1,7 @@
1
1
  local AdjacencyMatrix = {}
2
2
  AdjacencyMatrix.__index = AdjacencyMatrix
3
3
 
4
- export type AdjacencyMatrix = {
5
- matrix: { { number } },
6
- length: number,
7
- width: number,
8
-
9
- extend: (self: AdjacencyMatrix) -> (),
10
- setEdge: (self: AdjacencyMatrix, i: number, j: number, v: number) -> (),
11
- toAdjacencyList: (self: AdjacencyMatrix) -> { { number } },
12
- topologicalSort: (self: AdjacencyMatrix) -> { number }?,
13
- new: () -> AdjacencyMatrix,
14
- }
15
-
16
- function AdjacencyMatrix:__tostring()
4
+ function AdjacencyMatrix.__tostring(self: AdjacencyMatrix)
17
5
  local s = "\n"
18
6
 
19
7
  for i = 1, self.length do
@@ -38,9 +26,9 @@ function AdjacencyMatrix:__tostring()
38
26
  return s
39
27
  end
40
28
 
41
- function AdjacencyMatrix:extend()
42
- self.length = (self.length :: number) + 1
43
- self.width = (self.length :: number) + 1
29
+ function AdjacencyMatrix.extend(self: AdjacencyMatrix)
30
+ self.length = self.length + 1
31
+ self.width = self.length + 1
44
32
 
45
33
  self.matrix[self.length] = {}
46
34
  for j = 1, self.width do
@@ -52,11 +40,16 @@ function AdjacencyMatrix:extend()
52
40
  end
53
41
  end
54
42
 
55
- function AdjacencyMatrix:setEdge(i, j, val)
43
+ function AdjacencyMatrix.setEdge(
44
+ self: AdjacencyMatrix,
45
+ i: number,
46
+ j: number,
47
+ val: number
48
+ )
56
49
  self.matrix[i][j] = val
57
50
  end
58
51
 
59
- function AdjacencyMatrix:toAdjacencyList()
52
+ function AdjacencyMatrix.toAdjacencyList(self: AdjacencyMatrix): { { number } }
60
53
  local list = {}
61
54
 
62
55
  for i = 1, self.length do
@@ -71,7 +64,7 @@ function AdjacencyMatrix:toAdjacencyList()
71
64
  return list
72
65
  end
73
66
 
74
- function AdjacencyMatrix:topologicalSort(): { number }?
67
+ function AdjacencyMatrix.topologicalSort(self: AdjacencyMatrix): { number }?
75
68
  local adjacencyList = self:toAdjacencyList()
76
69
 
77
70
  local result = {}
@@ -114,34 +107,19 @@ function AdjacencyMatrix.new(): AdjacencyMatrix
114
107
  matrix = {},
115
108
  length = 0,
116
109
  width = 0,
117
- }, AdjacencyMatrix) :: any
110
+ }, AdjacencyMatrix)
118
111
  end
119
112
 
120
- export type DependencyGraph<T> = {
121
- nodes: { T },
122
- matrix: AdjacencyMatrix,
113
+ export type AdjacencyMatrix = setmetatable<{
114
+ matrix: { { number } },
123
115
  length: number,
124
116
  width: number,
125
-
126
- getOrderedList: (self: DependencyGraph<T>) -> { T }?,
127
- insert: (self: DependencyGraph<T>, node: T) -> DependencyGraph<T>,
128
- insertAfter: (
129
- self: DependencyGraph<T>,
130
- node: T,
131
- afterNode: T
132
- ) -> DependencyGraph<T>,
133
- insertBefore: (
134
- self: DependencyGraph<T>,
135
- node: T,
136
- beforeNode: T
137
- ) -> DependencyGraph<T>,
138
- new: () -> DependencyGraph<T>,
139
- }
117
+ }, typeof(AdjacencyMatrix)>
140
118
 
141
119
  local DependencyGraph = {}
142
120
  DependencyGraph.__index = DependencyGraph
143
121
 
144
- function DependencyGraph:getOrderedList(): { any }?
122
+ function DependencyGraph.getOrderedList<T>(self: DependencyGraph<T>): { T }?
145
123
  local orderedList = {}
146
124
 
147
125
  local topologicalSort = self.matrix:topologicalSort()
@@ -156,10 +134,13 @@ function DependencyGraph:getOrderedList(): { any }?
156
134
  return orderedList
157
135
  end
158
136
 
159
- function DependencyGraph:insertBefore(node, beforeNode)
160
- if not table.find(self.nodes, beforeNode) then
161
- error("Node not found in DependencyGraph:insertBefore(_, unknown)")
162
- end
137
+ function DependencyGraph.insertBefore<T>(
138
+ self: DependencyGraph<T>,
139
+ node: T,
140
+ beforeNode: T
141
+ )
142
+ local i = table.find(self.nodes, beforeNode)
143
+ assert(i, "Node not found in DependencyGraph:insertBefore(_, unknown)")
163
144
 
164
145
  local j = table.find(self.nodes, node)
165
146
  if not j then
@@ -167,7 +148,8 @@ function DependencyGraph:insertBefore(node, beforeNode)
167
148
  j = #self.nodes
168
149
  end
169
150
 
170
- local i = table.find(self.nodes, beforeNode)
151
+ -- selene: allow(incorrect_standard_library_use)
152
+ assert(j)
171
153
 
172
154
  self.matrix:extend()
173
155
  self.matrix:setEdge(j, i, 1)
@@ -175,10 +157,13 @@ function DependencyGraph:insertBefore(node, beforeNode)
175
157
  return self
176
158
  end
177
159
 
178
- function DependencyGraph:insertAfter(node, afterNode)
179
- if not table.find(self.nodes, afterNode) then
180
- error("Node not found in DependencyGraph:insertAfter(_, unknown)")
181
- end
160
+ function DependencyGraph.insertAfter<T>(
161
+ self: DependencyGraph<T>,
162
+ node: T,
163
+ afterNode: T
164
+ )
165
+ local i = table.find(self.nodes, afterNode)
166
+ assert(i, "Node not found in DependencyGraph:insertAfter(_, unknown)")
182
167
 
183
168
  local j = table.find(self.nodes, node)
184
169
  if not j then
@@ -186,7 +171,8 @@ function DependencyGraph:insertAfter(node, afterNode)
186
171
  j = #self.nodes
187
172
  end
188
173
 
189
- local i = table.find(self.nodes, afterNode)
174
+ -- selene: allow(incorrect_standard_library_use)
175
+ assert(j)
190
176
 
191
177
  self.matrix:extend()
192
178
  self.matrix:setEdge(i, j, 1)
@@ -194,7 +180,7 @@ function DependencyGraph:insertAfter(node, afterNode)
194
180
  return self
195
181
  end
196
182
 
197
- function DependencyGraph:insert(node)
183
+ function DependencyGraph.insert<T>(self: DependencyGraph<T>, node: T)
198
184
  local i = #self.nodes
199
185
  table.insert(self.nodes, node)
200
186
  local j = #self.nodes
@@ -208,13 +194,20 @@ function DependencyGraph:insert(node)
208
194
  return self
209
195
  end
210
196
 
211
- function DependencyGraph.new<T>(): DependencyGraph<T>
197
+ function DependencyGraph.new(): DependencyGraph<any>
212
198
  return setmetatable({
213
199
  nodes = {},
214
200
  matrix = AdjacencyMatrix.new(),
215
201
  length = 0,
216
202
  width = 0,
217
- }, DependencyGraph) :: any
203
+ }, DependencyGraph)
218
204
  end
219
205
 
206
+ export type DependencyGraph<T> = setmetatable<{
207
+ nodes: { T },
208
+ matrix: AdjacencyMatrix,
209
+ length: number,
210
+ width: number,
211
+ }, typeof(DependencyGraph)>
212
+
220
213
  return DependencyGraph
package/src/Phase.luau CHANGED
@@ -1,41 +1,46 @@
1
- --- @class Phase
2
- ---
3
- --- Phases represent tags that tell the scheduler when to
4
- --- schedule a set of systems.
5
- local Phase = {}
6
- Phase.__index = Phase
7
-
8
- function Phase:__tostring()
9
- return self._name
10
- end
11
-
12
- --- @within Phase
13
- ---
14
- --- Creates a new Phase, with an optional name to use for debugging.
15
- --- When no name is provided, the script and line number will be used.
16
- function Phase.new(name: string?)
17
- name = name or debug.info(2, "sl")
18
- return setmetatable({
19
- _name = name,
20
- _type = "phase",
21
- }, Phase)
22
- end
23
-
24
- --- @prop PreStartup Phase
25
- --- @within Phase
26
- --- Runs before the `Startup` Phase.
27
-
28
- --- @prop Startup Phase
29
- --- @within Phase
30
- --- This Phase will run once, the first time the Scheduler is ran,
31
- --- before any other Phases are ran.
32
-
33
- --- @prop PostStartup Phase
34
- --- @within Phase
35
- --- Runs after the `Startup` phase.
36
-
37
- Phase.PreStartup = Phase.new("PreStartup")
38
- Phase.Startup = Phase.new("Startup")
39
- Phase.PostStartup = Phase.new("PostStartup")
40
-
41
- return Phase
1
+ --- @class Phase
2
+ ---
3
+ --- Phases represent tags that tell the scheduler when to
4
+ --- schedule a set of systems.
5
+ local Phase = {}
6
+ Phase.__index = Phase
7
+
8
+ function Phase.__tostring(self: Phase)
9
+ return self._name
10
+ end
11
+
12
+ --- @within Phase
13
+ ---
14
+ --- Creates a new Phase, with an optional name to use for debugging.
15
+ --- When no name is provided, the script and line number will be used.
16
+ function Phase.new(name: string?): Phase
17
+ name = name or debug.info(2, "sl") :: string
18
+ return setmetatable({
19
+ _name = name,
20
+ _type = "phase",
21
+ }, Phase)
22
+ end
23
+
24
+ --- @prop PreStartup Phase
25
+ --- @within Phase
26
+ --- Runs before the `Startup` Phase.
27
+
28
+ --- @prop Startup Phase
29
+ --- @within Phase
30
+ --- This Phase will run once, the first time the Scheduler is ran,
31
+ --- before any other Phases are ran.
32
+
33
+ --- @prop PostStartup Phase
34
+ --- @within Phase
35
+ --- Runs after the `Startup` phase.
36
+
37
+ Phase.PreStartup = Phase.new("PreStartup")
38
+ Phase.Startup = Phase.new("Startup")
39
+ Phase.PostStartup = Phase.new("PostStartup")
40
+
41
+ export type Phase = setmetatable<{
42
+ _name: string,
43
+ _type: "phase",
44
+ }, typeof(Phase)>
45
+
46
+ return Phase
package/src/Pipeline.luau CHANGED
@@ -1,86 +1,105 @@
1
- --!nonstrict
2
- local DependencyGraph = require(script.Parent.DependencyGraph)
3
- local Phase = require(script.Parent.Phase)
4
-
5
- --- @class Pipeline
6
- ---
7
- --- Pipelines represent a set of ordered Phases. Systems cannot be
8
- --- assigned to Pipelines themselves, but rather to Phases within
9
- --- those Pipelines.
10
- local Pipeline = {}
11
- Pipeline.__index = Pipeline
12
-
13
- function Pipeline:__tostring()
14
- return self._name
15
- end
16
-
17
- --- @method insert
18
- --- @within Pipeline
19
- --- @param phase Phase
20
- --- @return Pipeline
21
- ---
22
- --- Adds a Phase to the Pipeline, ordering it implicitly.
23
- function Pipeline:insert(phase)
24
- self.dependencyGraph:insert(phase)
25
- return self
26
- end
27
-
28
- --- @method insertAfter
29
- --- @within Pipeline
30
- --- @param phase Phase
31
- --- @param after Phase
32
- --- @return Pipeline
33
- ---
34
- --- Adds a Phase to the Pipeline after another Phase, ordering it explicitly.
35
- function Pipeline:insertAfter(phase, afterPhase)
36
- local i = table.find(self.dependencyGraph.nodes, afterPhase)
37
- assert(
38
- i,
39
- "Unknown Phase in Pipeline:insertAfter(_, unknown), try adding this Phase to the Pipeline."
40
- )
41
-
42
- self.dependencyGraph:insertAfter(phase, afterPhase)
43
- return self
44
- end
45
-
46
- --- @method insertBefore
47
- --- @within Pipeline
48
- --- @param phase Phase
49
- --- @param before Phase
50
- --- @return Pipeline
51
- ---
52
- --- Adds a Phase to the Pipeline before another Phase, ordering it explicitly.
53
- function Pipeline:insertBefore(phase, beforePhase)
54
- local i = table.find(self.dependencyGraph.nodes, beforePhase)
55
- assert(
56
- i,
57
- "Unknown Phase in Pipeline:insertBefore(_, unknown), try adding this Phase to the Pipeline."
58
- )
59
-
60
- self.dependencyGraph:insertBefore(phase, beforePhase)
61
- return self
62
- end
63
-
64
- --- @within Pipeline
65
- ---
66
- --- Creates a new Pipeline, with an optional name to use for debugging.
67
- --- When no name is provided, the script and line number will be used.
68
- function Pipeline.new(name: string?)
69
- name = name or debug.info(2, "sl")
70
- return setmetatable({
71
- _name = name,
72
- _type = "pipeline",
73
- dependencyGraph = DependencyGraph.new(),
74
- }, Pipeline)
75
- end
76
-
77
- --- @prop Startup Pipeline
78
- --- @within Pipeline
79
- ---
80
- --- A Pipeline containing the `PreStartup`, `Startup`, and `PostStartup` phases.
81
- Pipeline.Startup = Pipeline.new()
82
- :insert(Phase.PreStartup)
83
- :insert(Phase.Startup)
84
- :insert(Phase.PostStartup)
85
-
86
- return Pipeline
1
+ local DependencyGraph = require(script.Parent.DependencyGraph)
2
+ local Phase = require(script.Parent.Phase)
3
+
4
+ type DependencyGraph<T> = DependencyGraph.DependencyGraph<T>
5
+ type Phase = Phase.Phase
6
+
7
+ --- @class Pipeline
8
+ ---
9
+ --- Pipelines represent a set of ordered Phases. Systems cannot be
10
+ --- assigned to Pipelines themselves, but rather to Phases within
11
+ --- those Pipelines.
12
+ local Pipeline = {}
13
+ Pipeline.__index = Pipeline
14
+
15
+ function Pipeline.__tostring(self: Pipeline): string
16
+ return self._name
17
+ end
18
+
19
+ --- @method insert
20
+ --- @within Pipeline
21
+ --- @param phase Phase
22
+ --- @return Pipeline
23
+ ---
24
+ --- Adds a Phase to the Pipeline, ordering it implicitly.
25
+ function Pipeline.insert(self: Pipeline, phase: Phase): Pipeline
26
+ self.dependencyGraph:insert(phase)
27
+ return self
28
+ end
29
+
30
+ --- @method insertAfter
31
+ --- @within Pipeline
32
+ --- @param phase Phase
33
+ --- @param after Phase
34
+ --- @return Pipeline
35
+ ---
36
+ --- Adds a Phase to the Pipeline after another Phase, ordering it explicitly.
37
+ function Pipeline.insertAfter(
38
+ self: Pipeline,
39
+ phase: Phase,
40
+ afterPhase: Phase
41
+ ): Pipeline
42
+ local i = table.find(self.dependencyGraph.nodes, afterPhase)
43
+ assert(
44
+ i,
45
+ "Unknown Phase in Pipeline:insertAfter(_, unknown), try adding this Phase to the Pipeline."
46
+ )
47
+
48
+ self.dependencyGraph:insertAfter(phase, afterPhase)
49
+ return self
50
+ end
51
+
52
+ --- @method insertBefore
53
+ --- @within Pipeline
54
+ --- @param phase Phase
55
+ --- @param before Phase
56
+ --- @return Pipeline
57
+ ---
58
+ --- Adds a Phase to the Pipeline before another Phase, ordering it explicitly.
59
+ function Pipeline.insertBefore(
60
+ self: Pipeline,
61
+ phase: Phase,
62
+ beforePhase: Phase
63
+ ): Pipeline
64
+ local i = table.find(self.dependencyGraph.nodes, beforePhase)
65
+ assert(
66
+ i,
67
+ "Unknown Phase in Pipeline:insertBefore(_, unknown), try adding this Phase to the Pipeline."
68
+ )
69
+
70
+ self.dependencyGraph:insertBefore(phase, beforePhase)
71
+ return self
72
+ end
73
+
74
+ --- @within Pipeline
75
+ ---
76
+ --- Creates a new Pipeline, with an optional name to use for debugging.
77
+ --- When no name is provided, the script and line number will be used.
78
+ function Pipeline.new(name: string?): Pipeline
79
+ name = name or debug.info(2, "sl") :: string
80
+
81
+ local dependencyGraph: DependencyGraph<Phase> = DependencyGraph.new()
82
+
83
+ return setmetatable({
84
+ _name = name,
85
+ _type = "pipeline",
86
+ dependencyGraph = dependencyGraph,
87
+ }, Pipeline)
88
+ end
89
+
90
+ --- @prop Startup Pipeline
91
+ --- @within Pipeline
92
+ ---
93
+ --- A Pipeline containing the `PreStartup`, `Startup`, and `PostStartup` phases.
94
+ Pipeline.Startup = Pipeline.new()
95
+ :insert(Phase.PreStartup)
96
+ :insert(Phase.Startup)
97
+ :insert(Phase.PostStartup)
98
+
99
+ export type Pipeline = setmetatable<{
100
+ _name: string,
101
+ _type: "pipeline",
102
+ dependencyGraph: DependencyGraph<Phase>,
103
+ }, typeof(Pipeline)>
104
+
105
+ return Pipeline
@@ -152,7 +152,79 @@ export interface SystemTable<T extends unknown[]> extends BaseSystemTable<T> {
152
152
  * };
153
153
  * ```
154
154
  */
155
- export type System<T extends unknown[]> = InitializerSystemFn<T> | SystemFn<T> | SystemTable<T>;
155
+ export type System<T extends unknown[]> =
156
+ | InitializerSystemFn<T>
157
+ | SystemFn<T>
158
+ | SystemTable<T>;
159
+
160
+ type InternalSystem<T extends unknown[]> = SystemFn<T> | InitializerSystemFn<T>;
161
+
162
+ type SystemInfo<T extends unknown[]> = {
163
+ system: InternalSystem<T>;
164
+ run: InternalSystem<T>;
165
+ cleanup?: SystemFn<T>;
166
+ initialized: boolean;
167
+ name: string;
168
+ deltaTime?: number;
169
+ lastTime?: number;
170
+ timeLastLogged?: number;
171
+ recentLogs?: { [key: string]: boolean };
172
+ logs: any[];
173
+ phase: Phase;
174
+ };
175
+
176
+ type Hook<T, V = void> = {
177
+ readonly __context: T;
178
+ readonly __return: V;
179
+ };
180
+
181
+ type PartialHookContext<T extends unknown[]> = {
182
+ scheduler: Scheduler<T>;
183
+ };
184
+
185
+ type SystemHookContext<T extends unknown[]> = PartialHookContext<T> & {
186
+ system: SystemInfo<T>;
187
+ };
188
+
189
+ type SystemReplaceContext<T extends unknown[]> = PartialHookContext<T> & {
190
+ new: SystemInfo<T>;
191
+ old: SystemInfo<T>;
192
+ };
193
+
194
+ type SystemErrorContext<T extends unknown[]> = PartialHookContext<T> & {
195
+ system: SystemInfo<T>;
196
+ error?: unknown;
197
+ };
198
+
199
+ type SystemCallHookFn = () => void;
200
+ type SystemCallCallback<T extends unknown[]> = (
201
+ context: SystemCallContext<T>
202
+ ) => SystemCallHookFn;
203
+
204
+ type SystemCallContext<T extends unknown[]> = PartialHookContext<T> & {
205
+ system: SystemInfo<T>;
206
+ nextFn: SystemCallHookFn;
207
+ };
208
+
209
+ type PhaseContext<T extends unknown[]> = PartialHookContext<T> & {
210
+ phase: Phase;
211
+ };
212
+
213
+ interface Hooks<T extends unknown[]> {
214
+ SystemAdd: Hook<SystemHookContext<T>>;
215
+ SystemRemove: Hook<SystemHookContext<T>>;
216
+ SystemReplace: Hook<SystemReplaceContext<T>>;
217
+ SystemCleanup: Hook<SystemErrorContext<T>>;
218
+ SystemError: Hook<SystemErrorContext<T>>;
219
+ SystemTriedRun: Hook<SystemHookContext<T>>;
220
+
221
+ OuterSystemCall: Hook<SystemCallContext<T>, SystemCallHookFn>;
222
+ InnerSystemCall: Hook<SystemCallContext<T>, SystemCallHookFn>;
223
+ SystemCall: Hook<SystemCallContext<T>, SystemCallHookFn>;
224
+
225
+ PhaseAdd: Hook<PhaseContext<T>>;
226
+ PhaseBegan: Hook<PhaseContext<T>>;
227
+ }
156
228
 
157
229
  /**
158
230
  * An Object which handles scheduling Systems to run within different Phases.
@@ -172,6 +244,19 @@ export class Scheduler<T extends unknown[]> {
172
244
  */
173
245
  addPlugin(plugin: Plugin<T>): this;
174
246
 
247
+ /**
248
+ * See [creating plugins](https://yetanotherclown.github.io/planck/docs/plugins/creating).
249
+ */
250
+ Hooks: Hooks<T>;
251
+
252
+ /**
253
+ * Allows for registering hooks, see [creating plugins](https://yetanotherclown.github.io/planck/docs/plugins/creating).
254
+ */
255
+ addHook<Context, Return>(
256
+ hook: Hook<Context, Return>,
257
+ fn: (context: Context) => Return
258
+ ): void;
259
+
175
260
  /**
176
261
  * Adds the System to the Scheduler, scheduling it to be ran implicitly within
177
262
  * the provided Phase or on the default Main phase.
@@ -244,7 +329,11 @@ export class Scheduler<T extends unknown[]> {
244
329
  * );
245
330
  * ```
246
331
  */
247
- insert<E extends EventInstance>(phase: Phase, instance: E, event: ExtractEvents<E>): this;
332
+ insert<E extends EventInstance>(
333
+ phase: Phase,
334
+ instance: E,
335
+ event: ExtractEvents<E>
336
+ ): this;
248
337
  /**
249
338
  * Initializes the Phase within the Scheduler, ordering it implicitly by
250
339
  * setting it as a dependent of the previous Phase/Pipeline, and scheduling it
@@ -272,7 +361,11 @@ export class Scheduler<T extends unknown[]> {
272
361
  * );
273
362
  * ```
274
363
  */
275
- insert<E extends EventInstance>(pipeline: Pipeline, instance: E, event: ExtractEvents<E>): this;
364
+ insert<E extends EventInstance>(
365
+ pipeline: Pipeline,
366
+ instance: E,
367
+ event: ExtractEvents<E>
368
+ ): this;
276
369
  /**
277
370
  * Initializes the Pipeline and it's Phases within the Scheduler, ordering the
278
371
  * Pipeline implicitly by setting it as a dependent of the previous