@rbxts/planck 0.1.0-rc.2

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/out/hooks.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import { Hooks } from "./types";
2
+
3
+ declare const hooks : Hooks;
4
+ export = hooks;
package/out/hooks.luau ADDED
@@ -0,0 +1,145 @@
1
+ -- Super-duper experimental Plugin Hooks API
2
+
3
+ local function systemAdd(scheduler, systemInfo)
4
+ local hooks = scheduler._hooks[scheduler.Hooks.SystemAdd]
5
+ local info = {
6
+ scheduler = scheduler,
7
+ system = systemInfo,
8
+ }
9
+
10
+ for _, hook in hooks do
11
+ local success, err = pcall(hook, info)
12
+ if not success then
13
+ warn("Unexpected error in hook:", err)
14
+ end
15
+ end
16
+ end
17
+
18
+ local function systemRemove(scheduler, systemInfo)
19
+ local hooks = scheduler._hooks[scheduler.Hooks.SystemRemove]
20
+ local info = {
21
+ scheduler = scheduler,
22
+ system = systemInfo,
23
+ }
24
+
25
+ for _, hook in hooks do
26
+ local success, err = pcall(hook, info)
27
+ if not success then
28
+ warn("Unexpected error in hook:", err)
29
+ end
30
+ end
31
+ end
32
+
33
+ local function systemReplace(scheduler, oldSystemInfo, newSystemInfo)
34
+ local hooks = scheduler._hooks[scheduler.Hooks.SystemReplace]
35
+ local info = {
36
+ scheduler = scheduler,
37
+ new = newSystemInfo,
38
+ old = oldSystemInfo,
39
+ }
40
+
41
+ for _, hook in hooks do
42
+ local success, err = pcall(hook, info)
43
+ if not success then
44
+ warn("Unexpected error in hook:", err)
45
+ end
46
+ end
47
+ end
48
+
49
+ local function systemCall(scheduler, hookName, systemInfo, nextFn)
50
+ local hooks = scheduler._hooks[scheduler.Hooks[hookName] ]
51
+
52
+ if hooks then
53
+ for _, hook in hooks do
54
+ nextFn = hook({
55
+ scheduler = nil,
56
+ system = systemInfo,
57
+ nextFn = nextFn,
58
+ })
59
+
60
+ if not nextFn then
61
+ local source, line = debug.info(hook, "sl")
62
+ warn(
63
+ `{source}:{line}: Expected 'SystemCall' hook to return a function`
64
+ )
65
+ end
66
+ end
67
+ end
68
+
69
+ nextFn()
70
+ end
71
+
72
+ local function systemError(scheduler, systemInfo, err)
73
+ local hooks = scheduler._hooks[scheduler.Hooks["SystemError"] ]
74
+
75
+ if hooks then
76
+ for _, hook in hooks do
77
+ hook({
78
+ scheduler = scheduler,
79
+ system = systemInfo,
80
+ error = err,
81
+ })
82
+ end
83
+ end
84
+ end
85
+
86
+ type PhaseAdd = {
87
+ scheduler: any,
88
+ phase: any
89
+ }
90
+
91
+ local function phaseAdd(scheduler, phase)
92
+ local hooks = scheduler._hooks[scheduler.Hooks.PhaseAdd]
93
+ local info = {
94
+ scheduler = scheduler,
95
+ phase = phase,
96
+ }
97
+
98
+ for _, hook in hooks do
99
+ local success, err = pcall(hook, info)
100
+ if not success then
101
+ warn("Unexpected error in hook:", err)
102
+ end
103
+ end
104
+ end
105
+
106
+ local function phaseBegan(scheduler, phase)
107
+ local hooks = scheduler._hooks[scheduler.Hooks.PhaseBegan]
108
+ local info = {
109
+ scheduler = scheduler,
110
+ phase = phase,
111
+ }
112
+
113
+ for _, hook in hooks do
114
+ local success, err = pcall(hook, info)
115
+ if not success then
116
+ warn("Unexpected error in hook:", err)
117
+ end
118
+ end
119
+ end
120
+
121
+ local Hooks = {
122
+ SystemAdd = "SystemAdd",
123
+ SystemRemove = "SystemRemove",
124
+ SystemReplace = "SystemReplace",
125
+ SystemError = "SystemError",
126
+
127
+ OuterSystemCall = "OuterSystemCall",
128
+ InnerSystemCall = "InnerSystemCall",
129
+ SystemCall = "SystemCall",
130
+
131
+ PhaseAdd = "PhaseAdd",
132
+ PhaseBegan = "PhaseBegan",
133
+ }
134
+
135
+ return {
136
+ Hooks = Hooks,
137
+
138
+ systemAdd = systemAdd,
139
+ systemRemove = systemRemove,
140
+ systemReplace = systemReplace,
141
+ systemCall = systemCall,
142
+ systemError = systemError,
143
+ phaseAdd = phaseAdd,
144
+ phaseBegan = phaseBegan,
145
+ }
package/out/index.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ import phase from "./Phase";
2
+ import pipeline from "./Pipeline";
3
+ import schedular from "./Scheduler";
4
+
5
+ interface Planck {
6
+ Phase: typeof phase;
7
+ Pipeline: typeof pipeline;
8
+ Scheduler: typeof schedular;
9
+ }
10
+
11
+ declare const planck: Planck;
12
+ export = planck;
package/out/init.luau ADDED
@@ -0,0 +1,149 @@
1
+ local Phase = require(script:WaitForChild('Phase')):: any
2
+ local Pipeline = require(script:WaitForChild('Pipeline')):: any
3
+ local Scheduler = require(script:WaitForChild('Scheduler')):: any
4
+
5
+ type SystemFn<U...> = ((U...) -> any) | ((U...) -> ())
6
+
7
+ type SystemTable<U...> = {
8
+ system: SystemFn<U...>,
9
+ phase: Phase?,
10
+ [any]: any
11
+ }
12
+
13
+ type System<U...> = SystemFn<U...> | SystemTable<U...>
14
+
15
+ type EventLike = RBXScriptSignal | {
16
+ connect: (self: EventLike,...any) -> any,
17
+ [any]: any
18
+ } | {
19
+ Connect: (self: EventLike,...any) -> any,
20
+ [any]: any
21
+ } | {
22
+ on: (self: EventLike,...any) -> any,
23
+ [any]: any
24
+ }
25
+
26
+ type EventInstance = Instance | {
27
+ [any]: EventLike
28
+ }
29
+
30
+ type Phase = {
31
+ PreStartup: Phase,
32
+ Startup: Phase,
33
+ PostStartup: Phase,
34
+
35
+ PreRender: Phase,
36
+ PreAnimation: Phase,
37
+ PreSimulation: Phase,
38
+ PostSimulation: Phase,
39
+
40
+ First: Phase,
41
+ PreUpdate: Phase,
42
+ Update: Phase,
43
+ PostUpdate: Phase,
44
+ Last: Phase,
45
+
46
+ new: (debugName: string?) -> Phase
47
+ }
48
+
49
+ type Pipeline = {
50
+ Main: Pipeline,
51
+ Startup: Pipeline,
52
+
53
+ insert: (self: Pipeline, phase: Phase) -> Pipeline,
54
+ insertAfter: (self: Pipeline, phase: Phase, after: Phase) -> Pipeline,
55
+ new: (debugName: string?) -> Pipeline
56
+ }
57
+
58
+ type Plugin<U...> = {
59
+ build: (self: Plugin<U...>, scheduler: Scheduler<U...>) -> (),
60
+ [any]: any
61
+ }
62
+
63
+ type Scheduler<U...> = {
64
+ addPlugin: (self: Scheduler<U...>, plugin: Plugin<U...>) -> Scheduler<U...>,
65
+
66
+ addSystem: (
67
+ self: Scheduler<U...>,
68
+ system: System<U...>,
69
+ phase: Phase?
70
+ ) -> Scheduler<U...>,
71
+
72
+ addSystems: (
73
+ self: Scheduler<U...>,
74
+ systems: { System<U...> },
75
+ phase: Phase?
76
+ ) -> Scheduler<U...>,
77
+
78
+ editSystem: (
79
+ self: Scheduler<U...>,
80
+ system: System<U...>,
81
+ new: Phase
82
+ ) -> Scheduler<U...>,
83
+
84
+ replaceSystem: (
85
+ self: Scheduler<U...>,
86
+ system: System<U...>,
87
+ new: System<U...>
88
+ ) -> Scheduler<U...>,
89
+
90
+ removeSystem: (
91
+ self: Scheduler<U...>,
92
+ system: System<U...>
93
+ ) -> Scheduler<U...>,
94
+
95
+ setRunCondition: ((
96
+ self: Scheduler<U...>,
97
+ system: System<U...>,
98
+ fn: (U...) -> boolean
99
+ ) -> Scheduler<U...>) & ((
100
+ self: Scheduler<U...>,
101
+ phase: Phase,
102
+ fn: (U...) -> boolean
103
+ ) -> Scheduler<U...>) & ((
104
+ self: Scheduler<U...>,
105
+ pipeline: Pipeline,
106
+ fn: (U...) -> boolean
107
+ ) -> Scheduler<U...>),
108
+
109
+ run: ((self: Scheduler<U...>, system: System<U...>) -> Scheduler<U...>)
110
+ & ((self: Scheduler<U...>, phase: Phase) -> Scheduler<U...>)
111
+ & ((self: Scheduler<U...>, pipeline: Pipeline) -> Scheduler<U...>),
112
+
113
+ runAll: (self: Scheduler<U...>) -> Scheduler<U...>,
114
+
115
+ insert: ((self: Scheduler<U...>, phase: Phase) -> Scheduler<U...>) & ((
116
+ self: Scheduler<U...>,
117
+ pipeline: Pipeline
118
+ ) -> Scheduler<U...>) & ((
119
+ self: Scheduler<U...>,
120
+ phase: Phase,
121
+ instance: EventInstance | EventLike,
122
+ event: string | EventLike
123
+ ) -> Scheduler<U...>) & ((
124
+ self: Scheduler<U...>,
125
+ Pipeline: Pipeline,
126
+ instance: EventInstance | EventLike,
127
+ event: string | EventLike
128
+ ) -> Scheduler<U...>),
129
+
130
+ insertAfter: ((
131
+ self: Scheduler<U...>,
132
+ phase: Phase,
133
+ after: Phase | Pipeline
134
+ ) -> Scheduler<U...>) & ((
135
+ self: Scheduler<U...>,
136
+ pipeline: Pipeline,
137
+ after: Phase | Pipeline
138
+ ) -> Scheduler<U...>),
139
+
140
+ new: (U...) -> Scheduler<U...>
141
+ }
142
+
143
+ return {
144
+ Phase = Phase :: Phase,
145
+ Pipeline = Pipeline :: Pipeline,
146
+ Scheduler = Scheduler :: {
147
+ new: <U...>(U...) -> Scheduler<U...>
148
+ },
149
+ }
package/out/types.d.ts ADDED
@@ -0,0 +1,150 @@
1
+
2
+ export type SystemInfo<T extends unknown[]> = {
3
+ readonly system: SystemFn<T>;
4
+ readonly phase: Phase;
5
+ readonly name: string;
6
+ readonly logs: string[];
7
+ }
8
+
9
+
10
+ export interface Hooks {
11
+ readonly Hooks: {
12
+ readonly SystemAdd: "SystemAdd";
13
+ readonly SystemRemove: "SystemRemove";
14
+ readonly SystemReplace: "SystemReplace";
15
+ readonly SystemError: "SystemError";
16
+
17
+ readonly OuterSystemCall: "OuterSystemCall";
18
+ readonly InnerSystemCall: "InnerSystemCall";
19
+ readonly SystemCall: "SystemCall";
20
+
21
+ readonly PhaseAdd: "PhaseAdd";
22
+ readonly PhaseBegan: "PhaseBegan";
23
+ }
24
+ systemAdd: <T extends unknown[] = unknown[]>(scheduler: Scheduler<T>, systemInfo: SystemInfo<T>) => void;
25
+ systemRemove: <T extends unknown[] = unknown[]>(scheduler: Scheduler<T>, systemInfo: SystemInfo<T>) => void;
26
+ systemReplace: <T extends unknown[] = unknown[]>(scheduler: Scheduler<T>, oldSystemInfo: SystemInfo<T>, newSystemInfo: SystemInfo<T>) => void;
27
+ systemCall: <T extends unknown[] = unknown[]>(scheduler: Scheduler<T>, hookName: "OuterSystemCall" | "InnerSystemCall" | "SystemCall", systemInfo: SystemInfo<T>, nextFn: () => void) => void;
28
+ systemError: <T extends unknown[] = unknown[]>(scheduler: Scheduler<T>, systemInfo: SystemInfo<T>, error: string) => void;
29
+ phaseAdd: <T extends unknown[] = unknown[]>(scheduler: Scheduler<T>, phase: Phase) => void;
30
+ phaseBegan: <T extends unknown[] = unknown[]>(scheduler: Scheduler<T>, phase: Phase) => void;
31
+ }
32
+ type SystemAddHookArgs<T extends unknown[]> = {
33
+ scheduler: Scheduler<T>,
34
+ system: SystemInfo<T>
35
+ }
36
+ type SystemRemoveHookArgs<T extends unknown[]> = SystemAddHookArgs<T>;
37
+ type SystemReplaceHookArgs<T extends unknown[]> = {
38
+ scheduler: Scheduler<T>,
39
+ old: SystemInfo<T>,
40
+ new: SystemInfo<T>
41
+ }
42
+ type SystemErrorHookArgs<T extends unknown[]> = SystemAddHookArgs<T> & { error: string };
43
+ type SystemCallHookArgs<T extends unknown[]> = {
44
+ scheduler: undefined;
45
+ system: SystemInfo<T>;
46
+ nextFn: () => void;
47
+ }
48
+ type PhaseAddHookArgs<T extends unknown[]> = {
49
+ scheduler: Scheduler<T>;
50
+ phase: Phase;
51
+ }
52
+ type PhaseBeganHookArgs<T extends unknown[]> = PhaseAddHookArgs<T>;
53
+ type HookFunctionMap<T extends unknown[] = unknown[]> = {
54
+ SystemAdd: SystemAddHookArgs<T>;
55
+ SystemRemove: SystemRemoveHookArgs<T>;
56
+ SystemReplace: SystemRemoveHookArgs<T>;
57
+ SystemError: SystemErrorHookArgs<T>;
58
+ OuterSystemCall: SystemCallHookArgs<T>;
59
+ InnerSystemCall: SystemCallHookArgs<T>;
60
+ SystemCall: SystemCallHookArgs<T>;
61
+ PhaseAdd: PhaseAddHookArgs<T>;
62
+ PhaseBegan: PhaseBeganHookArgs<T>;
63
+ }
64
+ // Utility type to get the correct function type based on the hook name
65
+ type HookFunctionArgs<K extends keyof HookFunctionMap, T extends unknown[]> = HookFunctionMap<T>[K];
66
+
67
+ export type SystemFn<T extends unknown[]> = ((...args: T) => unknown[]) | ((...args: T) => void);
68
+
69
+ export interface SystemTable<T extends unknown[]> {
70
+ readonly system: SystemFn<T>;
71
+ readonly phase?: Phase
72
+ readonly [key: string]: unknown
73
+ }
74
+
75
+ export type System<T extends unknown[]> = SystemFn<T> | SystemTable<T>;
76
+
77
+ export interface EventLike {
78
+ connect(callback: (...args: unknown[]) => void): void;
79
+ Connect(callback: (...args: unknown[]) => void): void;
80
+ on(callback: (...args: unknown[]) => void): void;
81
+ On(callback: (...args: unknown[]) => void): void;
82
+ }
83
+
84
+ export type EventInstance = Instance | EventLike;
85
+
86
+ declare class Phase {
87
+ constructor(debugName?: string)
88
+ static readonly PreStartup: Phase
89
+ static readonly Startup: Phase
90
+ static readonly PostStartup: Phase
91
+ static readonly PreRender: Phase
92
+ static readonly PreAnimation: Phase
93
+ static readonly PreSimulation: Phase
94
+ static readonly PostSimulation: Phase
95
+ static readonly First: Phase
96
+ static readonly PreUpdate: Phase
97
+ static readonly Update: Phase
98
+ static readonly PostUpdate: Phase
99
+ static readonly Last: Phase
100
+ }
101
+
102
+ declare class Pipeline {
103
+ constructor(debugName?: string)
104
+ insert(phase: Phase) : Pipeline
105
+ insertAfter(phase: Phase, after: Phase): Pipeline
106
+ static readonly Main: Pipeline
107
+ static readonly Startup: Pipeline
108
+ }
109
+
110
+ export interface Utils {
111
+ getSystem: <T extends unknown[]>(system: System<T>) => SystemFn<T> | undefined
112
+ getSystemName: <T extends unknown[]>(system: SystemFn<T>) => string
113
+ isPhase: (phase: Phase) => Phase | undefined
114
+ isPipeline: (pipeline: Pipeline) => Pipeline | undefined
115
+ getEventIdentifier: (instance: EventInstance, event?: EventLike) => string
116
+ isValidEvent: (instance: EventInstance, event?: EventLike) => boolean
117
+ }
118
+
119
+ export interface Plugin {
120
+ build<T extends unknown[]>(schedular: Scheduler<T>): void
121
+ }
122
+
123
+ declare class Scheduler<T extends unknown[]> {
124
+ Hooks: Hooks["Hooks"]
125
+ insertAfter(phase: Phase, after: Phase | Pipeline): Scheduler<T>
126
+ insertAfter(pipeline: Pipeline, after: Phase | Pipeline): Scheduler<T>
127
+ insert(phase: Phase): Scheduler<T>
128
+ insert(phase: Pipeline): Scheduler<T>
129
+ insert(phase: Phase, instance: EventInstance | EventLike): Scheduler<T>
130
+ insert(pipeline: Pipeline, instance: EventInstance | EventLike): Scheduler<T>
131
+ runAll(): Scheduler<T>
132
+ run(system: System<T>): Scheduler<T>
133
+ run(phase: Phase): Scheduler<T>
134
+ run(pipeline: Pipeline): Scheduler<T>
135
+ setRunCondition(system: System<T>, fn: (...args: T) => boolean): Scheduler<T>
136
+ setRunCondition(phase: Phase, fn: (...args: T) => boolean): Scheduler<T>
137
+ setRunCondition(pipeline: Pipeline, fn: (...args: T) => boolean): Scheduler<T>
138
+ removeSystem(system: System<T>): Scheduler<T>
139
+ replaceSystem(oldSystem: System<T>, newSystem: System<T>): Scheduler<T>
140
+ editSystem(system: System<T>, phase: Phase): Scheduler<T>
141
+ addSystem(system: System<T>, phase?: Phase): Scheduler<T>
142
+ addPlugin(plugin: Plugin): Scheduler<T>
143
+ /** @hidden */
144
+ _addHook<K extends keyof HookFunctionMap>(hook: K, fn: (info: HookFunctionArgs<K, T>) => void): void
145
+ constructor(...args: T)
146
+ }
147
+
148
+
149
+
150
+
package/out/utils.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import { Utils } from "./types";
2
+
3
+ declare const utils : Utils;
4
+ export = utils;
package/out/utils.luau ADDED
@@ -0,0 +1,83 @@
1
+ type Phase = any
2
+ type Pipeline = any
3
+
4
+ type SystemFn<U...> = ((U...) -> any) | ((U...) -> ())
5
+
6
+ type SystemTable<U...> = {
7
+ system: SystemFn<U...>,
8
+ phase: Phase?,
9
+ [any]: any
10
+ }
11
+
12
+ type System<U...> = SystemFn<U...> | SystemTable<U...>
13
+
14
+ local function getSystem<U...>(system: any): SystemTable<U...>?
15
+ if type(system) == "function" then
16
+ return system
17
+ elseif type(system) == "table" and system.system then
18
+ return system.system
19
+ else
20
+ return nil
21
+ end
22
+ end
23
+
24
+ local function getSystemName(system: any): string
25
+ local name = debug.info(system, "n")
26
+ if not name or string.len(name) == 0 then
27
+ name = debug.info(system, "sl")
28
+ end
29
+
30
+ return name
31
+ end
32
+
33
+ local function isPhase(phase: any): Phase?
34
+ if type(phase) == "table" and phase._type == "phase" then
35
+ return phase
36
+ else
37
+ return nil
38
+ end
39
+ end
40
+
41
+ local function isPipeline(pipeline: any): Pipeline?
42
+ if type(pipeline) == "table" and pipeline._type == "pipeline" then
43
+ return pipeline
44
+ else
45
+ return nil
46
+ end
47
+ end
48
+
49
+ local function getEventIdentifier(instance, event)
50
+ return `{instance}{event and `@{event}` or ""}`
51
+ end
52
+
53
+ local validEventMethods = {
54
+ "Connect",
55
+ "connect",
56
+ "On",
57
+ "on",
58
+ }
59
+
60
+ local function isValidEvent(instance, event)
61
+ local eventInstance = event and instance[event] or instance
62
+
63
+ if typeof(eventInstance) == "RBXScriptSignal" then
64
+ return true
65
+ elseif typeof(eventInstance) == "table" then
66
+ for _, method in validEventMethods do
67
+ if eventInstance[method] ~= nil then
68
+ return true
69
+ end
70
+ end
71
+ end
72
+
73
+ return false
74
+ end
75
+
76
+ return {
77
+ getSystem = getSystem,
78
+ getSystemName = getSystemName,
79
+ isPhase = isPhase,
80
+ isPipeline = isPipeline,
81
+ getEventIdentifier = getEventIdentifier,
82
+ isValidEvent = isValidEvent,
83
+ }
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@rbxts/planck",
3
+ "version": "0.1.0-rc.2",
4
+ "description": "An agnostic scheduler for ECS",
5
+ "main": "out/init.lua",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/yetanotherclown/planck"
9
+ },
10
+ "homepage": "https://yetanotherclown.github.io/planck",
11
+ "keywords": [
12
+ "ECS",
13
+ "Entity Component System",
14
+ "Scheduler",
15
+ "@rbxts",
16
+ "Roblox",
17
+ "Roblox-TS",
18
+ "roblox ts",
19
+ "roblox-ts"
20
+ ],
21
+ "author": "YetAnotherClown",
22
+ "license": "MIT",
23
+ "types": "out/index.d.ts",
24
+ "files": [
25
+ "out",
26
+ "!**/*.tsbuildinfo",
27
+ "!out/__tests__",
28
+ "!out/__tests__/**/*",
29
+ "!out/jest.config.luau"
30
+ ],
31
+ "publishConfig": {
32
+ "access": "public"
33
+ },
34
+ "devDependencies": {
35
+ "@rbxts/compiler-types": "3.0.0-types.0",
36
+ "@rbxts/types": "^1.0.813",
37
+ "@typescript-eslint/eslint-plugin": "^8.19.0",
38
+ "@typescript-eslint/parser": "^8.19.0",
39
+ "eslint": "^9.17.0",
40
+ "eslint-config-prettier": "^9.1.0",
41
+ "eslint-plugin-prettier": "^5.2.1",
42
+ "eslint-plugin-roblox-ts": "^0.0.36",
43
+ "prettier": "^3.4.2",
44
+ "roblox-ts": "^3.0.0",
45
+ "typescript": "^5.7.2"
46
+ },
47
+ "scripts": {
48
+ "build": "rbxtsc",
49
+ "watch": "rbxtsc -w"
50
+ }
51
+ }