@quenty/binder 4.4.1-canary.8533eea.0 → 4.5.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/CHANGELOG.md +10 -2
- package/README.md +6 -106
- package/package.json +11 -11
- package/src/Shared/Binder.lua +186 -84
- package/src/Shared/BinderGroup.lua +36 -2
- package/src/Shared/BinderGroupProvider.lua +35 -5
- package/src/Shared/BinderProvider.lua +66 -7
- package/src/Shared/BinderUtils.lua +72 -2
- package/src/Shared/Collection/BoundChildCollection.lua +42 -10
- package/src/Shared/Promise/promiseBoundClass.lua +13 -2
- package/src/Shared/Trackers/BoundAncestorTracker.lua +18 -3
- package/src/Shared/Trackers/BoundParentTracker.lua +4 -2
package/CHANGELOG.md
CHANGED
|
@@ -3,12 +3,20 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
-
## [4.
|
|
6
|
+
## [4.5.1](https://github.com/Quenty/NevermoreEngine/compare/@quenty/binder@4.5.0...@quenty/binder@4.5.1) (2021-12-30)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @quenty/binder
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# [4.5.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/binder@4.4.0...@quenty/binder@4.5.0) (2021-12-18)
|
|
7
15
|
|
|
8
16
|
|
|
9
17
|
### Bug Fixes
|
|
10
18
|
|
|
11
|
-
* Binder was not deconstructing correctly on cleanup ([
|
|
19
|
+
* Binder was not deconstructing correctly on cleanup ([b6cd547](https://github.com/Quenty/NevermoreEngine/commit/b6cd54746457afe180ddda2f4d41731b29c144a5))
|
|
12
20
|
|
|
13
21
|
|
|
14
22
|
|
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
## Binder
|
|
2
2
|
<div align="center">
|
|
3
|
-
<a href="http://quenty.github.io/
|
|
4
|
-
<img src="https://
|
|
3
|
+
<a href="http://quenty.github.io/NevermoreEngine/">
|
|
4
|
+
<img src="https://github.com/Quenty/NevermoreEngine/actions/workflows/docs.yml/badge.svg" alt="Documentation status" />
|
|
5
5
|
</a>
|
|
6
6
|
<a href="https://discord.gg/mhtGUS8">
|
|
7
|
-
<img src="https://img.shields.io/
|
|
7
|
+
<img src="https://img.shields.io/discord/385151591524597761?color=5865F2&label=discord&logo=discord&logoColor=white" alt="Discord" />
|
|
8
8
|
</a>
|
|
9
9
|
<a href="https://github.com/Quenty/NevermoreEngine/actions">
|
|
10
10
|
<img src="https://github.com/Quenty/NevermoreEngine/actions/workflows/build.yml/badge.svg" alt="Build and release status" />
|
|
@@ -13,109 +13,9 @@
|
|
|
13
13
|
|
|
14
14
|
Binders bind a class to Roblox Instance
|
|
15
15
|
|
|
16
|
+
<div align="center"><a href="https://quenty.github.io/NevermoreEngine/api/Binder">View docs →</a></div>
|
|
17
|
+
|
|
16
18
|
## Installation
|
|
17
19
|
```
|
|
18
20
|
npm install @quenty/binder --save
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
## Usage
|
|
22
|
-
|
|
23
|
-
```lua
|
|
24
|
-
-- Setup a class!
|
|
25
|
-
local MyClass = {}
|
|
26
|
-
MyClass.__index = MyClass
|
|
27
|
-
|
|
28
|
-
function MyClass.new(robloxInstance)
|
|
29
|
-
print("New tagged instance of ", robloxInstance)
|
|
30
|
-
return setmetatable({}, MyClass)
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
function MyClass:Destroy()
|
|
34
|
-
print("Cleaning up")
|
|
35
|
-
setmetatable(self, nil)
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
-- bind to every instance with tag of "TagName"!
|
|
39
|
-
local binder = Binder.new("TagName", MyClass)
|
|
40
|
-
binder:Start() -- listens for new instances and connects events
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
## API
|
|
44
|
-
|
|
45
|
-
### `Binder.new(tagName, constructor)`
|
|
46
|
-
Creates a new binder object.
|
|
47
|
-
|
|
48
|
-
### `Binder.isBinder(value)`
|
|
49
|
-
Retrieves whether or not its a binder
|
|
50
|
-
|
|
51
|
-
### `Binder:Start()`
|
|
52
|
-
Listens for new instances and connects to the GetInstanceAddedSignal() and removed signal!
|
|
53
|
-
|
|
54
|
-
### `Binder:GetTag()`
|
|
55
|
-
Returns the tag name that the binder has
|
|
56
|
-
|
|
57
|
-
### `Binder:GetConstructor()`
|
|
58
|
-
Returns whatever was set for the construtor. Used for meta-analysis of the binder, such as extracting new
|
|
59
|
-
|
|
60
|
-
### `Binder:ObserveInstance(inst, callback)`
|
|
61
|
-
Fired when added, and then after removal, but before destroy!
|
|
62
|
-
|
|
63
|
-
### `Binder:GetClassAddedSignal()`
|
|
64
|
-
Returns a new signal that will fire whenever a class is bound to the binder
|
|
65
|
-
|
|
66
|
-
### `Binder:GetClassRemovingSignal()`
|
|
67
|
-
Returns a new signal that will fire whenever a class is removed from the binder
|
|
68
|
-
|
|
69
|
-
### `Binder:GetAll()`
|
|
70
|
-
Returns all of the classes in a new table
|
|
71
|
-
|
|
72
|
-
```lua
|
|
73
|
-
local birdBinder = Binder.new("Bird", require("Bird")) -- Load bird into binder
|
|
74
|
-
|
|
75
|
-
-- Update every bird every frame
|
|
76
|
-
RunService.Stepped:Connect(function()
|
|
77
|
-
for _, bird in pairs(birdBinder:GetAll()) do
|
|
78
|
-
bird:Update()
|
|
79
|
-
end
|
|
80
|
-
end)
|
|
81
|
-
|
|
82
|
-
```
|
|
83
|
-
### `Binder:GetAllSet()`
|
|
84
|
-
Faster method to get all items in a binder
|
|
85
|
-
|
|
86
|
-
NOTE: Do not mutate this set directly
|
|
87
|
-
|
|
88
|
-
```lua
|
|
89
|
-
local birdBinder = Binder.new("Bird", require("Bird")) -- Load bird into binder
|
|
90
|
-
|
|
91
|
-
-- Update every bird every frame
|
|
92
|
-
RunService.Stepped:Connect(function()
|
|
93
|
-
for bird, _ in pairs(birdBinder:GetAllSet()) do
|
|
94
|
-
bird:Update()
|
|
95
|
-
end
|
|
96
|
-
end)
|
|
97
|
-
|
|
98
|
-
birdBinder:Start()
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
### `Binder:Bind(inst)`
|
|
102
|
-
Binds an instance to this binder using collection service and attempts to return it if it's bound properly. See BinderUtils.promiseBoundClass() for a safe way to retrieve it.
|
|
103
|
-
|
|
104
|
-
NOTE: Do not assume that a bound object will be retrieved
|
|
105
|
-
|
|
106
|
-
### `Binder:Unbind(inst)`
|
|
107
|
-
Unbinds the instance by removing the tag
|
|
108
|
-
|
|
109
|
-
### `Binder:BindClient(inst)`
|
|
110
|
-
See :Bind(). Acknowledges the risk of doing this on the client. Using this acknowledges that we're intentionally binding on a safe client object, i.e. one without replication. If another tag is changed on this instance, this tag will be lost/changed.
|
|
111
|
-
|
|
112
|
-
### `Binder:UnbindClient(inst)`
|
|
113
|
-
See Unbind(), acknowledges risk of doing this on the client.
|
|
114
|
-
|
|
115
|
-
### `Binder:Get(inst)`
|
|
116
|
-
Returns a version of the clas
|
|
117
|
-
|
|
118
|
-
### `Binder:Promise(inst, cancelToken)`
|
|
119
|
-
|
|
120
|
-
### `Binder:Destroy()`
|
|
121
|
-
Cleans up all bound classes, and disconnects all events
|
|
21
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quenty/binder",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.5.1",
|
|
4
4
|
"description": "Utility object to Bind a class to Roblox object, and associated helper methods",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Roblox",
|
|
@@ -25,18 +25,18 @@
|
|
|
25
25
|
"Quenty"
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@quenty/baseobject": "3.2.
|
|
29
|
-
"@quenty/brio": "3.
|
|
30
|
-
"@quenty/instanceutils": "3.
|
|
31
|
-
"@quenty/linkutils": "3.
|
|
32
|
-
"@quenty/loader": "3.1.
|
|
33
|
-
"@quenty/maid": "2.0.
|
|
34
|
-
"@quenty/promise": "3.
|
|
35
|
-
"@quenty/signal": "2.0.
|
|
36
|
-
"@quenty/valueobject": "3.
|
|
28
|
+
"@quenty/baseobject": "^3.2.1",
|
|
29
|
+
"@quenty/brio": "^3.5.1",
|
|
30
|
+
"@quenty/instanceutils": "^3.5.1",
|
|
31
|
+
"@quenty/linkutils": "^3.5.1",
|
|
32
|
+
"@quenty/loader": "^3.1.2",
|
|
33
|
+
"@quenty/maid": "^2.0.2",
|
|
34
|
+
"@quenty/promise": "^3.3.1",
|
|
35
|
+
"@quenty/signal": "^2.0.1",
|
|
36
|
+
"@quenty/valueobject": "^3.5.1"
|
|
37
37
|
},
|
|
38
38
|
"publishConfig": {
|
|
39
39
|
"access": "public"
|
|
40
40
|
},
|
|
41
|
-
"gitHead": "
|
|
41
|
+
"gitHead": "d146c77d0a8e452824de0ab0b4b03ba0370bcc1b"
|
|
42
42
|
}
|
package/src/Shared/Binder.lua
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
--[=[
|
|
2
|
+
Bind class to Roblox Instance
|
|
3
|
+
|
|
4
|
+
```lua
|
|
5
|
+
-- Setup a class!
|
|
6
|
+
local MyClass = {}
|
|
7
|
+
MyClass.__index = MyClass
|
|
8
|
+
|
|
9
|
+
function MyClass.new(robloxInstance)
|
|
10
|
+
print("New tagged instance of ", robloxInstance)
|
|
11
|
+
return setmetatable({}, MyClass)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
function MyClass:Destroy()
|
|
15
|
+
print("Cleaning up")
|
|
16
|
+
setmetatable(self, nil)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
-- bind to every instance with tag of "TagName"!
|
|
20
|
+
local binder = Binder.new("TagName", MyClass)
|
|
21
|
+
binder:Start() -- listens for new instances and connects events
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
@class Binder
|
|
25
|
+
]=]
|
|
3
26
|
|
|
4
27
|
local require = require(script.Parent.loader).load(script)
|
|
5
28
|
|
|
@@ -10,37 +33,37 @@ local Maid = require("Maid")
|
|
|
10
33
|
local MaidTaskUtils = require("MaidTaskUtils")
|
|
11
34
|
local Signal = require("Signal")
|
|
12
35
|
local promiseBoundClass = require("promiseBoundClass")
|
|
13
|
-
--[[
|
|
14
|
-
@usage
|
|
15
|
-
|
|
16
|
-
-- Setup a class!
|
|
17
|
-
local MyClass = {}
|
|
18
|
-
MyClass.__index = MyClass
|
|
19
|
-
|
|
20
|
-
function MyClass.new(robloxInstance)
|
|
21
|
-
print("New tagged instance of ", robloxInstance)
|
|
22
|
-
return setmetatable({}, MyClass)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
function MyClass:Destroy()
|
|
26
|
-
print("Cleaning up")
|
|
27
|
-
setmetatable(self, nil)
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
-- bind to every instance with tag of "TagName"!
|
|
31
|
-
local binder = Binder.new("TagName", MyClass)
|
|
32
|
-
binder:Start() -- listens for new instances and connects events
|
|
33
|
-
]]
|
|
34
36
|
|
|
35
37
|
local Binder = {}
|
|
36
38
|
Binder.__index = Binder
|
|
37
39
|
Binder.ClassName = "Binder"
|
|
38
40
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
--[=[
|
|
42
|
+
Constructor for a binder
|
|
43
|
+
@type BinderContructor (Instance, ...: any) -> T | { new: (Instance, ...: any) } | { Create(self, Instance, ...: any) }
|
|
44
|
+
@within Binder
|
|
45
|
+
]=]
|
|
46
|
+
|
|
47
|
+
--[=[
|
|
48
|
+
Constructs a new binder object.
|
|
49
|
+
|
|
50
|
+
```lua
|
|
51
|
+
local binder = Binder.new("Bird", function(inst)
|
|
52
|
+
print("Wow, a new bird!", inst)
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
Destroy = function()
|
|
56
|
+
print("Uh oh, the bird is gone!")
|
|
57
|
+
end;
|
|
58
|
+
}
|
|
59
|
+
end)
|
|
60
|
+
binder:Start()
|
|
61
|
+
```
|
|
62
|
+
@param tagName string -- Name of the tag to bind to. This uses CollectionService's tag system
|
|
63
|
+
@param constructor BinderContructor
|
|
64
|
+
@param ... any -- Variable arguments that will be passed into the constructor
|
|
65
|
+
@return Binder<T>
|
|
66
|
+
]=]
|
|
44
67
|
function Binder.new(tagName, constructor, ...)
|
|
45
68
|
local self = setmetatable({}, Binder)
|
|
46
69
|
|
|
@@ -55,7 +78,7 @@ function Binder.new(tagName, constructor, ...)
|
|
|
55
78
|
self._listeners = {} -- [inst] = callback
|
|
56
79
|
self._args = {...}
|
|
57
80
|
|
|
58
|
-
delay(5, function()
|
|
81
|
+
task.delay(5, function()
|
|
59
82
|
if not self._loaded then
|
|
60
83
|
warn(("Binder %q is not loaded. Call :Start() on it!"):format(self._tagName))
|
|
61
84
|
end
|
|
@@ -64,14 +87,19 @@ function Binder.new(tagName, constructor, ...)
|
|
|
64
87
|
return self
|
|
65
88
|
end
|
|
66
89
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
90
|
+
--[=[
|
|
91
|
+
Retrieves whether or not the given value is a binder.
|
|
92
|
+
|
|
93
|
+
@param value any
|
|
94
|
+
@return boolean true or false, whether or not it is a value
|
|
95
|
+
]=]
|
|
70
96
|
function Binder.isBinder(value)
|
|
71
97
|
return type(value) == "table" and value.ClassName == "Binder"
|
|
72
98
|
end
|
|
73
99
|
|
|
74
|
-
|
|
100
|
+
--[=[
|
|
101
|
+
Listens for new instances and connects to the GetInstanceAddedSignal() and removed signal!
|
|
102
|
+
]=]
|
|
75
103
|
function Binder:Start()
|
|
76
104
|
if self._loaded then
|
|
77
105
|
return
|
|
@@ -90,17 +118,31 @@ function Binder:Start()
|
|
|
90
118
|
end))
|
|
91
119
|
end
|
|
92
120
|
|
|
93
|
-
--
|
|
121
|
+
--[=[
|
|
122
|
+
Returns the tag name that the binder has.
|
|
123
|
+
@return string
|
|
124
|
+
]=]
|
|
94
125
|
function Binder:GetTag()
|
|
95
126
|
return self._tagName
|
|
96
127
|
end
|
|
97
128
|
|
|
98
|
-
|
|
129
|
+
--[=[
|
|
130
|
+
Returns whatever was set for the construtor. Used for meta-analysis of
|
|
131
|
+
the binder, such as extracting if parameters are allowed.
|
|
132
|
+
|
|
133
|
+
@return BinderContructor
|
|
134
|
+
]=]
|
|
99
135
|
function Binder:GetConstructor()
|
|
100
136
|
return self._constructor
|
|
101
137
|
end
|
|
102
138
|
|
|
103
|
-
--
|
|
139
|
+
--[=[
|
|
140
|
+
Fired when added, and then after removal, but before destroy!
|
|
141
|
+
|
|
142
|
+
@param inst Instance
|
|
143
|
+
@param callback function
|
|
144
|
+
@return function -- Cleanup function
|
|
145
|
+
]=]
|
|
104
146
|
function Binder:ObserveInstance(inst, callback)
|
|
105
147
|
self._listeners[inst] = self._listeners[inst] or {}
|
|
106
148
|
self._listeners[inst][callback] = true
|
|
@@ -117,19 +159,22 @@ function Binder:ObserveInstance(inst, callback)
|
|
|
117
159
|
end
|
|
118
160
|
end
|
|
119
161
|
|
|
120
|
-
--
|
|
121
|
-
|
|
122
|
-
@usage
|
|
162
|
+
--[=[
|
|
163
|
+
Returns a new signal that will fire whenever a class is bound to the binder
|
|
123
164
|
|
|
124
|
-
|
|
165
|
+
```lua
|
|
166
|
+
local birdBinder = Binder.new("Bird", require("Bird")) -- Load bird into binder
|
|
125
167
|
|
|
126
|
-
birdBinder:GetClassAddedSignal():Connect(function(bird)
|
|
127
|
-
|
|
128
|
-
end)
|
|
168
|
+
birdBinder:GetClassAddedSignal():Connect(function(bird)
|
|
169
|
+
bird:Squack() -- Make the bird squack when it's first spawned
|
|
170
|
+
end)
|
|
129
171
|
|
|
130
|
-
-- Load all birds
|
|
131
|
-
birdBinder:Start()
|
|
132
|
-
|
|
172
|
+
-- Load all birds
|
|
173
|
+
birdBinder:Start()
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
@return Signal<T>
|
|
177
|
+
]=]
|
|
133
178
|
function Binder:GetClassAddedSignal()
|
|
134
179
|
if self._classAddedSignal then
|
|
135
180
|
return self._classAddedSignal
|
|
@@ -140,7 +185,11 @@ function Binder:GetClassAddedSignal()
|
|
|
140
185
|
return self._classAddedSignal
|
|
141
186
|
end
|
|
142
187
|
|
|
143
|
-
--
|
|
188
|
+
--[=[
|
|
189
|
+
Returns a new signal that will fire whenever a class is removing from the binder.
|
|
190
|
+
|
|
191
|
+
@return Signal<T>
|
|
192
|
+
]=]
|
|
144
193
|
function Binder:GetClassRemovingSignal()
|
|
145
194
|
if self._classRemovingSignal then
|
|
146
195
|
return self._classRemovingSignal
|
|
@@ -152,7 +201,11 @@ function Binder:GetClassRemovingSignal()
|
|
|
152
201
|
return self._classRemovingSignal
|
|
153
202
|
end
|
|
154
203
|
|
|
155
|
-
--
|
|
204
|
+
--[=[
|
|
205
|
+
Returns a new signal that will fire whenever a class is removed from the binder.
|
|
206
|
+
|
|
207
|
+
@return Signal<T>
|
|
208
|
+
]=]
|
|
156
209
|
function Binder:GetClassRemovedSignal()
|
|
157
210
|
if self._classRemovedSignal then
|
|
158
211
|
return self._classRemovedSignal
|
|
@@ -164,21 +217,24 @@ function Binder:GetClassRemovedSignal()
|
|
|
164
217
|
return self._classRemovedSignal
|
|
165
218
|
end
|
|
166
219
|
|
|
167
|
-
--[[
|
|
168
|
-
|
|
220
|
+
--[=[
|
|
221
|
+
Returns all of the classes in a new table.
|
|
169
222
|
|
|
170
|
-
|
|
223
|
+
```lua
|
|
224
|
+
local birdBinder = Binder.new("Bird", require("Bird")) -- Load bird into binder
|
|
171
225
|
|
|
172
|
-
-- Update every bird every frame
|
|
173
|
-
RunService.Stepped:Connect(function()
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
end)
|
|
226
|
+
-- Update every bird every frame
|
|
227
|
+
RunService.Stepped:Connect(function()
|
|
228
|
+
for _, bird in pairs(birdBinder:GetAll()) do
|
|
229
|
+
bird:Update()
|
|
230
|
+
end
|
|
231
|
+
end)
|
|
232
|
+
|
|
233
|
+
birdBinder:Start()
|
|
234
|
+
```
|
|
178
235
|
|
|
179
|
-
|
|
180
|
-
]]
|
|
181
|
-
--- Returns all of the classes in a new table
|
|
236
|
+
@return {T}
|
|
237
|
+
]=]
|
|
182
238
|
function Binder:GetAll()
|
|
183
239
|
local all = {}
|
|
184
240
|
for class, _ in pairs(self._allClassSet) do
|
|
@@ -188,30 +244,45 @@ function Binder:GetAll()
|
|
|
188
244
|
end
|
|
189
245
|
|
|
190
246
|
|
|
191
|
-
--[[
|
|
192
|
-
|
|
247
|
+
--[=[
|
|
248
|
+
Faster method to get all items in a binder
|
|
193
249
|
|
|
194
|
-
|
|
250
|
+
```lua
|
|
251
|
+
local birdBinder = Binder.new("Bird", require("Bird")) -- Load bird into binder
|
|
195
252
|
|
|
196
|
-
-- Update every bird every frame
|
|
197
|
-
RunService.Stepped:Connect(function()
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
end)
|
|
253
|
+
-- Update every bird every frame
|
|
254
|
+
RunService.Stepped:Connect(function()
|
|
255
|
+
for bird, _ in pairs(birdBinder:GetAllSet()) do
|
|
256
|
+
bird:Update()
|
|
257
|
+
end
|
|
258
|
+
end)
|
|
202
259
|
|
|
203
|
-
birdBinder:Start()
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
260
|
+
birdBinder:Start()
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
:::warning
|
|
264
|
+
Do not mutate this set directly
|
|
265
|
+
:::
|
|
266
|
+
|
|
267
|
+
@return { [T]: boolean }
|
|
268
|
+
]=]
|
|
207
269
|
function Binder:GetAllSet()
|
|
208
270
|
return self._allClassSet
|
|
209
271
|
end
|
|
210
272
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
273
|
+
--[=[
|
|
274
|
+
Binds an instance to this binder using collection service and attempts
|
|
275
|
+
to return it if it's bound properly. See BinderUtils.promiseBoundClass() for a safe
|
|
276
|
+
way to retrieve it.
|
|
277
|
+
|
|
278
|
+
:::warning
|
|
279
|
+
Do not assume that a bound object will be retrieved
|
|
280
|
+
:::
|
|
281
|
+
|
|
282
|
+
@server
|
|
283
|
+
@param inst Instance -- Instance to check
|
|
284
|
+
@return T? -- Bound class
|
|
285
|
+
]=]
|
|
215
286
|
function Binder:Bind(inst)
|
|
216
287
|
if RunService:IsClient() then
|
|
217
288
|
warn(("[Binder.Bind] - Bindings '%s' done on the client! Will be disrupted upon server replication! %s")
|
|
@@ -222,7 +293,12 @@ function Binder:Bind(inst)
|
|
|
222
293
|
return self:Get(inst)
|
|
223
294
|
end
|
|
224
295
|
|
|
225
|
-
--
|
|
296
|
+
--[=[
|
|
297
|
+
Unbinds the instance by removing the tag.
|
|
298
|
+
|
|
299
|
+
@server
|
|
300
|
+
@param inst Instance -- Instance to unbind
|
|
301
|
+
]=]
|
|
226
302
|
function Binder:Unbind(inst)
|
|
227
303
|
assert(typeof(inst) == "Instance", "Bad inst'")
|
|
228
304
|
|
|
@@ -234,9 +310,16 @@ function Binder:Unbind(inst)
|
|
|
234
310
|
CollectionService:RemoveTag(inst, self._tagName)
|
|
235
311
|
end
|
|
236
312
|
|
|
237
|
-
--
|
|
238
|
-
|
|
239
|
-
|
|
313
|
+
--[=[
|
|
314
|
+
See :Bind(). Acknowledges the risk of doing this on the client.
|
|
315
|
+
|
|
316
|
+
Using this acknowledges that we're intentionally binding on a safe client object,
|
|
317
|
+
i.e. one without replication. If another tag is changed on this instance, this tag will be lost/changed.
|
|
318
|
+
|
|
319
|
+
@client
|
|
320
|
+
@param inst Instance -- Instance to bind
|
|
321
|
+
@return T? -- Bound class (potentially)
|
|
322
|
+
]=]
|
|
240
323
|
function Binder:BindClient(inst)
|
|
241
324
|
if not RunService:IsClient() then
|
|
242
325
|
warn(("[Binder.BindClient] - Bindings '%s' done on the server! Will be replicated!")
|
|
@@ -247,18 +330,35 @@ function Binder:BindClient(inst)
|
|
|
247
330
|
return self:Get(inst)
|
|
248
331
|
end
|
|
249
332
|
|
|
250
|
-
--
|
|
333
|
+
--[=[
|
|
334
|
+
See Unbind(), acknowledges risk of doing this on the client.
|
|
335
|
+
|
|
336
|
+
@client
|
|
337
|
+
@param inst Instance -- Instance to unbind
|
|
338
|
+
]=]
|
|
251
339
|
function Binder:UnbindClient(inst)
|
|
252
340
|
assert(typeof(inst) == "Instance", "Bad inst")
|
|
253
341
|
CollectionService:RemoveTag(inst, self._tagName)
|
|
254
342
|
end
|
|
255
343
|
|
|
256
|
-
|
|
344
|
+
--[=[
|
|
345
|
+
Returns a instance of the class that is bound to the instance given.
|
|
346
|
+
|
|
347
|
+
@param inst Instance -- Instance to check
|
|
348
|
+
@return T?
|
|
349
|
+
]=]
|
|
257
350
|
function Binder:Get(inst)
|
|
258
351
|
assert(typeof(inst) == "Instance", "Argument 'inst' is not an Instance")
|
|
259
352
|
return self._instToClass[inst]
|
|
260
353
|
end
|
|
261
354
|
|
|
355
|
+
--[=[
|
|
356
|
+
Returns a promise which will resolve when the instance is bound.
|
|
357
|
+
|
|
358
|
+
@param inst Instance -- Instance to check
|
|
359
|
+
@param cancelToken? CancelToken
|
|
360
|
+
@return Promise<T>
|
|
361
|
+
]=]
|
|
262
362
|
function Binder:Promise(inst, cancelToken)
|
|
263
363
|
assert(typeof(inst) == "Instance", "Argument 'inst' is not an Instance")
|
|
264
364
|
return promiseBoundClass(self, inst, cancelToken)
|
|
@@ -355,7 +455,9 @@ function Binder:_remove(inst)
|
|
|
355
455
|
end
|
|
356
456
|
end
|
|
357
457
|
|
|
358
|
-
|
|
458
|
+
--[=[
|
|
459
|
+
Cleans up all bound classes, and disconnects all events.
|
|
460
|
+
]=]
|
|
359
461
|
function Binder:Destroy()
|
|
360
462
|
local inst, class = next(self._instToClass)
|
|
361
463
|
while class ~= nil do
|
|
@@ -1,5 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
--[=[
|
|
2
|
+
Groups binders together into a list, and allows binders to be dynamically
|
|
3
|
+
added or removed.
|
|
4
|
+
|
|
5
|
+
Also allows their interface to be validated using a validation function.
|
|
6
|
+
This ensures that all added objects are the same type, so they can be used
|
|
7
|
+
for dynamic interactions.
|
|
8
|
+
|
|
9
|
+
@class BinderGroup
|
|
10
|
+
]=]
|
|
3
11
|
|
|
4
12
|
local require = require(script.Parent.loader).load(script)
|
|
5
13
|
|
|
@@ -10,6 +18,13 @@ local BinderGroup = {}
|
|
|
10
18
|
BinderGroup.ClassName = "BinderGroup"
|
|
11
19
|
BinderGroup.__index = BinderGroup
|
|
12
20
|
|
|
21
|
+
--[=[
|
|
22
|
+
Constructs a new BinderGroup
|
|
23
|
+
|
|
24
|
+
@param binders { Binder<T> } -- A list of binders that
|
|
25
|
+
@param validateConstructor (constructor: any) -> boolean -- Validates a binder matches T
|
|
26
|
+
@return BinderGroup<T>
|
|
27
|
+
]=]
|
|
13
28
|
function BinderGroup.new(binders, validateConstructor)
|
|
14
29
|
local self = setmetatable({}, BinderGroup)
|
|
15
30
|
|
|
@@ -24,6 +39,11 @@ function BinderGroup.new(binders, validateConstructor)
|
|
|
24
39
|
return self
|
|
25
40
|
end
|
|
26
41
|
|
|
42
|
+
--[=[
|
|
43
|
+
Adds a list of binders to the group.
|
|
44
|
+
|
|
45
|
+
@param binders { Binder<T> }
|
|
46
|
+
]=]
|
|
27
47
|
function BinderGroup:AddList(binders)
|
|
28
48
|
assert(type(binders) == "table", "Bad binders")
|
|
29
49
|
|
|
@@ -34,6 +54,11 @@ function BinderGroup:AddList(binders)
|
|
|
34
54
|
end
|
|
35
55
|
end
|
|
36
56
|
|
|
57
|
+
--[=[
|
|
58
|
+
Adds the specific binder to the list
|
|
59
|
+
|
|
60
|
+
@param binder Binder<T>
|
|
61
|
+
]=]
|
|
37
62
|
function BinderGroup:Add(binder)
|
|
38
63
|
assert(Binder.isBinder(binder))
|
|
39
64
|
|
|
@@ -52,6 +77,15 @@ function BinderGroup:Add(binder)
|
|
|
52
77
|
self.BinderAdded:Fire(binder)
|
|
53
78
|
end
|
|
54
79
|
|
|
80
|
+
--[=[
|
|
81
|
+
Returns a list of binders.
|
|
82
|
+
|
|
83
|
+
:::warning
|
|
84
|
+
Do not modify the list of binders returned here
|
|
85
|
+
:::
|
|
86
|
+
|
|
87
|
+
@return { T }
|
|
88
|
+
]=]
|
|
55
89
|
function BinderGroup:GetBinders()
|
|
56
90
|
assert(self._binders, "No self._binders")
|
|
57
91
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
--[=[
|
|
2
|
+
Provides a basis for binderGroups that can be retrieved anywhere
|
|
3
|
+
@class BinderGroupProvider
|
|
4
|
+
]=]
|
|
3
5
|
|
|
4
6
|
local require = require(script.Parent.loader).load(script)
|
|
5
7
|
|
|
@@ -9,6 +11,11 @@ local BinderGroupProvider = {}
|
|
|
9
11
|
BinderGroupProvider.ClassName = "BinderGroupProvider"
|
|
10
12
|
BinderGroupProvider.__index = BinderGroupProvider
|
|
11
13
|
|
|
14
|
+
--[=[
|
|
15
|
+
Constructs a new BinderGroupProvider
|
|
16
|
+
@param initMethod (BinderGroupProvider) -> ()
|
|
17
|
+
@return BinderGroupProvider
|
|
18
|
+
]=]
|
|
12
19
|
function BinderGroupProvider.new(initMethod)
|
|
13
20
|
local self = setmetatable({}, BinderGroupProvider)
|
|
14
21
|
|
|
@@ -21,10 +28,18 @@ function BinderGroupProvider.new(initMethod)
|
|
|
21
28
|
return self
|
|
22
29
|
end
|
|
23
30
|
|
|
31
|
+
--[=[
|
|
32
|
+
Returns a promise that will resolve once groups are added.
|
|
33
|
+
@return Promise
|
|
34
|
+
]=]
|
|
24
35
|
function BinderGroupProvider:PromiseGroupsAdded()
|
|
25
36
|
return self._groupsAddedPromise
|
|
26
37
|
end
|
|
27
38
|
|
|
39
|
+
--[=[
|
|
40
|
+
Starts the binder provider. Should be called via ServiceBag.
|
|
41
|
+
@param ... ServiceBag | any
|
|
42
|
+
]=]
|
|
28
43
|
function BinderGroupProvider:Init(...)
|
|
29
44
|
assert(not self._init, "Already initialized")
|
|
30
45
|
|
|
@@ -34,6 +49,9 @@ function BinderGroupProvider:Init(...)
|
|
|
34
49
|
self._groupsAddedPromise:Resolve()
|
|
35
50
|
end
|
|
36
51
|
|
|
52
|
+
--[=[
|
|
53
|
+
Starts the binder provider. Should be called via ServiceBag.
|
|
54
|
+
]=]
|
|
37
55
|
function BinderGroupProvider:Start()
|
|
38
56
|
-- Do nothing
|
|
39
57
|
end
|
|
@@ -46,11 +64,23 @@ function BinderGroupProvider:__index(index)
|
|
|
46
64
|
error(("%q Not a valid index"):format(tostring(index)))
|
|
47
65
|
end
|
|
48
66
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
67
|
+
--[=[
|
|
68
|
+
Returns a binder group given the binderName
|
|
69
|
+
|
|
70
|
+
@param groupName string
|
|
71
|
+
@return BinderGroup?
|
|
72
|
+
]=]
|
|
73
|
+
function BinderGroupProvider:Get(groupName)
|
|
74
|
+
assert(type(groupName) == "string", "groupName must be a string")
|
|
75
|
+
return rawget(self, groupName)
|
|
52
76
|
end
|
|
53
77
|
|
|
78
|
+
--[=[
|
|
79
|
+
Adds a new group at the given name
|
|
80
|
+
|
|
81
|
+
@param groupName string
|
|
82
|
+
@param binderGroup BinderGroup
|
|
83
|
+
]=]
|
|
54
84
|
function BinderGroupProvider:Add(groupName, binderGroup)
|
|
55
85
|
assert(type(groupName) == "string", "Bad groupName")
|
|
56
86
|
assert(type(binderGroup) == "table", "Bad binderGroup")
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
--[=[
|
|
2
|
+
Provides a basis for binders that can be retrieved anywhere
|
|
3
|
+
@class BinderProvider
|
|
4
|
+
]=]
|
|
3
5
|
|
|
4
6
|
local require = require(script.Parent.loader).load(script)
|
|
5
7
|
|
|
@@ -9,6 +11,28 @@ local BinderProvider = {}
|
|
|
9
11
|
BinderProvider.ClassName = "BinderProvider"
|
|
10
12
|
BinderProvider.__index = BinderProvider
|
|
11
13
|
|
|
14
|
+
--[=[
|
|
15
|
+
Constructs a new BinderProvider.
|
|
16
|
+
|
|
17
|
+
```lua
|
|
18
|
+
local serviceBag = ServiceBag.new()
|
|
19
|
+
|
|
20
|
+
-- Usually in a separate file!
|
|
21
|
+
local binderProvider = BinderProvider.new(function(self, serviceBag)
|
|
22
|
+
serviceBag:Add(Binder.new("Bird", require("Bird")))
|
|
23
|
+
end)
|
|
24
|
+
|
|
25
|
+
-- Retrieve binders
|
|
26
|
+
local binders = serviceBag:GetService(binderProvider)
|
|
27
|
+
|
|
28
|
+
-- Runs the game (including binders)
|
|
29
|
+
serviceBag:Init()
|
|
30
|
+
serviceBag:Start()
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
@param initMethod (self, serviceBag: ServiceBag)
|
|
34
|
+
@return BinderProvider
|
|
35
|
+
]=]
|
|
12
36
|
function BinderProvider.new(initMethod)
|
|
13
37
|
local self = setmetatable({}, BinderProvider)
|
|
14
38
|
|
|
@@ -25,13 +49,21 @@ function BinderProvider.new(initMethod)
|
|
|
25
49
|
return self
|
|
26
50
|
end
|
|
27
51
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
52
|
+
--[=[
|
|
53
|
+
Retrieves whether or not its a binder provider
|
|
54
|
+
@param value any
|
|
55
|
+
@return boolean -- True if it is a binder provider
|
|
56
|
+
]=]
|
|
31
57
|
function BinderProvider.isBinderProvider(value)
|
|
32
58
|
return type(value) == "table" and value.ClassName == "BinderProvider"
|
|
33
59
|
end
|
|
34
60
|
|
|
61
|
+
--[=[
|
|
62
|
+
Resolves to the given binder given the binderName.
|
|
63
|
+
|
|
64
|
+
@param binderName string
|
|
65
|
+
@return Promise<Binder<T>>
|
|
66
|
+
]=]
|
|
35
67
|
function BinderProvider:PromiseBinder(binderName)
|
|
36
68
|
if self._bindersAddedPromise:IsFulfilled() then
|
|
37
69
|
local binder = self:Get(binderName)
|
|
@@ -53,7 +85,11 @@ function BinderProvider:PromiseBinder(binderName)
|
|
|
53
85
|
end)
|
|
54
86
|
end
|
|
55
87
|
|
|
56
|
-
--
|
|
88
|
+
--[=[
|
|
89
|
+
Initializes itself and all binders
|
|
90
|
+
|
|
91
|
+
@param ... ServiceBag | any
|
|
92
|
+
]=]
|
|
57
93
|
function BinderProvider:Init(...)
|
|
58
94
|
assert(not self._initialized, "Already initialized")
|
|
59
95
|
|
|
@@ -62,15 +98,27 @@ function BinderProvider:Init(...)
|
|
|
62
98
|
self._bindersAddedPromise:Resolve()
|
|
63
99
|
end
|
|
64
100
|
|
|
101
|
+
--[=[
|
|
102
|
+
Returns a promise that will resolve once all binders are added.
|
|
103
|
+
|
|
104
|
+
@return Promise
|
|
105
|
+
]=]
|
|
65
106
|
function BinderProvider:PromiseBindersAdded()
|
|
66
107
|
return self._bindersAddedPromise
|
|
67
108
|
end
|
|
68
109
|
|
|
110
|
+
--[=[
|
|
111
|
+
Returns a promise that will resolve once all binders are started.
|
|
112
|
+
|
|
113
|
+
@return Promise
|
|
114
|
+
]=]
|
|
69
115
|
function BinderProvider:PromiseBindersStarted()
|
|
70
116
|
return self._startPromise
|
|
71
117
|
end
|
|
72
118
|
|
|
73
|
-
--
|
|
119
|
+
--[=[
|
|
120
|
+
Starts all of the binders.
|
|
121
|
+
]=]
|
|
74
122
|
function BinderProvider:Start()
|
|
75
123
|
assert(self._initialized, "Not initialized")
|
|
76
124
|
assert(not self._started, "Already started")
|
|
@@ -92,11 +140,22 @@ function BinderProvider:__index(index)
|
|
|
92
140
|
error(("%q Not a valid index"):format(tostring(index)))
|
|
93
141
|
end
|
|
94
142
|
|
|
143
|
+
--[=[
|
|
144
|
+
Retrieves a binder given a tagName
|
|
145
|
+
|
|
146
|
+
@param tagName string
|
|
147
|
+
@return Binder<T>?
|
|
148
|
+
]=]
|
|
95
149
|
function BinderProvider:Get(tagName)
|
|
96
150
|
assert(type(tagName) == "string", "tagName must be a string")
|
|
97
151
|
return rawget(self, tagName)
|
|
98
152
|
end
|
|
99
153
|
|
|
154
|
+
--[=[
|
|
155
|
+
Adds a binder given a tag name.
|
|
156
|
+
|
|
157
|
+
@param binder Binder<T>
|
|
158
|
+
]=]
|
|
100
159
|
function BinderProvider:Add(binder)
|
|
101
160
|
assert(not self._started, "Already inited")
|
|
102
161
|
assert(not self:Get(binder:GetTag()), "Binder already exists")
|
|
@@ -1,10 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
--[=[
|
|
2
|
+
Utility methods for the binder object.
|
|
3
|
+
@class BinderUtils
|
|
4
|
+
]=]
|
|
3
5
|
|
|
4
6
|
local CollectionService = game:GetService("CollectionService")
|
|
5
7
|
|
|
6
8
|
local BinderUtils = {}
|
|
7
9
|
|
|
10
|
+
--[=[
|
|
11
|
+
Finds the first ancestor that is bound with the current child.
|
|
12
|
+
Skips the child class, of course.
|
|
13
|
+
|
|
14
|
+
@param binder Binder<T>
|
|
15
|
+
@param child Instance
|
|
16
|
+
@return T?
|
|
17
|
+
]=]
|
|
8
18
|
function BinderUtils.findFirstAncestor(binder, child)
|
|
9
19
|
assert(type(binder) == "table", "Binder must be binder")
|
|
10
20
|
assert(typeof(child) == "Instance", "Child parameter must be instance")
|
|
@@ -20,6 +30,14 @@ function BinderUtils.findFirstAncestor(binder, child)
|
|
|
20
30
|
return nil
|
|
21
31
|
end
|
|
22
32
|
|
|
33
|
+
--[=[
|
|
34
|
+
Finds the first child bound with the given binder and returns
|
|
35
|
+
the bound class.
|
|
36
|
+
|
|
37
|
+
@param binder Binder<T>
|
|
38
|
+
@param parent Instance
|
|
39
|
+
@return T?
|
|
40
|
+
]=]
|
|
23
41
|
function BinderUtils.findFirstChild(binder, parent)
|
|
24
42
|
assert(type(binder) == "table", "Binder must be binder")
|
|
25
43
|
assert(typeof(parent) == "Instance", "Parent parameter must be instance")
|
|
@@ -34,6 +52,13 @@ function BinderUtils.findFirstChild(binder, parent)
|
|
|
34
52
|
return nil
|
|
35
53
|
end
|
|
36
54
|
|
|
55
|
+
--[=[
|
|
56
|
+
Gets all bound children of the given binder for the parent.
|
|
57
|
+
|
|
58
|
+
@param binder Binder<T>
|
|
59
|
+
@param parent Instance
|
|
60
|
+
@return {T}
|
|
61
|
+
]=]
|
|
37
62
|
function BinderUtils.getChildren(binder, parent)
|
|
38
63
|
assert(type(binder) == "table", "Binder must be binder")
|
|
39
64
|
assert(typeof(parent) == "Instance", "Parent parameter must be instance")
|
|
@@ -48,6 +73,16 @@ function BinderUtils.getChildren(binder, parent)
|
|
|
48
73
|
return objects
|
|
49
74
|
end
|
|
50
75
|
|
|
76
|
+
|
|
77
|
+
--[=[
|
|
78
|
+
Maps a list of binders into a look up table where the keys are
|
|
79
|
+
tags and the value is the binder.
|
|
80
|
+
|
|
81
|
+
Duplicates are overwritten by the last entry.
|
|
82
|
+
|
|
83
|
+
@param bindersList { Binder<any> }
|
|
84
|
+
@return { [string]: Binder<any> }
|
|
85
|
+
]=]
|
|
51
86
|
function BinderUtils.mapBinderListToTable(bindersList)
|
|
52
87
|
assert(type(bindersList) == "table", "bindersList must be a table of binders")
|
|
53
88
|
|
|
@@ -58,6 +93,19 @@ function BinderUtils.mapBinderListToTable(bindersList)
|
|
|
58
93
|
return tags
|
|
59
94
|
end
|
|
60
95
|
|
|
96
|
+
--[=[
|
|
97
|
+
Given a mapping of tags to binders, retrieves the bound values
|
|
98
|
+
from an instanceList by quering the list of :GetTags() instead
|
|
99
|
+
of iterating over each binder.
|
|
100
|
+
|
|
101
|
+
This lookup should be faster when there are potentially many
|
|
102
|
+
interaction points for a given tag map, but the actual bound
|
|
103
|
+
list should be low.
|
|
104
|
+
|
|
105
|
+
@param tagsMap { [string]: Binder<T> }
|
|
106
|
+
@param instanceList { Instance }
|
|
107
|
+
@return { T }
|
|
108
|
+
]=]
|
|
61
109
|
function BinderUtils.getMappedFromList(tagsMap, instanceList)
|
|
62
110
|
local objects = {}
|
|
63
111
|
|
|
@@ -76,6 +124,13 @@ function BinderUtils.getMappedFromList(tagsMap, instanceList)
|
|
|
76
124
|
return objects
|
|
77
125
|
end
|
|
78
126
|
|
|
127
|
+
--[=[
|
|
128
|
+
Given a list of binders retrieves all children bound with the given value.
|
|
129
|
+
|
|
130
|
+
@param bindersList { Binder<T> }
|
|
131
|
+
@param parent Instance
|
|
132
|
+
@return { T }
|
|
133
|
+
]=]
|
|
79
134
|
function BinderUtils.getChildrenOfBinders(bindersList, parent)
|
|
80
135
|
assert(type(bindersList) == "table", "bindersList must be a table of binders")
|
|
81
136
|
assert(typeof(parent) == "Instance", "Parent parameter must be instance")
|
|
@@ -84,6 +139,14 @@ function BinderUtils.getChildrenOfBinders(bindersList, parent)
|
|
|
84
139
|
return BinderUtils.getMappedFromList(tagsMap, parent:GetChildren())
|
|
85
140
|
end
|
|
86
141
|
|
|
142
|
+
--[=[
|
|
143
|
+
Gets all the linked (via objectValues of name `linkName`) bound objects
|
|
144
|
+
|
|
145
|
+
@param binder Binder<T>
|
|
146
|
+
@param linkName string -- Name of the object values required
|
|
147
|
+
@param parent Instance
|
|
148
|
+
@return {T}
|
|
149
|
+
]=]
|
|
87
150
|
function BinderUtils.getLinkedChildren(binder, linkName, parent)
|
|
88
151
|
local seen = {}
|
|
89
152
|
local objects = {}
|
|
@@ -103,6 +166,13 @@ function BinderUtils.getLinkedChildren(binder, linkName, parent)
|
|
|
103
166
|
return objects
|
|
104
167
|
end
|
|
105
168
|
|
|
169
|
+
--[=[
|
|
170
|
+
Gets all bound descendants of the given binder for the parent.
|
|
171
|
+
|
|
172
|
+
@param binder Binder<T>
|
|
173
|
+
@param parent Instance
|
|
174
|
+
@return {T}
|
|
175
|
+
]=]
|
|
106
176
|
function BinderUtils.getDescendants(binder, parent)
|
|
107
177
|
assert(type(binder) == "table", "Binder must be binder")
|
|
108
178
|
assert(typeof(parent) == "Instance", "Parent parameter must be instance")
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
--[=[
|
|
2
|
+
Tracks child of type of a binder.
|
|
3
|
+
@class BoundChildCollection
|
|
4
|
+
]=]
|
|
3
5
|
|
|
4
6
|
local require = require(script.Parent.loader).load(script)
|
|
5
7
|
|
|
@@ -10,17 +12,31 @@ local BoundChildCollection = setmetatable({}, BaseObject)
|
|
|
10
12
|
BoundChildCollection.ClassName = "BoundChildCollection"
|
|
11
13
|
BoundChildCollection.__index = BoundChildCollection
|
|
12
14
|
|
|
15
|
+
--[=[
|
|
16
|
+
Constructcs a new BoundChildCollection.
|
|
17
|
+
@param binder Binder<T>
|
|
18
|
+
@param parent Instance
|
|
19
|
+
@return BoundChildCollection<T>
|
|
20
|
+
]=]
|
|
13
21
|
function BoundChildCollection.new(binder, parent)
|
|
14
22
|
local self = setmetatable(BaseObject.new(), BoundChildCollection)
|
|
15
23
|
|
|
16
24
|
self._binder = binder or error("No binder")
|
|
17
25
|
self._parent = parent or error("No parent")
|
|
18
26
|
|
|
19
|
-
|
|
27
|
+
--[=[
|
|
28
|
+
Fires on class addition
|
|
29
|
+
@prop ClassAdded Signal<T>
|
|
30
|
+
@within BoundChildCollection
|
|
31
|
+
]=]
|
|
20
32
|
self.ClassAdded = Signal.new() -- :Fire(class)
|
|
21
33
|
self._maid:GiveTask(self.ClassAdded)
|
|
22
34
|
|
|
23
|
-
|
|
35
|
+
--[=[
|
|
36
|
+
Fires on class removal
|
|
37
|
+
@prop ClassRemoved Signal<T>
|
|
38
|
+
@within BoundChildCollection
|
|
39
|
+
]=]
|
|
24
40
|
self.ClassRemoved = Signal.new() -- :Fire(class)
|
|
25
41
|
self._maid:GiveTask(self.ClassRemoved)
|
|
26
42
|
|
|
@@ -39,24 +55,40 @@ function BoundChildCollection.new(binder, parent)
|
|
|
39
55
|
return self
|
|
40
56
|
end
|
|
41
57
|
|
|
42
|
-
|
|
43
|
-
|
|
58
|
+
--[=[
|
|
59
|
+
Returns whether the track has the class
|
|
60
|
+
@param class T
|
|
61
|
+
@return boolean? -- true if the class exists, nil otherwise
|
|
62
|
+
]=]
|
|
44
63
|
function BoundChildCollection:HasClass(class)
|
|
45
64
|
return self._classes[class]
|
|
46
65
|
end
|
|
47
66
|
|
|
67
|
+
--[=[
|
|
68
|
+
Gets the size
|
|
69
|
+
@return number
|
|
70
|
+
]=]
|
|
48
71
|
function BoundChildCollection:GetSize()
|
|
49
72
|
return self._size
|
|
50
73
|
end
|
|
51
74
|
|
|
52
|
-
|
|
53
|
-
|
|
75
|
+
--[=[
|
|
76
|
+
Returns the raw classes variable as [class] = true.
|
|
77
|
+
|
|
78
|
+
:::warning
|
|
79
|
+
Do not modify the set
|
|
80
|
+
:::
|
|
81
|
+
|
|
82
|
+
@return { [T] = true } -- The set
|
|
83
|
+
]=]
|
|
54
84
|
function BoundChildCollection:GetSet()
|
|
55
85
|
return self._classes
|
|
56
86
|
end
|
|
57
87
|
|
|
58
|
-
|
|
59
|
-
|
|
88
|
+
--[=[
|
|
89
|
+
Slow than :GetSet(), but adds them in an ordered list
|
|
90
|
+
@return { T }
|
|
91
|
+
]=]
|
|
60
92
|
function BoundChildCollection:GetClasses()
|
|
61
93
|
local list = {}
|
|
62
94
|
for class, _ in pairs(self._classes) do
|
|
@@ -1,11 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
--[=[
|
|
2
|
+
Utility function to promise a bound class on an object
|
|
3
|
+
@class promiseBoundClass
|
|
4
|
+
]=]
|
|
3
5
|
|
|
4
6
|
local require = require(script.Parent.loader).load(script)
|
|
5
7
|
|
|
6
8
|
local Promise = require("Promise")
|
|
7
9
|
local Maid = require("Maid")
|
|
8
10
|
|
|
11
|
+
--[=[
|
|
12
|
+
Returns a promise that resolves when the class is bound to the instance.
|
|
13
|
+
@param binder Binder<T>
|
|
14
|
+
@param inst Instance
|
|
15
|
+
@param cancelToken CancelToken
|
|
16
|
+
@return Promise<T>
|
|
17
|
+
@function promiseBoundClass
|
|
18
|
+
@within promiseBoundClass
|
|
19
|
+
]=]
|
|
9
20
|
return function(binder, inst, cancelToken)
|
|
10
21
|
assert(type(binder) == "table", "'binder' must be table")
|
|
11
22
|
assert(typeof(inst) == "Instance", "'inst' must be instance")
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
--[=[
|
|
2
|
+
Tracks a parent bound to a specific binder
|
|
3
|
+
@class BoundAncestorTracker
|
|
4
|
+
]=]
|
|
3
5
|
|
|
4
6
|
local require = require(script.Parent.loader).load(script)
|
|
5
7
|
|
|
@@ -11,13 +13,26 @@ local BoundAncestorTracker = setmetatable({}, BaseObject)
|
|
|
11
13
|
BoundAncestorTracker.ClassName = "BoundAncestorTracker"
|
|
12
14
|
BoundAncestorTracker.__index = BoundAncestorTracker
|
|
13
15
|
|
|
16
|
+
|
|
17
|
+
--[=[
|
|
18
|
+
Constructs a new BoundAncestorTracker
|
|
19
|
+
|
|
20
|
+
@param binder Binder<T>
|
|
21
|
+
@param child Instance
|
|
22
|
+
@return BoundAncestorTracker
|
|
23
|
+
]=]
|
|
14
24
|
function BoundAncestorTracker.new(binder, child)
|
|
15
25
|
local self = setmetatable(BaseObject.new(), BoundAncestorTracker)
|
|
16
26
|
|
|
17
27
|
self._child = child or error("No child")
|
|
18
28
|
self._binder = binder or error("No binder")
|
|
19
29
|
|
|
20
|
-
|
|
30
|
+
--[=[
|
|
31
|
+
@prop Class ValueObject<T>
|
|
32
|
+
@readonly
|
|
33
|
+
@within BoundAncestorTracker
|
|
34
|
+
Bound value
|
|
35
|
+
]=]
|
|
21
36
|
self.Class = ValueObject.new()
|
|
22
37
|
self._maid:GiveTask(self.Class)
|
|
23
38
|
|