roblox-opencode 1.0.0 → 1.0.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/README.md +112 -122
- package/commands/setup-game.md +108 -108
- package/commands/sync-check.md +53 -53
- package/core/roblox-core.md +93 -93
- package/dist/server.js +189 -167
- package/package.json +35 -35
- package/skills/roblox-analytics/SKILL.md +277 -277
- package/skills/roblox-analytics/references/event-batcher.luau +75 -75
- package/skills/roblox-animation-vfx/SKILL.md +1325 -1325
- package/skills/roblox-architecture/SKILL.md +863 -863
- package/skills/roblox-architecture/references/combat-systems.md +1381 -1381
- package/skills/roblox-code-review/SKILL.md +686 -686
- package/skills/roblox-data/SKILL.md +889 -889
- package/skills/roblox-data/references/inventory-systems.md +1729 -1729
- package/skills/roblox-debug/SKILL.md +98 -98
- package/skills/roblox-gui/SKILL.md +1103 -1103
- package/skills/roblox-gui-fusion/SKILL.md +150 -150
- package/skills/roblox-gui-fusion/references/inventory.luau +427 -427
- package/skills/roblox-gui-fusion/references/settings-menu.luau +579 -579
- package/skills/roblox-gui-fusion/references/shop.luau +411 -411
- package/skills/roblox-luau-mastery/SKILL.md +1519 -1519
- package/skills/roblox-monetization/SKILL.md +1084 -1084
- package/skills/roblox-monetization/references/process-receipt.luau +131 -131
- package/skills/roblox-networking/SKILL.md +669 -669
- package/skills/roblox-networking/references/remote-validator.luau +193 -193
- package/skills/roblox-publish-checklist/SKILL.md +127 -127
- package/skills/roblox-runtime/SKILL.md +753 -753
- package/skills/roblox-sharp-edges/SKILL.md +294 -294
- package/skills/roblox-sync/SKILL.md +126 -126
- package/skills/roblox-testing/SKILL.md +943 -943
- package/skills/roblox-tooling/SKILL.md +149 -149
- package/vendor/LICENSES/ProfileStore-LICENSE +201 -201
- package/vendor/LICENSES/RbxUtil-LICENSE +7 -7
- package/vendor/LICENSES/promise-LICENSE +20 -20
- package/vendor/LICENSES/t-LICENSE +21 -21
- package/vendor/LICENSES/testez-LICENSE +200 -200
- package/vendor/README.md +83 -83
- package/vendor/fusion/Animation/ExternalTime.luau +83 -83
- package/vendor/fusion/Animation/Spring.luau +321 -321
- package/vendor/fusion/Animation/Stopwatch.luau +127 -127
- package/vendor/fusion/Animation/Tween.luau +187 -187
- package/vendor/fusion/Animation/getTweenDuration.luau +27 -27
- package/vendor/fusion/Animation/getTweenRatio.luau +47 -47
- package/vendor/fusion/Animation/lerpType.luau +163 -163
- package/vendor/fusion/Animation/packType.luau +99 -99
- package/vendor/fusion/Animation/springCoefficients.luau +80 -80
- package/vendor/fusion/Animation/unpackType.luau +102 -102
- package/vendor/fusion/Colour/Oklab.luau +70 -70
- package/vendor/fusion/Colour/sRGB.luau +54 -54
- package/vendor/fusion/External.luau +167 -167
- package/vendor/fusion/ExternalDebug.luau +69 -69
- package/vendor/fusion/Graph/Observer.luau +113 -113
- package/vendor/fusion/Graph/castToGraph.luau +28 -28
- package/vendor/fusion/Graph/change.luau +80 -80
- package/vendor/fusion/Graph/depend.luau +32 -32
- package/vendor/fusion/Graph/evaluate.luau +55 -55
- package/vendor/fusion/Instances/Attribute.luau +57 -57
- package/vendor/fusion/Instances/AttributeChange.luau +46 -46
- package/vendor/fusion/Instances/AttributeOut.luau +63 -63
- package/vendor/fusion/Instances/Child.luau +21 -21
- package/vendor/fusion/Instances/Children.luau +147 -147
- package/vendor/fusion/Instances/Hydrate.luau +32 -32
- package/vendor/fusion/Instances/New.luau +52 -52
- package/vendor/fusion/Instances/OnChange.luau +49 -49
- package/vendor/fusion/Instances/OnEvent.luau +53 -53
- package/vendor/fusion/Instances/Out.luau +69 -69
- package/vendor/fusion/Instances/applyInstanceProps.luau +148 -148
- package/vendor/fusion/Instances/defaultProps.luau +194 -194
- package/vendor/fusion/LICENSE +21 -21
- package/vendor/fusion/Logging/formatError.luau +48 -48
- package/vendor/fusion/Logging/messages.luau +51 -51
- package/vendor/fusion/Logging/parseError.luau +24 -24
- package/vendor/fusion/Memory/checkLifetime.luau +133 -133
- package/vendor/fusion/Memory/deriveScope.luau +23 -23
- package/vendor/fusion/Memory/deriveScopeImpl.luau +44 -44
- package/vendor/fusion/Memory/doCleanup.luau +78 -78
- package/vendor/fusion/Memory/innerScope.luau +33 -33
- package/vendor/fusion/Memory/legacyCleanup.luau +17 -17
- package/vendor/fusion/Memory/needsDestruction.luau +16 -16
- package/vendor/fusion/Memory/poisonScope.luau +33 -33
- package/vendor/fusion/Memory/scopePool.luau +54 -54
- package/vendor/fusion/Memory/scoped.luau +26 -26
- package/vendor/fusion/Memory/whichLivesLonger.luau +74 -74
- package/vendor/fusion/RobloxExternal.luau +97 -97
- package/vendor/fusion/State/Computed.luau +138 -138
- package/vendor/fusion/State/For/Disassembly.luau +210 -210
- package/vendor/fusion/State/For/ForTypes.luau +30 -30
- package/vendor/fusion/State/For/init.luau +109 -109
- package/vendor/fusion/State/ForKeys.luau +93 -93
- package/vendor/fusion/State/ForPairs.luau +96 -96
- package/vendor/fusion/State/ForValues.luau +93 -93
- package/vendor/fusion/State/Value.luau +87 -87
- package/vendor/fusion/State/castToState.luau +25 -25
- package/vendor/fusion/State/peek.luau +30 -30
- package/vendor/fusion/Types.luau +314 -314
- package/vendor/fusion/Utility/Contextual.luau +90 -90
- package/vendor/fusion/Utility/Safe.luau +22 -22
- package/vendor/fusion/Utility/isSimilar.luau +29 -29
- package/vendor/fusion/Utility/merge.luau +35 -35
- package/vendor/fusion/Utility/nameOf.luau +34 -34
- package/vendor/fusion/Utility/never.luau +13 -13
- package/vendor/fusion/Utility/nicknames.luau +10 -10
- package/vendor/fusion/Utility/xtypeof.luau +26 -26
- package/vendor/fusion/init.luau +82 -82
- package/vendor/profilestore/init.luau +2242 -2242
- package/vendor/promise/init.luau +1982 -1982
- package/vendor/rbxutil/buffer-util/Buffer.test.luau +25 -25
- package/vendor/rbxutil/buffer-util/BufferReader.luau +228 -228
- package/vendor/rbxutil/buffer-util/BufferWriter.luau +269 -269
- package/vendor/rbxutil/buffer-util/DataTypeBuffer.luau +223 -223
- package/vendor/rbxutil/buffer-util/Types.luau +60 -60
- package/vendor/rbxutil/buffer-util/index.d.ts +153 -153
- package/vendor/rbxutil/buffer-util/init.luau +41 -41
- package/vendor/rbxutil/buffer-util/package.json +16 -16
- package/vendor/rbxutil/buffer-util/wally.toml +9 -9
- package/vendor/rbxutil/comm/Client/ClientComm.luau +232 -232
- package/vendor/rbxutil/comm/Client/ClientRemoteProperty.luau +156 -156
- package/vendor/rbxutil/comm/Client/ClientRemoteSignal.luau +109 -109
- package/vendor/rbxutil/comm/Client/init.luau +135 -135
- package/vendor/rbxutil/comm/Server/RemoteProperty.luau +295 -295
- package/vendor/rbxutil/comm/Server/RemoteSignal.luau +211 -211
- package/vendor/rbxutil/comm/Server/ServerComm.luau +211 -211
- package/vendor/rbxutil/comm/Server/init.luau +140 -140
- package/vendor/rbxutil/comm/Types.luau +18 -18
- package/vendor/rbxutil/comm/Util.luau +27 -27
- package/vendor/rbxutil/comm/init.luau +35 -35
- package/vendor/rbxutil/comm/wally.toml +13 -13
- package/vendor/rbxutil/component/init.luau +759 -759
- package/vendor/rbxutil/component/init.test.luau +311 -311
- package/vendor/rbxutil/component/wally.toml +14 -14
- package/vendor/rbxutil/concur/init.luau +542 -542
- package/vendor/rbxutil/concur/init.test.luau +364 -364
- package/vendor/rbxutil/concur/wally.toml +8 -8
- package/vendor/rbxutil/enum-list/init.luau +101 -101
- package/vendor/rbxutil/enum-list/init.test.luau +91 -91
- package/vendor/rbxutil/enum-list/wally.toml +8 -8
- package/vendor/rbxutil/find/index.d.ts +20 -20
- package/vendor/rbxutil/find/init.luau +44 -44
- package/vendor/rbxutil/find/package.json +17 -17
- package/vendor/rbxutil/find/wally.toml +8 -8
- package/vendor/rbxutil/input/Gamepad.luau +559 -559
- package/vendor/rbxutil/input/Keyboard.luau +124 -124
- package/vendor/rbxutil/input/Mouse.luau +278 -278
- package/vendor/rbxutil/input/PreferredInput.luau +91 -91
- package/vendor/rbxutil/input/Touch.luau +120 -120
- package/vendor/rbxutil/input/init.luau +33 -33
- package/vendor/rbxutil/input/wally.toml +12 -12
- package/vendor/rbxutil/loader/index.d.ts +15 -15
- package/vendor/rbxutil/loader/init.luau +137 -137
- package/vendor/rbxutil/loader/wally.toml +8 -8
- package/vendor/rbxutil/log/index.d.ts +38 -38
- package/vendor/rbxutil/log/init.luau +746 -746
- package/vendor/rbxutil/log/wally.toml +8 -8
- package/vendor/rbxutil/net/init.luau +190 -190
- package/vendor/rbxutil/net/wally.toml +8 -8
- package/vendor/rbxutil/option/index.d.ts +44 -44
- package/vendor/rbxutil/option/init.luau +489 -489
- package/vendor/rbxutil/option/init.test.luau +342 -342
- package/vendor/rbxutil/option/wally.toml +8 -8
- package/vendor/rbxutil/pid/index.d.ts +53 -53
- package/vendor/rbxutil/pid/init.luau +195 -195
- package/vendor/rbxutil/pid/package.json +16 -16
- package/vendor/rbxutil/pid/wally.toml +9 -9
- package/vendor/rbxutil/quaternion/index.d.ts +117 -117
- package/vendor/rbxutil/quaternion/init.luau +570 -570
- package/vendor/rbxutil/quaternion/package.json +16 -16
- package/vendor/rbxutil/quaternion/wally.toml +9 -9
- package/vendor/rbxutil/query/index.d.ts +43 -43
- package/vendor/rbxutil/query/init.luau +117 -117
- package/vendor/rbxutil/query/package.json +18 -18
- package/vendor/rbxutil/query/wally.toml +9 -9
- package/vendor/rbxutil/sequent/index.d.ts +28 -28
- package/vendor/rbxutil/sequent/init.luau +340 -340
- package/vendor/rbxutil/sequent/package.json +16 -16
- package/vendor/rbxutil/sequent/wally.toml +9 -9
- package/vendor/rbxutil/ser/init.luau +175 -175
- package/vendor/rbxutil/ser/init.test.luau +50 -50
- package/vendor/rbxutil/ser/wally.toml +11 -11
- package/vendor/rbxutil/shake/index.d.ts +36 -36
- package/vendor/rbxutil/shake/init.luau +532 -532
- package/vendor/rbxutil/shake/init.test.luau +267 -267
- package/vendor/rbxutil/shake/package.json +16 -16
- package/vendor/rbxutil/shake/wally.toml +9 -9
- package/vendor/rbxutil/signal/index.d.ts +100 -100
- package/vendor/rbxutil/signal/init.luau +432 -432
- package/vendor/rbxutil/signal/init.test.luau +190 -190
- package/vendor/rbxutil/signal/package.json +17 -17
- package/vendor/rbxutil/signal/wally.toml +9 -9
- package/vendor/rbxutil/silo/TableWatcher.luau +65 -65
- package/vendor/rbxutil/silo/Util.luau +55 -55
- package/vendor/rbxutil/silo/init.luau +338 -338
- package/vendor/rbxutil/silo/init.test.luau +215 -215
- package/vendor/rbxutil/silo/wally.toml +8 -8
- package/vendor/rbxutil/spring/index.d.ts +40 -40
- package/vendor/rbxutil/spring/init.luau +97 -97
- package/vendor/rbxutil/spring/package.json +17 -17
- package/vendor/rbxutil/spring/wally.toml +8 -8
- package/vendor/rbxutil/stream/index.d.ts +88 -88
- package/vendor/rbxutil/stream/init.luau +597 -597
- package/vendor/rbxutil/stream/package.json +18 -18
- package/vendor/rbxutil/stream/wally.toml +9 -9
- package/vendor/rbxutil/streamable/Streamable.luau +202 -202
- package/vendor/rbxutil/streamable/StreamableUtil.luau +80 -80
- package/vendor/rbxutil/streamable/init.luau +8 -8
- package/vendor/rbxutil/streamable/wally.toml +12 -12
- package/vendor/rbxutil/symbol/init.luau +56 -56
- package/vendor/rbxutil/symbol/init.test.luau +37 -37
- package/vendor/rbxutil/symbol/wally.toml +8 -8
- package/vendor/rbxutil/table-util/init.luau +938 -938
- package/vendor/rbxutil/table-util/init.test.luau +439 -439
- package/vendor/rbxutil/task-queue/index.d.ts +27 -27
- package/vendor/rbxutil/task-queue/init.luau +97 -97
- package/vendor/rbxutil/task-queue/wally.toml +8 -8
- package/vendor/rbxutil/timer/index.d.ts +81 -81
- package/vendor/rbxutil/timer/init.luau +249 -249
- package/vendor/rbxutil/timer/init.test.luau +73 -73
- package/vendor/rbxutil/timer/wally.toml +11 -11
- package/vendor/rbxutil/tree/index.d.ts +15 -15
- package/vendor/rbxutil/tree/init.luau +137 -137
- package/vendor/rbxutil/tree/wally.toml +8 -8
- package/vendor/rbxutil/trove/index.d.ts +46 -46
- package/vendor/rbxutil/trove/init.luau +787 -787
- package/vendor/rbxutil/trove/init.test.luau +203 -203
- package/vendor/rbxutil/trove/wally.toml +8 -8
- package/vendor/rbxutil/typed-remote/init.luau +196 -196
- package/vendor/rbxutil/typed-remote/wally.toml +8 -8
- package/vendor/rbxutil/wait-for/index.d.ts +17 -17
- package/vendor/rbxutil/wait-for/init.luau +257 -257
- package/vendor/rbxutil/wait-for/init.test.luau +182 -182
- package/vendor/rbxutil/wait-for/wally.toml +11 -11
- package/vendor/t/t.lua +1350 -1350
- package/vendor/testez/Context.lua +26 -26
- package/vendor/testez/Expectation.lua +311 -311
- package/vendor/testez/ExpectationContext.lua +38 -38
- package/vendor/testez/LifecycleHooks.lua +89 -89
- package/vendor/testez/Reporters/TeamCityReporter.lua +101 -101
- package/vendor/testez/Reporters/TextReporter.lua +105 -105
- package/vendor/testez/Reporters/TextReporterQuiet.lua +96 -96
- package/vendor/testez/TestBootstrap.lua +146 -146
- package/vendor/testez/TestEnum.lua +27 -27
- package/vendor/testez/TestPlan.lua +304 -304
- package/vendor/testez/TestPlanner.lua +39 -39
- package/vendor/testez/TestResults.lua +111 -111
- package/vendor/testez/TestRunner.lua +188 -188
- package/vendor/testez/TestSession.lua +243 -243
- package/vendor/testez/init.lua +39 -39
|
@@ -1,190 +1,190 @@
|
|
|
1
|
-
local ServerScriptService = game:GetService("ServerScriptService")
|
|
2
|
-
|
|
3
|
-
local Test = require(ServerScriptService.TestRunner.Test)
|
|
4
|
-
|
|
5
|
-
local function AwaitCondition(predicate: () -> boolean, timeout: number?)
|
|
6
|
-
local start = os.clock()
|
|
7
|
-
timeout = (timeout or 10)
|
|
8
|
-
while true do
|
|
9
|
-
if predicate() then
|
|
10
|
-
return true
|
|
11
|
-
end
|
|
12
|
-
if (os.clock() - start) > timeout then
|
|
13
|
-
return false
|
|
14
|
-
end
|
|
15
|
-
task.wait()
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
return function(ctx: Test.TestContext)
|
|
20
|
-
local Signal = require(script.Parent)
|
|
21
|
-
|
|
22
|
-
local signal
|
|
23
|
-
|
|
24
|
-
local function NumConns(sig)
|
|
25
|
-
sig = sig or signal
|
|
26
|
-
return #sig:GetConnections()
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
ctx:BeforeEach(function()
|
|
30
|
-
signal = Signal.new()
|
|
31
|
-
end)
|
|
32
|
-
|
|
33
|
-
ctx:AfterEach(function()
|
|
34
|
-
signal:Destroy()
|
|
35
|
-
end)
|
|
36
|
-
|
|
37
|
-
ctx:Describe("Constructor", function()
|
|
38
|
-
ctx:Test("should create a new signal and fire it", function()
|
|
39
|
-
ctx:Expect(Signal.Is(signal)):ToBe(true)
|
|
40
|
-
task.defer(function()
|
|
41
|
-
signal:Fire(10, 20)
|
|
42
|
-
end)
|
|
43
|
-
local n1, n2 = signal:Wait()
|
|
44
|
-
ctx:Expect(n1):ToBe(10)
|
|
45
|
-
ctx:Expect(n2):ToBe(20)
|
|
46
|
-
end)
|
|
47
|
-
|
|
48
|
-
ctx:Test("should create a proxy signal and connect to it", function()
|
|
49
|
-
local signalWrap = Signal.Wrap(game:GetService("RunService").Heartbeat)
|
|
50
|
-
ctx:Expect(Signal.Is(signalWrap)):ToBe(true)
|
|
51
|
-
local fired = false
|
|
52
|
-
signalWrap:Connect(function()
|
|
53
|
-
fired = true
|
|
54
|
-
end)
|
|
55
|
-
ctx:Expect(AwaitCondition(function()
|
|
56
|
-
return fired
|
|
57
|
-
end, 2)):ToBe(true)
|
|
58
|
-
signalWrap:Destroy()
|
|
59
|
-
end)
|
|
60
|
-
end)
|
|
61
|
-
|
|
62
|
-
ctx:Describe("FireDeferred", function()
|
|
63
|
-
ctx:Test("should be able to fire primitive argument", function()
|
|
64
|
-
local send = 10
|
|
65
|
-
local value
|
|
66
|
-
signal:Connect(function(v)
|
|
67
|
-
value = v
|
|
68
|
-
end)
|
|
69
|
-
signal:FireDeferred(send)
|
|
70
|
-
ctx:Expect(AwaitCondition(function()
|
|
71
|
-
return (send == value)
|
|
72
|
-
end, 1)):ToBe(true)
|
|
73
|
-
end)
|
|
74
|
-
|
|
75
|
-
ctx:Test("should be able to fire a reference based argument", function()
|
|
76
|
-
local send = { 10, 20 }
|
|
77
|
-
local value
|
|
78
|
-
signal:Connect(function(v)
|
|
79
|
-
value = v
|
|
80
|
-
end)
|
|
81
|
-
signal:FireDeferred(send)
|
|
82
|
-
ctx:Expect(AwaitCondition(function()
|
|
83
|
-
return (send == value)
|
|
84
|
-
end, 1)):ToBe(true)
|
|
85
|
-
end)
|
|
86
|
-
end)
|
|
87
|
-
|
|
88
|
-
ctx:Describe("Fire", function()
|
|
89
|
-
ctx:Test("should be able to fire primitive argument", function()
|
|
90
|
-
local send = 10
|
|
91
|
-
local value
|
|
92
|
-
signal:Connect(function(v)
|
|
93
|
-
value = v
|
|
94
|
-
end)
|
|
95
|
-
signal:Fire(send)
|
|
96
|
-
ctx:Expect(value):ToBe(send)
|
|
97
|
-
end)
|
|
98
|
-
|
|
99
|
-
ctx:Test("should be able to fire a reference based argument", function()
|
|
100
|
-
local send = { 10, 20 }
|
|
101
|
-
local value
|
|
102
|
-
signal:Connect(function(v)
|
|
103
|
-
value = v
|
|
104
|
-
end)
|
|
105
|
-
signal:Fire(send)
|
|
106
|
-
ctx:Expect(value):ToBe(send)
|
|
107
|
-
end)
|
|
108
|
-
end)
|
|
109
|
-
|
|
110
|
-
ctx:Describe("ConnectOnce", function()
|
|
111
|
-
ctx:Test("should only capture first fire", function()
|
|
112
|
-
local value
|
|
113
|
-
local c = signal:ConnectOnce(function(v)
|
|
114
|
-
value = v
|
|
115
|
-
end)
|
|
116
|
-
ctx:Expect(c.Connected):ToBe(true)
|
|
117
|
-
signal:Fire(10)
|
|
118
|
-
ctx:Expect(c.Connected):ToBe(false)
|
|
119
|
-
signal:Fire(20)
|
|
120
|
-
ctx:Expect(value):ToBe(10)
|
|
121
|
-
end)
|
|
122
|
-
end)
|
|
123
|
-
|
|
124
|
-
ctx:Describe("Wait", function()
|
|
125
|
-
ctx:Test("should be able to wait for a signal to fire", function()
|
|
126
|
-
task.defer(function()
|
|
127
|
-
signal:Fire(10, 20, 30)
|
|
128
|
-
end)
|
|
129
|
-
local n1, n2, n3 = signal:Wait()
|
|
130
|
-
ctx:Expect(n1):ToBe(10)
|
|
131
|
-
ctx:Expect(n2):ToBe(20)
|
|
132
|
-
ctx:Expect(n3):ToBe(30)
|
|
133
|
-
end)
|
|
134
|
-
end)
|
|
135
|
-
|
|
136
|
-
ctx:Describe("DisconnectAll", function()
|
|
137
|
-
ctx:Test("should disconnect all connections", function()
|
|
138
|
-
signal:Connect(function() end)
|
|
139
|
-
signal:Connect(function() end)
|
|
140
|
-
ctx:Expect(NumConns()):ToBe(2)
|
|
141
|
-
signal:DisconnectAll()
|
|
142
|
-
ctx:Expect(NumConns()):ToBe(0)
|
|
143
|
-
end)
|
|
144
|
-
end)
|
|
145
|
-
|
|
146
|
-
ctx:Describe("Disconnect", function()
|
|
147
|
-
ctx:Test("should disconnect connection", function()
|
|
148
|
-
local con = signal:Connect(function() end)
|
|
149
|
-
ctx:Expect(NumConns()):ToBe(1)
|
|
150
|
-
con:Disconnect()
|
|
151
|
-
ctx:Expect(NumConns()):ToBe(0)
|
|
152
|
-
end)
|
|
153
|
-
|
|
154
|
-
ctx:Test("should still work if connections disconnected while firing", function()
|
|
155
|
-
local a = 0
|
|
156
|
-
local c
|
|
157
|
-
signal:Connect(function()
|
|
158
|
-
a += 1
|
|
159
|
-
end)
|
|
160
|
-
c = signal:Connect(function()
|
|
161
|
-
c:Disconnect()
|
|
162
|
-
a += 1
|
|
163
|
-
end)
|
|
164
|
-
signal:Connect(function()
|
|
165
|
-
a += 1
|
|
166
|
-
end)
|
|
167
|
-
signal:Fire()
|
|
168
|
-
ctx:Expect(a):ToBe(3)
|
|
169
|
-
end)
|
|
170
|
-
|
|
171
|
-
ctx:Test("should still work if connections disconnected while firing deferred", function()
|
|
172
|
-
local a = 0
|
|
173
|
-
local c
|
|
174
|
-
signal:Connect(function()
|
|
175
|
-
a += 1
|
|
176
|
-
end)
|
|
177
|
-
c = signal:Connect(function()
|
|
178
|
-
c:Disconnect()
|
|
179
|
-
a += 1
|
|
180
|
-
end)
|
|
181
|
-
signal:Connect(function()
|
|
182
|
-
a += 1
|
|
183
|
-
end)
|
|
184
|
-
signal:FireDeferred()
|
|
185
|
-
ctx:Expect(AwaitCondition(function()
|
|
186
|
-
return a == 3
|
|
187
|
-
end)):ToBe(true)
|
|
188
|
-
end)
|
|
189
|
-
end)
|
|
190
|
-
end
|
|
1
|
+
local ServerScriptService = game:GetService("ServerScriptService")
|
|
2
|
+
|
|
3
|
+
local Test = require(ServerScriptService.TestRunner.Test)
|
|
4
|
+
|
|
5
|
+
local function AwaitCondition(predicate: () -> boolean, timeout: number?)
|
|
6
|
+
local start = os.clock()
|
|
7
|
+
timeout = (timeout or 10)
|
|
8
|
+
while true do
|
|
9
|
+
if predicate() then
|
|
10
|
+
return true
|
|
11
|
+
end
|
|
12
|
+
if (os.clock() - start) > timeout then
|
|
13
|
+
return false
|
|
14
|
+
end
|
|
15
|
+
task.wait()
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
return function(ctx: Test.TestContext)
|
|
20
|
+
local Signal = require(script.Parent)
|
|
21
|
+
|
|
22
|
+
local signal
|
|
23
|
+
|
|
24
|
+
local function NumConns(sig)
|
|
25
|
+
sig = sig or signal
|
|
26
|
+
return #sig:GetConnections()
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
ctx:BeforeEach(function()
|
|
30
|
+
signal = Signal.new()
|
|
31
|
+
end)
|
|
32
|
+
|
|
33
|
+
ctx:AfterEach(function()
|
|
34
|
+
signal:Destroy()
|
|
35
|
+
end)
|
|
36
|
+
|
|
37
|
+
ctx:Describe("Constructor", function()
|
|
38
|
+
ctx:Test("should create a new signal and fire it", function()
|
|
39
|
+
ctx:Expect(Signal.Is(signal)):ToBe(true)
|
|
40
|
+
task.defer(function()
|
|
41
|
+
signal:Fire(10, 20)
|
|
42
|
+
end)
|
|
43
|
+
local n1, n2 = signal:Wait()
|
|
44
|
+
ctx:Expect(n1):ToBe(10)
|
|
45
|
+
ctx:Expect(n2):ToBe(20)
|
|
46
|
+
end)
|
|
47
|
+
|
|
48
|
+
ctx:Test("should create a proxy signal and connect to it", function()
|
|
49
|
+
local signalWrap = Signal.Wrap(game:GetService("RunService").Heartbeat)
|
|
50
|
+
ctx:Expect(Signal.Is(signalWrap)):ToBe(true)
|
|
51
|
+
local fired = false
|
|
52
|
+
signalWrap:Connect(function()
|
|
53
|
+
fired = true
|
|
54
|
+
end)
|
|
55
|
+
ctx:Expect(AwaitCondition(function()
|
|
56
|
+
return fired
|
|
57
|
+
end, 2)):ToBe(true)
|
|
58
|
+
signalWrap:Destroy()
|
|
59
|
+
end)
|
|
60
|
+
end)
|
|
61
|
+
|
|
62
|
+
ctx:Describe("FireDeferred", function()
|
|
63
|
+
ctx:Test("should be able to fire primitive argument", function()
|
|
64
|
+
local send = 10
|
|
65
|
+
local value
|
|
66
|
+
signal:Connect(function(v)
|
|
67
|
+
value = v
|
|
68
|
+
end)
|
|
69
|
+
signal:FireDeferred(send)
|
|
70
|
+
ctx:Expect(AwaitCondition(function()
|
|
71
|
+
return (send == value)
|
|
72
|
+
end, 1)):ToBe(true)
|
|
73
|
+
end)
|
|
74
|
+
|
|
75
|
+
ctx:Test("should be able to fire a reference based argument", function()
|
|
76
|
+
local send = { 10, 20 }
|
|
77
|
+
local value
|
|
78
|
+
signal:Connect(function(v)
|
|
79
|
+
value = v
|
|
80
|
+
end)
|
|
81
|
+
signal:FireDeferred(send)
|
|
82
|
+
ctx:Expect(AwaitCondition(function()
|
|
83
|
+
return (send == value)
|
|
84
|
+
end, 1)):ToBe(true)
|
|
85
|
+
end)
|
|
86
|
+
end)
|
|
87
|
+
|
|
88
|
+
ctx:Describe("Fire", function()
|
|
89
|
+
ctx:Test("should be able to fire primitive argument", function()
|
|
90
|
+
local send = 10
|
|
91
|
+
local value
|
|
92
|
+
signal:Connect(function(v)
|
|
93
|
+
value = v
|
|
94
|
+
end)
|
|
95
|
+
signal:Fire(send)
|
|
96
|
+
ctx:Expect(value):ToBe(send)
|
|
97
|
+
end)
|
|
98
|
+
|
|
99
|
+
ctx:Test("should be able to fire a reference based argument", function()
|
|
100
|
+
local send = { 10, 20 }
|
|
101
|
+
local value
|
|
102
|
+
signal:Connect(function(v)
|
|
103
|
+
value = v
|
|
104
|
+
end)
|
|
105
|
+
signal:Fire(send)
|
|
106
|
+
ctx:Expect(value):ToBe(send)
|
|
107
|
+
end)
|
|
108
|
+
end)
|
|
109
|
+
|
|
110
|
+
ctx:Describe("ConnectOnce", function()
|
|
111
|
+
ctx:Test("should only capture first fire", function()
|
|
112
|
+
local value
|
|
113
|
+
local c = signal:ConnectOnce(function(v)
|
|
114
|
+
value = v
|
|
115
|
+
end)
|
|
116
|
+
ctx:Expect(c.Connected):ToBe(true)
|
|
117
|
+
signal:Fire(10)
|
|
118
|
+
ctx:Expect(c.Connected):ToBe(false)
|
|
119
|
+
signal:Fire(20)
|
|
120
|
+
ctx:Expect(value):ToBe(10)
|
|
121
|
+
end)
|
|
122
|
+
end)
|
|
123
|
+
|
|
124
|
+
ctx:Describe("Wait", function()
|
|
125
|
+
ctx:Test("should be able to wait for a signal to fire", function()
|
|
126
|
+
task.defer(function()
|
|
127
|
+
signal:Fire(10, 20, 30)
|
|
128
|
+
end)
|
|
129
|
+
local n1, n2, n3 = signal:Wait()
|
|
130
|
+
ctx:Expect(n1):ToBe(10)
|
|
131
|
+
ctx:Expect(n2):ToBe(20)
|
|
132
|
+
ctx:Expect(n3):ToBe(30)
|
|
133
|
+
end)
|
|
134
|
+
end)
|
|
135
|
+
|
|
136
|
+
ctx:Describe("DisconnectAll", function()
|
|
137
|
+
ctx:Test("should disconnect all connections", function()
|
|
138
|
+
signal:Connect(function() end)
|
|
139
|
+
signal:Connect(function() end)
|
|
140
|
+
ctx:Expect(NumConns()):ToBe(2)
|
|
141
|
+
signal:DisconnectAll()
|
|
142
|
+
ctx:Expect(NumConns()):ToBe(0)
|
|
143
|
+
end)
|
|
144
|
+
end)
|
|
145
|
+
|
|
146
|
+
ctx:Describe("Disconnect", function()
|
|
147
|
+
ctx:Test("should disconnect connection", function()
|
|
148
|
+
local con = signal:Connect(function() end)
|
|
149
|
+
ctx:Expect(NumConns()):ToBe(1)
|
|
150
|
+
con:Disconnect()
|
|
151
|
+
ctx:Expect(NumConns()):ToBe(0)
|
|
152
|
+
end)
|
|
153
|
+
|
|
154
|
+
ctx:Test("should still work if connections disconnected while firing", function()
|
|
155
|
+
local a = 0
|
|
156
|
+
local c
|
|
157
|
+
signal:Connect(function()
|
|
158
|
+
a += 1
|
|
159
|
+
end)
|
|
160
|
+
c = signal:Connect(function()
|
|
161
|
+
c:Disconnect()
|
|
162
|
+
a += 1
|
|
163
|
+
end)
|
|
164
|
+
signal:Connect(function()
|
|
165
|
+
a += 1
|
|
166
|
+
end)
|
|
167
|
+
signal:Fire()
|
|
168
|
+
ctx:Expect(a):ToBe(3)
|
|
169
|
+
end)
|
|
170
|
+
|
|
171
|
+
ctx:Test("should still work if connections disconnected while firing deferred", function()
|
|
172
|
+
local a = 0
|
|
173
|
+
local c
|
|
174
|
+
signal:Connect(function()
|
|
175
|
+
a += 1
|
|
176
|
+
end)
|
|
177
|
+
c = signal:Connect(function()
|
|
178
|
+
c:Disconnect()
|
|
179
|
+
a += 1
|
|
180
|
+
end)
|
|
181
|
+
signal:Connect(function()
|
|
182
|
+
a += 1
|
|
183
|
+
end)
|
|
184
|
+
signal:FireDeferred()
|
|
185
|
+
ctx:Expect(AwaitCondition(function()
|
|
186
|
+
return a == 3
|
|
187
|
+
end)):ToBe(true)
|
|
188
|
+
end)
|
|
189
|
+
end)
|
|
190
|
+
end
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@rbxutil/signal",
|
|
3
|
-
"version": "2.0.3",
|
|
4
|
-
"main": "init.luau",
|
|
5
|
-
"repository": "github:Sleitnick/RbxUtil",
|
|
6
|
-
"license": "MIT",
|
|
7
|
-
"types": "index.d.ts",
|
|
8
|
-
"files": [
|
|
9
|
-
"./*",
|
|
10
|
-
"!*.toml",
|
|
11
|
-
"!*.json",
|
|
12
|
-
"!*.test.luau"
|
|
13
|
-
],
|
|
14
|
-
"publishConfig": {
|
|
15
|
-
"access": "public"
|
|
16
|
-
}
|
|
17
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@rbxutil/signal",
|
|
3
|
+
"version": "2.0.3",
|
|
4
|
+
"main": "init.luau",
|
|
5
|
+
"repository": "github:Sleitnick/RbxUtil",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"types": "index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"./*",
|
|
10
|
+
"!*.toml",
|
|
11
|
+
"!*.json",
|
|
12
|
+
"!*.test.luau"
|
|
13
|
+
],
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"access": "public"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
[package]
|
|
2
|
-
name = "sleitnick/signal"
|
|
3
|
-
description = "Signal class"
|
|
4
|
-
version = "2.0.3"
|
|
5
|
-
license = "MIT"
|
|
6
|
-
authors = ["Stephen Leitnick"]
|
|
7
|
-
registry = "https://github.com/UpliftGames/wally-index"
|
|
8
|
-
realm = "shared"
|
|
9
|
-
exclude = ["node_modules", "package.json", "**/*.ts"]
|
|
1
|
+
[package]
|
|
2
|
+
name = "sleitnick/signal"
|
|
3
|
+
description = "Signal class"
|
|
4
|
+
version = "2.0.3"
|
|
5
|
+
license = "MIT"
|
|
6
|
+
authors = ["Stephen Leitnick"]
|
|
7
|
+
registry = "https://github.com/UpliftGames/wally-index"
|
|
8
|
+
realm = "shared"
|
|
9
|
+
exclude = ["node_modules", "package.json", "**/*.ts"]
|
|
@@ -1,65 +1,65 @@
|
|
|
1
|
-
--!strict
|
|
2
|
-
|
|
3
|
-
-- TableWatcher
|
|
4
|
-
-- Stephen Leitnick
|
|
5
|
-
-- April 29, 2022
|
|
6
|
-
|
|
7
|
-
type AnyTable = { [any]: any }
|
|
8
|
-
|
|
9
|
-
type Watcher = {
|
|
10
|
-
Changes: AnyTable,
|
|
11
|
-
Tbl: AnyTable,
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
local Util = require(script.Parent.Util)
|
|
15
|
-
|
|
16
|
-
local watchers: { [TableWatcher]: Watcher } = {}
|
|
17
|
-
setmetatable(watchers, { __mode = "k" })
|
|
18
|
-
|
|
19
|
-
local WatcherMt = {}
|
|
20
|
-
|
|
21
|
-
function WatcherMt:__index(index)
|
|
22
|
-
local w = watchers[self]
|
|
23
|
-
local c = w.Changes[index]
|
|
24
|
-
if c ~= nil then
|
|
25
|
-
if c == Util.None then
|
|
26
|
-
return nil
|
|
27
|
-
else
|
|
28
|
-
return c
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
return w.Tbl[index]
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
function WatcherMt:__newindex(index, value)
|
|
35
|
-
local w = watchers[self]
|
|
36
|
-
if w.Tbl[index] == value then
|
|
37
|
-
return
|
|
38
|
-
end
|
|
39
|
-
if value == nil then
|
|
40
|
-
w.Changes[index] = Util.None
|
|
41
|
-
else
|
|
42
|
-
w.Changes[index] = value
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
function WatcherMt:__call()
|
|
47
|
-
local w = watchers[self]
|
|
48
|
-
if next(w.Changes) == nil then
|
|
49
|
-
return w.Tbl
|
|
50
|
-
end
|
|
51
|
-
return Util.Extend(w.Tbl, w.Changes)
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
local function TableWatcher(t: AnyTable): TableWatcher
|
|
55
|
-
local watcher = setmetatable({}, WatcherMt)
|
|
56
|
-
watchers[watcher] = {
|
|
57
|
-
Changes = {},
|
|
58
|
-
Tbl = t,
|
|
59
|
-
}
|
|
60
|
-
return watcher
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
type TableWatcher = typeof(setmetatable({}, WatcherMt))
|
|
64
|
-
|
|
65
|
-
return TableWatcher
|
|
1
|
+
--!strict
|
|
2
|
+
|
|
3
|
+
-- TableWatcher
|
|
4
|
+
-- Stephen Leitnick
|
|
5
|
+
-- April 29, 2022
|
|
6
|
+
|
|
7
|
+
type AnyTable = { [any]: any }
|
|
8
|
+
|
|
9
|
+
type Watcher = {
|
|
10
|
+
Changes: AnyTable,
|
|
11
|
+
Tbl: AnyTable,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
local Util = require(script.Parent.Util)
|
|
15
|
+
|
|
16
|
+
local watchers: { [TableWatcher]: Watcher } = {}
|
|
17
|
+
setmetatable(watchers, { __mode = "k" })
|
|
18
|
+
|
|
19
|
+
local WatcherMt = {}
|
|
20
|
+
|
|
21
|
+
function WatcherMt:__index(index)
|
|
22
|
+
local w = watchers[self]
|
|
23
|
+
local c = w.Changes[index]
|
|
24
|
+
if c ~= nil then
|
|
25
|
+
if c == Util.None then
|
|
26
|
+
return nil
|
|
27
|
+
else
|
|
28
|
+
return c
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
return w.Tbl[index]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
function WatcherMt:__newindex(index, value)
|
|
35
|
+
local w = watchers[self]
|
|
36
|
+
if w.Tbl[index] == value then
|
|
37
|
+
return
|
|
38
|
+
end
|
|
39
|
+
if value == nil then
|
|
40
|
+
w.Changes[index] = Util.None
|
|
41
|
+
else
|
|
42
|
+
w.Changes[index] = value
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
function WatcherMt:__call()
|
|
47
|
+
local w = watchers[self]
|
|
48
|
+
if next(w.Changes) == nil then
|
|
49
|
+
return w.Tbl
|
|
50
|
+
end
|
|
51
|
+
return Util.Extend(w.Tbl, w.Changes)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
local function TableWatcher(t: AnyTable): TableWatcher
|
|
55
|
+
local watcher = setmetatable({}, WatcherMt)
|
|
56
|
+
watchers[watcher] = {
|
|
57
|
+
Changes = {},
|
|
58
|
+
Tbl = t,
|
|
59
|
+
}
|
|
60
|
+
return watcher
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
type TableWatcher = typeof(setmetatable({}, WatcherMt))
|
|
64
|
+
|
|
65
|
+
return TableWatcher
|
|
@@ -1,55 +1,55 @@
|
|
|
1
|
-
--!strict
|
|
2
|
-
|
|
3
|
-
-- Util
|
|
4
|
-
-- Stephen Leitnick
|
|
5
|
-
-- April 29, 2022
|
|
6
|
-
|
|
7
|
-
type AnyTable = { [any]: any }
|
|
8
|
-
|
|
9
|
-
local Util = {}
|
|
10
|
-
|
|
11
|
-
Util.None = newproxy()
|
|
12
|
-
|
|
13
|
-
-- Recursive table freeze.
|
|
14
|
-
function Util.DeepFreeze<T>(tbl: AnyTable): AnyTable
|
|
15
|
-
table.freeze(tbl)
|
|
16
|
-
for _, v in tbl do
|
|
17
|
-
if type(v) == "table" then
|
|
18
|
-
Util.DeepFreeze(v)
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
return tbl
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
-- Recursive table copy.
|
|
25
|
-
function Util.DeepCopy<T>(tbl: AnyTable): AnyTable
|
|
26
|
-
local newTbl = table.clone(tbl)
|
|
27
|
-
for k, v in newTbl do
|
|
28
|
-
if type(v) == "table" then
|
|
29
|
-
newTbl[k] = Util.DeepCopy(v)
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
return newTbl
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
-- Extends one table with another.
|
|
36
|
-
-- Similar to the spread operator in JavaScript.
|
|
37
|
-
function Util.Extend(original: AnyTable, extension: AnyTable): AnyTable
|
|
38
|
-
local t = Util.DeepCopy(original)
|
|
39
|
-
for k, v in extension do
|
|
40
|
-
if type(v) == "table" then
|
|
41
|
-
if type(original[k]) == "table" then
|
|
42
|
-
t[k] = Util.Extend(original[k], v)
|
|
43
|
-
else
|
|
44
|
-
t[k] = Util.DeepCopy(v)
|
|
45
|
-
end
|
|
46
|
-
elseif v == Util.None then
|
|
47
|
-
t[k] = nil
|
|
48
|
-
else
|
|
49
|
-
t[k] = v
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
return t
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
return Util
|
|
1
|
+
--!strict
|
|
2
|
+
|
|
3
|
+
-- Util
|
|
4
|
+
-- Stephen Leitnick
|
|
5
|
+
-- April 29, 2022
|
|
6
|
+
|
|
7
|
+
type AnyTable = { [any]: any }
|
|
8
|
+
|
|
9
|
+
local Util = {}
|
|
10
|
+
|
|
11
|
+
Util.None = newproxy()
|
|
12
|
+
|
|
13
|
+
-- Recursive table freeze.
|
|
14
|
+
function Util.DeepFreeze<T>(tbl: AnyTable): AnyTable
|
|
15
|
+
table.freeze(tbl)
|
|
16
|
+
for _, v in tbl do
|
|
17
|
+
if type(v) == "table" then
|
|
18
|
+
Util.DeepFreeze(v)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
return tbl
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
-- Recursive table copy.
|
|
25
|
+
function Util.DeepCopy<T>(tbl: AnyTable): AnyTable
|
|
26
|
+
local newTbl = table.clone(tbl)
|
|
27
|
+
for k, v in newTbl do
|
|
28
|
+
if type(v) == "table" then
|
|
29
|
+
newTbl[k] = Util.DeepCopy(v)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
return newTbl
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
-- Extends one table with another.
|
|
36
|
+
-- Similar to the spread operator in JavaScript.
|
|
37
|
+
function Util.Extend(original: AnyTable, extension: AnyTable): AnyTable
|
|
38
|
+
local t = Util.DeepCopy(original)
|
|
39
|
+
for k, v in extension do
|
|
40
|
+
if type(v) == "table" then
|
|
41
|
+
if type(original[k]) == "table" then
|
|
42
|
+
t[k] = Util.Extend(original[k], v)
|
|
43
|
+
else
|
|
44
|
+
t[k] = Util.DeepCopy(v)
|
|
45
|
+
end
|
|
46
|
+
elseif v == Util.None then
|
|
47
|
+
t[k] = nil
|
|
48
|
+
else
|
|
49
|
+
t[k] = v
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
return t
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
return Util
|