@quenty/signal 2.4.0 → 3.0.0
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 +11 -0
- package/package.json +5 -2
- package/src/Shared/GoodSignal.lua +114 -34
- package/src/Shared/Signal.lua +8 -0
- package/src/node_modules.project.json +7 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,17 @@
|
|
|
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
|
+
# [3.0.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/signal@2.4.0...@quenty/signal@3.0.0) (2023-10-11)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* Use GoodSignal only as signal implementation ([4475cab](https://github.com/Quenty/NevermoreEngine/commit/4475cab448564a8cf8e51902e30f5c486bf49ac3))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
6
17
|
# [2.4.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/signal@2.3.0...@quenty/signal@2.4.0) (2023-05-26)
|
|
7
18
|
|
|
8
19
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quenty/signal",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "A simple signal implementation for Roblox",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Roblox",
|
|
@@ -29,5 +29,8 @@
|
|
|
29
29
|
"publishConfig": {
|
|
30
30
|
"access": "public"
|
|
31
31
|
},
|
|
32
|
-
"
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@quenty/loader": "^7.0.0"
|
|
34
|
+
},
|
|
35
|
+
"gitHead": "fdeae46099587019ec5fc15317dc673aed379400"
|
|
33
36
|
}
|
|
@@ -1,27 +1,47 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
1
|
+
--[=[
|
|
2
|
+
Batched Yield-Safe Signal Implementation
|
|
3
|
+
|
|
4
|
+
Lua-side duplication of the [API of events on Roblox objects](https://create.roblox.com/docs/reference/engine/datatypes/RBXScriptSignal).
|
|
5
|
+
|
|
6
|
+
Signals are needed for to ensure that for local events objects are passed by
|
|
7
|
+
reference rather than by value where possible, as the BindableEvent objects
|
|
8
|
+
always pass signal arguments by value, meaning tables will be deep copied.
|
|
9
|
+
Roblox's deep copy method parses to a non-lua table compatable format.
|
|
10
|
+
|
|
11
|
+
This class is designed to work both in deferred mode and in regular mode.
|
|
12
|
+
It follows whatever mode is set.
|
|
13
|
+
|
|
14
|
+
```lua
|
|
15
|
+
local signal = Signal.new()
|
|
16
|
+
|
|
17
|
+
local arg = {}
|
|
18
|
+
|
|
19
|
+
signal:Connect(function(value)
|
|
20
|
+
assert(arg == value, "Tables are preserved when firing a Signal")
|
|
21
|
+
end)
|
|
22
|
+
|
|
23
|
+
signal:Fire(arg)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
:::info
|
|
27
|
+
Why this over a direct [BindableEvent]? Well, in this case, the signal
|
|
28
|
+
prevents Roblox from trying to serialize and desialize each table reference
|
|
29
|
+
fired through the BindableEvent.
|
|
30
|
+
:::
|
|
31
|
+
|
|
32
|
+
This is a Signal class which has effectively identical behavior to a
|
|
33
|
+
normal RBXScriptSignal, with the only difference being a couple extra
|
|
34
|
+
stack frames at the bottom of the stack trace when an error is thrown
|
|
35
|
+
This implementation caches runner coroutines, so the ability to yield in
|
|
36
|
+
the signal handlers comes at minimal extra cost over a naive signal
|
|
37
|
+
implementation that either always or never spawns a thread.
|
|
38
|
+
|
|
39
|
+
Author notes:
|
|
40
|
+
stravant - July 31st, 2021 - Created the file.
|
|
41
|
+
Quenty - Auguest 21st, 2023 - Modified to fit Nevermore contract, with Moonwave docs
|
|
42
|
+
|
|
43
|
+
@class Signal
|
|
44
|
+
]=]
|
|
25
45
|
|
|
26
46
|
-- The currently idle thread to run the next handler on
|
|
27
47
|
local freeRunnerThread = nil
|
|
@@ -100,14 +120,36 @@ setmetatable(Connection, {
|
|
|
100
120
|
|
|
101
121
|
-- Signal class
|
|
102
122
|
local Signal = {}
|
|
123
|
+
Signal.ClassName = "Signal"
|
|
103
124
|
Signal.__index = Signal
|
|
104
125
|
|
|
126
|
+
--[=[
|
|
127
|
+
Constructs a new signal.
|
|
128
|
+
@return Signal<T>
|
|
129
|
+
]=]
|
|
105
130
|
function Signal.new()
|
|
106
131
|
return setmetatable({
|
|
107
132
|
_handlerListHead = false,
|
|
108
133
|
}, Signal)
|
|
109
134
|
end
|
|
110
135
|
|
|
136
|
+
--[=[
|
|
137
|
+
Returns whether a class is a signal
|
|
138
|
+
|
|
139
|
+
@param value any
|
|
140
|
+
@return boolean
|
|
141
|
+
]=]
|
|
142
|
+
function Signal.isSignal(value)
|
|
143
|
+
return type(value) == "table"
|
|
144
|
+
and getmetatable(value) == Signal
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
--[=[
|
|
148
|
+
Connect a new handler to the event. Returns a connection object that can be disconnected.
|
|
149
|
+
|
|
150
|
+
@param fn (... T) -> () -- Function handler called when `:Fire(...)` is called
|
|
151
|
+
@return RBXScriptConnection
|
|
152
|
+
]=]
|
|
111
153
|
function Signal:Connect(fn)
|
|
112
154
|
local connection = Connection.new(self, fn)
|
|
113
155
|
if self._handlerListHead then
|
|
@@ -119,16 +161,30 @@ function Signal:Connect(fn)
|
|
|
119
161
|
return connection
|
|
120
162
|
end
|
|
121
163
|
|
|
122
|
-
--
|
|
123
|
-
|
|
164
|
+
--[=[
|
|
165
|
+
Disconnects all connected events to the signal.
|
|
166
|
+
|
|
167
|
+
:::info
|
|
168
|
+
Disconnect all handlers. Since we use a linked list it suffices to clear the
|
|
169
|
+
reference to the head handler.
|
|
170
|
+
:::
|
|
171
|
+
]=]
|
|
124
172
|
function Signal:DisconnectAll()
|
|
125
173
|
self._handlerListHead = false
|
|
126
174
|
end
|
|
127
175
|
|
|
128
|
-
--
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
176
|
+
--[=[
|
|
177
|
+
Fire the event with the given arguments. All handlers will be invoked. Handlers follow
|
|
178
|
+
|
|
179
|
+
::: info
|
|
180
|
+
Signal:Fire(...) is implemented by running the handler functions on the
|
|
181
|
+
coRunnerThread, and any time the resulting thread yielded without returning
|
|
182
|
+
to us, that means that it yielded to the Roblox scheduler and has been taken
|
|
183
|
+
over by Roblox scheduling, meaning we have to make a new coroutine runner.
|
|
184
|
+
:::
|
|
185
|
+
|
|
186
|
+
@param ... T -- Variable arguments to pass to handler
|
|
187
|
+
]=]
|
|
132
188
|
function Signal:Fire(...)
|
|
133
189
|
local item = self._handlerListHead
|
|
134
190
|
while item do
|
|
@@ -144,8 +200,17 @@ function Signal:Fire(...)
|
|
|
144
200
|
end
|
|
145
201
|
end
|
|
146
202
|
|
|
147
|
-
--
|
|
148
|
-
|
|
203
|
+
--[=[
|
|
204
|
+
Wait for fire to be called, and return the arguments it was given.
|
|
205
|
+
|
|
206
|
+
::: info
|
|
207
|
+
Signal:Wait() is implemented in terms of a temporary connection using
|
|
208
|
+
a Signal:Connect() which disconnects itself.
|
|
209
|
+
:::
|
|
210
|
+
|
|
211
|
+
@yields
|
|
212
|
+
@return T
|
|
213
|
+
]=]
|
|
149
214
|
function Signal:Wait()
|
|
150
215
|
local waitingCoroutine = coroutine.running()
|
|
151
216
|
local cn;
|
|
@@ -156,8 +221,17 @@ function Signal:Wait()
|
|
|
156
221
|
return coroutine.yield()
|
|
157
222
|
end
|
|
158
223
|
|
|
159
|
-
--
|
|
160
|
-
|
|
224
|
+
--[=[
|
|
225
|
+
Connect a new, one-time handler to the event. Returns a connection object that can be disconnected.
|
|
226
|
+
|
|
227
|
+
::: info
|
|
228
|
+
-- Implement Signal:Once() in terms of a connection which disconnects
|
|
229
|
+
-- itself before running the handler.
|
|
230
|
+
:::
|
|
231
|
+
|
|
232
|
+
@param fn (... T) -> () -- One-time function handler called when `:Fire(...)` is called
|
|
233
|
+
@return RBXScriptConnection
|
|
234
|
+
]=]
|
|
161
235
|
function Signal:Once(fn)
|
|
162
236
|
local cn;
|
|
163
237
|
cn = self:Connect(function(...)
|
|
@@ -169,6 +243,12 @@ function Signal:Once(fn)
|
|
|
169
243
|
return cn
|
|
170
244
|
end
|
|
171
245
|
|
|
246
|
+
--[=[
|
|
247
|
+
Alias for [DisconnectAll]
|
|
248
|
+
|
|
249
|
+
@function Destroy
|
|
250
|
+
@within Signal
|
|
251
|
+
]=]
|
|
172
252
|
Signal.Destroy = Signal.DisconnectAll
|
|
173
253
|
|
|
174
254
|
-- Make signal strict
|
package/src/Shared/Signal.lua
CHANGED
|
@@ -30,6 +30,14 @@
|
|
|
30
30
|
@class Signal
|
|
31
31
|
]=]
|
|
32
32
|
|
|
33
|
+
local USE_GOOD_SIGNAL_ONLY = true
|
|
34
|
+
|
|
35
|
+
if USE_GOOD_SIGNAL_ONLY then
|
|
36
|
+
local require = require(script.Parent.loader).load(script)
|
|
37
|
+
|
|
38
|
+
return require("GoodSignal")
|
|
39
|
+
end
|
|
40
|
+
|
|
33
41
|
local HttpService = game:GetService("HttpService")
|
|
34
42
|
|
|
35
43
|
local ENABLE_TRACEBACK = false
|