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.
Files changed (246) hide show
  1. package/README.md +112 -122
  2. package/commands/setup-game.md +108 -108
  3. package/commands/sync-check.md +53 -53
  4. package/core/roblox-core.md +93 -93
  5. package/dist/server.js +189 -167
  6. package/package.json +35 -35
  7. package/skills/roblox-analytics/SKILL.md +277 -277
  8. package/skills/roblox-analytics/references/event-batcher.luau +75 -75
  9. package/skills/roblox-animation-vfx/SKILL.md +1325 -1325
  10. package/skills/roblox-architecture/SKILL.md +863 -863
  11. package/skills/roblox-architecture/references/combat-systems.md +1381 -1381
  12. package/skills/roblox-code-review/SKILL.md +686 -686
  13. package/skills/roblox-data/SKILL.md +889 -889
  14. package/skills/roblox-data/references/inventory-systems.md +1729 -1729
  15. package/skills/roblox-debug/SKILL.md +98 -98
  16. package/skills/roblox-gui/SKILL.md +1103 -1103
  17. package/skills/roblox-gui-fusion/SKILL.md +150 -150
  18. package/skills/roblox-gui-fusion/references/inventory.luau +427 -427
  19. package/skills/roblox-gui-fusion/references/settings-menu.luau +579 -579
  20. package/skills/roblox-gui-fusion/references/shop.luau +411 -411
  21. package/skills/roblox-luau-mastery/SKILL.md +1519 -1519
  22. package/skills/roblox-monetization/SKILL.md +1084 -1084
  23. package/skills/roblox-monetization/references/process-receipt.luau +131 -131
  24. package/skills/roblox-networking/SKILL.md +669 -669
  25. package/skills/roblox-networking/references/remote-validator.luau +193 -193
  26. package/skills/roblox-publish-checklist/SKILL.md +127 -127
  27. package/skills/roblox-runtime/SKILL.md +753 -753
  28. package/skills/roblox-sharp-edges/SKILL.md +294 -294
  29. package/skills/roblox-sync/SKILL.md +126 -126
  30. package/skills/roblox-testing/SKILL.md +943 -943
  31. package/skills/roblox-tooling/SKILL.md +149 -149
  32. package/vendor/LICENSES/ProfileStore-LICENSE +201 -201
  33. package/vendor/LICENSES/RbxUtil-LICENSE +7 -7
  34. package/vendor/LICENSES/promise-LICENSE +20 -20
  35. package/vendor/LICENSES/t-LICENSE +21 -21
  36. package/vendor/LICENSES/testez-LICENSE +200 -200
  37. package/vendor/README.md +83 -83
  38. package/vendor/fusion/Animation/ExternalTime.luau +83 -83
  39. package/vendor/fusion/Animation/Spring.luau +321 -321
  40. package/vendor/fusion/Animation/Stopwatch.luau +127 -127
  41. package/vendor/fusion/Animation/Tween.luau +187 -187
  42. package/vendor/fusion/Animation/getTweenDuration.luau +27 -27
  43. package/vendor/fusion/Animation/getTweenRatio.luau +47 -47
  44. package/vendor/fusion/Animation/lerpType.luau +163 -163
  45. package/vendor/fusion/Animation/packType.luau +99 -99
  46. package/vendor/fusion/Animation/springCoefficients.luau +80 -80
  47. package/vendor/fusion/Animation/unpackType.luau +102 -102
  48. package/vendor/fusion/Colour/Oklab.luau +70 -70
  49. package/vendor/fusion/Colour/sRGB.luau +54 -54
  50. package/vendor/fusion/External.luau +167 -167
  51. package/vendor/fusion/ExternalDebug.luau +69 -69
  52. package/vendor/fusion/Graph/Observer.luau +113 -113
  53. package/vendor/fusion/Graph/castToGraph.luau +28 -28
  54. package/vendor/fusion/Graph/change.luau +80 -80
  55. package/vendor/fusion/Graph/depend.luau +32 -32
  56. package/vendor/fusion/Graph/evaluate.luau +55 -55
  57. package/vendor/fusion/Instances/Attribute.luau +57 -57
  58. package/vendor/fusion/Instances/AttributeChange.luau +46 -46
  59. package/vendor/fusion/Instances/AttributeOut.luau +63 -63
  60. package/vendor/fusion/Instances/Child.luau +21 -21
  61. package/vendor/fusion/Instances/Children.luau +147 -147
  62. package/vendor/fusion/Instances/Hydrate.luau +32 -32
  63. package/vendor/fusion/Instances/New.luau +52 -52
  64. package/vendor/fusion/Instances/OnChange.luau +49 -49
  65. package/vendor/fusion/Instances/OnEvent.luau +53 -53
  66. package/vendor/fusion/Instances/Out.luau +69 -69
  67. package/vendor/fusion/Instances/applyInstanceProps.luau +148 -148
  68. package/vendor/fusion/Instances/defaultProps.luau +194 -194
  69. package/vendor/fusion/LICENSE +21 -21
  70. package/vendor/fusion/Logging/formatError.luau +48 -48
  71. package/vendor/fusion/Logging/messages.luau +51 -51
  72. package/vendor/fusion/Logging/parseError.luau +24 -24
  73. package/vendor/fusion/Memory/checkLifetime.luau +133 -133
  74. package/vendor/fusion/Memory/deriveScope.luau +23 -23
  75. package/vendor/fusion/Memory/deriveScopeImpl.luau +44 -44
  76. package/vendor/fusion/Memory/doCleanup.luau +78 -78
  77. package/vendor/fusion/Memory/innerScope.luau +33 -33
  78. package/vendor/fusion/Memory/legacyCleanup.luau +17 -17
  79. package/vendor/fusion/Memory/needsDestruction.luau +16 -16
  80. package/vendor/fusion/Memory/poisonScope.luau +33 -33
  81. package/vendor/fusion/Memory/scopePool.luau +54 -54
  82. package/vendor/fusion/Memory/scoped.luau +26 -26
  83. package/vendor/fusion/Memory/whichLivesLonger.luau +74 -74
  84. package/vendor/fusion/RobloxExternal.luau +97 -97
  85. package/vendor/fusion/State/Computed.luau +138 -138
  86. package/vendor/fusion/State/For/Disassembly.luau +210 -210
  87. package/vendor/fusion/State/For/ForTypes.luau +30 -30
  88. package/vendor/fusion/State/For/init.luau +109 -109
  89. package/vendor/fusion/State/ForKeys.luau +93 -93
  90. package/vendor/fusion/State/ForPairs.luau +96 -96
  91. package/vendor/fusion/State/ForValues.luau +93 -93
  92. package/vendor/fusion/State/Value.luau +87 -87
  93. package/vendor/fusion/State/castToState.luau +25 -25
  94. package/vendor/fusion/State/peek.luau +30 -30
  95. package/vendor/fusion/Types.luau +314 -314
  96. package/vendor/fusion/Utility/Contextual.luau +90 -90
  97. package/vendor/fusion/Utility/Safe.luau +22 -22
  98. package/vendor/fusion/Utility/isSimilar.luau +29 -29
  99. package/vendor/fusion/Utility/merge.luau +35 -35
  100. package/vendor/fusion/Utility/nameOf.luau +34 -34
  101. package/vendor/fusion/Utility/never.luau +13 -13
  102. package/vendor/fusion/Utility/nicknames.luau +10 -10
  103. package/vendor/fusion/Utility/xtypeof.luau +26 -26
  104. package/vendor/fusion/init.luau +82 -82
  105. package/vendor/profilestore/init.luau +2242 -2242
  106. package/vendor/promise/init.luau +1982 -1982
  107. package/vendor/rbxutil/buffer-util/Buffer.test.luau +25 -25
  108. package/vendor/rbxutil/buffer-util/BufferReader.luau +228 -228
  109. package/vendor/rbxutil/buffer-util/BufferWriter.luau +269 -269
  110. package/vendor/rbxutil/buffer-util/DataTypeBuffer.luau +223 -223
  111. package/vendor/rbxutil/buffer-util/Types.luau +60 -60
  112. package/vendor/rbxutil/buffer-util/index.d.ts +153 -153
  113. package/vendor/rbxutil/buffer-util/init.luau +41 -41
  114. package/vendor/rbxutil/buffer-util/package.json +16 -16
  115. package/vendor/rbxutil/buffer-util/wally.toml +9 -9
  116. package/vendor/rbxutil/comm/Client/ClientComm.luau +232 -232
  117. package/vendor/rbxutil/comm/Client/ClientRemoteProperty.luau +156 -156
  118. package/vendor/rbxutil/comm/Client/ClientRemoteSignal.luau +109 -109
  119. package/vendor/rbxutil/comm/Client/init.luau +135 -135
  120. package/vendor/rbxutil/comm/Server/RemoteProperty.luau +295 -295
  121. package/vendor/rbxutil/comm/Server/RemoteSignal.luau +211 -211
  122. package/vendor/rbxutil/comm/Server/ServerComm.luau +211 -211
  123. package/vendor/rbxutil/comm/Server/init.luau +140 -140
  124. package/vendor/rbxutil/comm/Types.luau +18 -18
  125. package/vendor/rbxutil/comm/Util.luau +27 -27
  126. package/vendor/rbxutil/comm/init.luau +35 -35
  127. package/vendor/rbxutil/comm/wally.toml +13 -13
  128. package/vendor/rbxutil/component/init.luau +759 -759
  129. package/vendor/rbxutil/component/init.test.luau +311 -311
  130. package/vendor/rbxutil/component/wally.toml +14 -14
  131. package/vendor/rbxutil/concur/init.luau +542 -542
  132. package/vendor/rbxutil/concur/init.test.luau +364 -364
  133. package/vendor/rbxutil/concur/wally.toml +8 -8
  134. package/vendor/rbxutil/enum-list/init.luau +101 -101
  135. package/vendor/rbxutil/enum-list/init.test.luau +91 -91
  136. package/vendor/rbxutil/enum-list/wally.toml +8 -8
  137. package/vendor/rbxutil/find/index.d.ts +20 -20
  138. package/vendor/rbxutil/find/init.luau +44 -44
  139. package/vendor/rbxutil/find/package.json +17 -17
  140. package/vendor/rbxutil/find/wally.toml +8 -8
  141. package/vendor/rbxutil/input/Gamepad.luau +559 -559
  142. package/vendor/rbxutil/input/Keyboard.luau +124 -124
  143. package/vendor/rbxutil/input/Mouse.luau +278 -278
  144. package/vendor/rbxutil/input/PreferredInput.luau +91 -91
  145. package/vendor/rbxutil/input/Touch.luau +120 -120
  146. package/vendor/rbxutil/input/init.luau +33 -33
  147. package/vendor/rbxutil/input/wally.toml +12 -12
  148. package/vendor/rbxutil/loader/index.d.ts +15 -15
  149. package/vendor/rbxutil/loader/init.luau +137 -137
  150. package/vendor/rbxutil/loader/wally.toml +8 -8
  151. package/vendor/rbxutil/log/index.d.ts +38 -38
  152. package/vendor/rbxutil/log/init.luau +746 -746
  153. package/vendor/rbxutil/log/wally.toml +8 -8
  154. package/vendor/rbxutil/net/init.luau +190 -190
  155. package/vendor/rbxutil/net/wally.toml +8 -8
  156. package/vendor/rbxutil/option/index.d.ts +44 -44
  157. package/vendor/rbxutil/option/init.luau +489 -489
  158. package/vendor/rbxutil/option/init.test.luau +342 -342
  159. package/vendor/rbxutil/option/wally.toml +8 -8
  160. package/vendor/rbxutil/pid/index.d.ts +53 -53
  161. package/vendor/rbxutil/pid/init.luau +195 -195
  162. package/vendor/rbxutil/pid/package.json +16 -16
  163. package/vendor/rbxutil/pid/wally.toml +9 -9
  164. package/vendor/rbxutil/quaternion/index.d.ts +117 -117
  165. package/vendor/rbxutil/quaternion/init.luau +570 -570
  166. package/vendor/rbxutil/quaternion/package.json +16 -16
  167. package/vendor/rbxutil/quaternion/wally.toml +9 -9
  168. package/vendor/rbxutil/query/index.d.ts +43 -43
  169. package/vendor/rbxutil/query/init.luau +117 -117
  170. package/vendor/rbxutil/query/package.json +18 -18
  171. package/vendor/rbxutil/query/wally.toml +9 -9
  172. package/vendor/rbxutil/sequent/index.d.ts +28 -28
  173. package/vendor/rbxutil/sequent/init.luau +340 -340
  174. package/vendor/rbxutil/sequent/package.json +16 -16
  175. package/vendor/rbxutil/sequent/wally.toml +9 -9
  176. package/vendor/rbxutil/ser/init.luau +175 -175
  177. package/vendor/rbxutil/ser/init.test.luau +50 -50
  178. package/vendor/rbxutil/ser/wally.toml +11 -11
  179. package/vendor/rbxutil/shake/index.d.ts +36 -36
  180. package/vendor/rbxutil/shake/init.luau +532 -532
  181. package/vendor/rbxutil/shake/init.test.luau +267 -267
  182. package/vendor/rbxutil/shake/package.json +16 -16
  183. package/vendor/rbxutil/shake/wally.toml +9 -9
  184. package/vendor/rbxutil/signal/index.d.ts +100 -100
  185. package/vendor/rbxutil/signal/init.luau +432 -432
  186. package/vendor/rbxutil/signal/init.test.luau +190 -190
  187. package/vendor/rbxutil/signal/package.json +17 -17
  188. package/vendor/rbxutil/signal/wally.toml +9 -9
  189. package/vendor/rbxutil/silo/TableWatcher.luau +65 -65
  190. package/vendor/rbxutil/silo/Util.luau +55 -55
  191. package/vendor/rbxutil/silo/init.luau +338 -338
  192. package/vendor/rbxutil/silo/init.test.luau +215 -215
  193. package/vendor/rbxutil/silo/wally.toml +8 -8
  194. package/vendor/rbxutil/spring/index.d.ts +40 -40
  195. package/vendor/rbxutil/spring/init.luau +97 -97
  196. package/vendor/rbxutil/spring/package.json +17 -17
  197. package/vendor/rbxutil/spring/wally.toml +8 -8
  198. package/vendor/rbxutil/stream/index.d.ts +88 -88
  199. package/vendor/rbxutil/stream/init.luau +597 -597
  200. package/vendor/rbxutil/stream/package.json +18 -18
  201. package/vendor/rbxutil/stream/wally.toml +9 -9
  202. package/vendor/rbxutil/streamable/Streamable.luau +202 -202
  203. package/vendor/rbxutil/streamable/StreamableUtil.luau +80 -80
  204. package/vendor/rbxutil/streamable/init.luau +8 -8
  205. package/vendor/rbxutil/streamable/wally.toml +12 -12
  206. package/vendor/rbxutil/symbol/init.luau +56 -56
  207. package/vendor/rbxutil/symbol/init.test.luau +37 -37
  208. package/vendor/rbxutil/symbol/wally.toml +8 -8
  209. package/vendor/rbxutil/table-util/init.luau +938 -938
  210. package/vendor/rbxutil/table-util/init.test.luau +439 -439
  211. package/vendor/rbxutil/task-queue/index.d.ts +27 -27
  212. package/vendor/rbxutil/task-queue/init.luau +97 -97
  213. package/vendor/rbxutil/task-queue/wally.toml +8 -8
  214. package/vendor/rbxutil/timer/index.d.ts +81 -81
  215. package/vendor/rbxutil/timer/init.luau +249 -249
  216. package/vendor/rbxutil/timer/init.test.luau +73 -73
  217. package/vendor/rbxutil/timer/wally.toml +11 -11
  218. package/vendor/rbxutil/tree/index.d.ts +15 -15
  219. package/vendor/rbxutil/tree/init.luau +137 -137
  220. package/vendor/rbxutil/tree/wally.toml +8 -8
  221. package/vendor/rbxutil/trove/index.d.ts +46 -46
  222. package/vendor/rbxutil/trove/init.luau +787 -787
  223. package/vendor/rbxutil/trove/init.test.luau +203 -203
  224. package/vendor/rbxutil/trove/wally.toml +8 -8
  225. package/vendor/rbxutil/typed-remote/init.luau +196 -196
  226. package/vendor/rbxutil/typed-remote/wally.toml +8 -8
  227. package/vendor/rbxutil/wait-for/index.d.ts +17 -17
  228. package/vendor/rbxutil/wait-for/init.luau +257 -257
  229. package/vendor/rbxutil/wait-for/init.test.luau +182 -182
  230. package/vendor/rbxutil/wait-for/wally.toml +11 -11
  231. package/vendor/t/t.lua +1350 -1350
  232. package/vendor/testez/Context.lua +26 -26
  233. package/vendor/testez/Expectation.lua +311 -311
  234. package/vendor/testez/ExpectationContext.lua +38 -38
  235. package/vendor/testez/LifecycleHooks.lua +89 -89
  236. package/vendor/testez/Reporters/TeamCityReporter.lua +101 -101
  237. package/vendor/testez/Reporters/TextReporter.lua +105 -105
  238. package/vendor/testez/Reporters/TextReporterQuiet.lua +96 -96
  239. package/vendor/testez/TestBootstrap.lua +146 -146
  240. package/vendor/testez/TestEnum.lua +27 -27
  241. package/vendor/testez/TestPlan.lua +304 -304
  242. package/vendor/testez/TestPlanner.lua +39 -39
  243. package/vendor/testez/TestResults.lua +111 -111
  244. package/vendor/testez/TestRunner.lua +188 -188
  245. package/vendor/testez/TestSession.lua +243 -243
  246. package/vendor/testez/init.lua +39 -39
@@ -1,257 +1,257 @@
1
- -- WaitFor
2
- -- Stephen Leitnick
3
- -- January 17, 2022
4
-
5
- local RunService = game:GetService("RunService")
6
-
7
- local Promise = require(script.Parent.Promise)
8
-
9
- local DEFAULT_TIMEOUT = 60
10
-
11
- --[=[
12
- @class WaitFor
13
- Utility class for awaiting the existence of instances.
14
-
15
- By default, all promises timeout after 60 seconds, unless the `timeout`
16
- argument is specified.
17
-
18
- :::note
19
- Promises will be rejected if the parent (or any ancestor) is unparented
20
- from the game.
21
- :::
22
-
23
- :::caution Set name before parent
24
- When waiting for instances based on name (e.g. `WaitFor.Child`), the `WaitFor`
25
- system is listening to events to capture these instances being added. This
26
- means that the name must be set _before_ being parented into the object.
27
- :::
28
- ]=]
29
- local WaitFor = {}
30
-
31
- --[=[
32
- @within WaitFor
33
- @prop Error {Unparented: string, ParentChanged: string}
34
- ]=]
35
- WaitFor.Error = {
36
- Unparented = "Unparented",
37
- ParentChanged = "ParentChanged",
38
- }
39
-
40
- local function PromiseWatchAncestry(instance: Instance, promise)
41
- return Promise.race({
42
- promise,
43
- Promise.fromEvent(instance.AncestryChanged, function(_, newParent)
44
- return newParent == nil
45
- end):andThen(function()
46
- return Promise.reject(WaitFor.Error.Unparented)
47
- end),
48
- })
49
- end
50
-
51
- --[=[
52
- @return Promise<Instance>
53
- Wait for a child to exist within a given parent based on the child name.
54
-
55
- ```lua
56
- WaitFor.Child(parent, "SomeObject"):andThen(function(someObject)
57
- print(someObject, "now exists")
58
- end):catch(warn)
59
- ```
60
- ]=]
61
- function WaitFor.Child(parent: Instance, childName: string, timeout: number?)
62
- local child = parent:FindFirstChild(childName)
63
- if child then
64
- return Promise.resolve(child)
65
- end
66
- return PromiseWatchAncestry(
67
- parent,
68
- Promise.fromEvent(parent.ChildAdded, function(c)
69
- return c.Name == childName
70
- end):timeout(timeout or DEFAULT_TIMEOUT)
71
- )
72
- end
73
-
74
- --[=[
75
- @return Promise<{Instance}>
76
- Wait for all children to exist within the given parent.
77
-
78
- ```lua
79
- WaitFor.Children(parent, {"SomeObject01", "SomeObject02"}):andThen(function(children)
80
- local someObject01, someObject02 = table.unpack(children)
81
- end)
82
- ```
83
-
84
- :::note
85
- Once all children are found, a second check is made to ensure that all children
86
- are still directly parented to the given `parent` (since one child's parent
87
- might have changed before another child was found). A rejected promise with the
88
- `WaitFor.Error.ParentChanged` error will be thrown if any parents of the children
89
- no longer match the given `parent`.
90
- :::
91
- ]=]
92
- function WaitFor.Children(parent: Instance, childrenNames: { string }, timeout: number?)
93
- local all = table.create(#childrenNames)
94
- for i, childName in ipairs(childrenNames) do
95
- all[i] = WaitFor.Child(parent, childName, timeout)
96
- end
97
- return Promise.all(all):andThen(function(children)
98
- -- Check that all are still parented
99
- for _, child in ipairs(children) do
100
- if child.Parent ~= parent then
101
- return Promise.reject(WaitFor.Error.ParentChanged)
102
- end
103
- end
104
- return children
105
- end)
106
- end
107
-
108
- --[=[
109
- @return Promise<Instance>
110
- Wait for a descendant to exist within a given parent. This is similar to
111
- `WaitFor.Child`, except it looks for all descendants instead of immediate
112
- children.
113
-
114
- ```lua
115
- WaitFor.Descendant(parent, "SomeDescendant"):andThen(function(someDescendant)
116
- print("SomeDescendant now exists")
117
- end)
118
- ```
119
- ]=]
120
- function WaitFor.Descendant(parent: Instance, descendantName: string, timeout: number?)
121
- local descendant = parent:FindFirstChild(descendantName, true)
122
- if descendant then
123
- return Promise.resolve(descendant)
124
- end
125
- return PromiseWatchAncestry(
126
- parent,
127
- Promise.fromEvent(parent.DescendantAdded, function(d)
128
- return d.Name == descendantName
129
- end):timeout(timeout or DEFAULT_TIMEOUT)
130
- )
131
- end
132
-
133
- --[=[
134
- @return Promise<{Instance}>
135
- Wait for all descendants to exist within a given parent.
136
-
137
- ```lua
138
- WaitFor.Descendants(parent, {"SomeDescendant01", "SomeDescendant02"}):andThen(function(descendants)
139
- local someDescendant01, someDescendant02 = table.unpack(descendants)
140
- end)
141
- ```
142
-
143
- :::note
144
- Once all descendants are found, a second check is made to ensure that none of the
145
- instances have moved outside of the parent (since one instance might change before
146
- another instance is found). A rejected promise with the `WaitFor.Error.ParentChanged`
147
- error will be thrown if any of the instances are no longer descendants of the given
148
- `parent`.
149
- :::
150
- ]=]
151
- function WaitFor.Descendants(parent: Instance, descendantNames: { string }, timeout: number?)
152
- local all = table.create(#descendantNames)
153
- for i, descendantName in ipairs(descendantNames) do
154
- all[i] = WaitFor.Descendant(parent, descendantName, timeout)
155
- end
156
- return Promise.all(all):andThen(function(descendants)
157
- -- Check that all are still parented
158
- for _, descendant in ipairs(descendants) do
159
- if not descendant:IsDescendantOf(parent) then
160
- return Promise.reject(WaitFor.Error.ParentChanged)
161
- end
162
- end
163
- return descendants
164
- end)
165
- end
166
-
167
- --[=[
168
- @return Promise<Instance>
169
- Wait for the PrimaryPart of a model to exist.
170
-
171
- ```lua
172
- WaitFor.PrimaryPart(model):andThen(function(primaryPart)
173
- print(primaryPart == model.PrimaryPart)
174
- end)
175
- ```
176
- ]=]
177
- function WaitFor.PrimaryPart(model: Model, timeout: number?)
178
- local primary = model.PrimaryPart
179
- if primary then
180
- return Promise.resolve(primary)
181
- end
182
- return PromiseWatchAncestry(
183
- model,
184
- Promise.fromEvent(model:GetPropertyChangedSignal("PrimaryPart"), function()
185
- primary = model.PrimaryPart
186
- return primary ~= nil
187
- end)
188
- :andThen(function()
189
- return primary
190
- end)
191
- :timeout(timeout or DEFAULT_TIMEOUT)
192
- )
193
- end
194
-
195
- --[=[
196
- @return Promise<Instance>
197
- Wait for the Value of an ObjectValue to exist.
198
-
199
- ```lua
200
- WaitFor.ObjectValue(someObjectValue):andThen(function(value)
201
- print("someObjectValue's value is", value)
202
- end)
203
- ```
204
- ]=]
205
- function WaitFor.ObjectValue(objectValue: ObjectValue, timeout: number?)
206
- local value = objectValue.Value
207
- if value then
208
- return Promise.resolve(value)
209
- end
210
- return PromiseWatchAncestry(
211
- objectValue,
212
- Promise.fromEvent(objectValue.Changed, function(v)
213
- value = v
214
- return value ~= nil
215
- end)
216
- :andThen(function()
217
- return value
218
- end)
219
- :timeout(timeout or DEFAULT_TIMEOUT)
220
- )
221
- end
222
-
223
- --[=[
224
- @return Promise<T>
225
- Wait for the given predicate function to return a non-nil value of
226
- of type `T`. The predicate is fired every RunService Heartbeat step.
227
-
228
- ```lua
229
- -- Example, waiting for some property to be set:
230
- WaitFor.Custom(function() return vectorForce.Attachment0 end):andThen(function(a0)
231
- print(a0)
232
- end)
233
- ```
234
- ]=]
235
- function WaitFor.Custom<T>(predicate: () -> T?, timeout: number?)
236
- local value = predicate()
237
- if value ~= nil then
238
- return Promise.resolve(value)
239
- end
240
- return Promise.new(function(resolve, _reject, onCancel)
241
- local heartbeat
242
- local function OnDone()
243
- heartbeat:Disconnect()
244
- end
245
- local function Update()
246
- local v = predicate()
247
- if v ~= nil then
248
- OnDone()
249
- resolve(v)
250
- end
251
- end
252
- heartbeat = RunService.Heartbeat:Connect(Update)
253
- onCancel(OnDone)
254
- end):timeout(timeout or DEFAULT_TIMEOUT)
255
- end
256
-
257
- return WaitFor
1
+ -- WaitFor
2
+ -- Stephen Leitnick
3
+ -- January 17, 2022
4
+
5
+ local RunService = game:GetService("RunService")
6
+
7
+ local Promise = require(script.Parent.Promise)
8
+
9
+ local DEFAULT_TIMEOUT = 60
10
+
11
+ --[=[
12
+ @class WaitFor
13
+ Utility class for awaiting the existence of instances.
14
+
15
+ By default, all promises timeout after 60 seconds, unless the `timeout`
16
+ argument is specified.
17
+
18
+ :::note
19
+ Promises will be rejected if the parent (or any ancestor) is unparented
20
+ from the game.
21
+ :::
22
+
23
+ :::caution Set name before parent
24
+ When waiting for instances based on name (e.g. `WaitFor.Child`), the `WaitFor`
25
+ system is listening to events to capture these instances being added. This
26
+ means that the name must be set _before_ being parented into the object.
27
+ :::
28
+ ]=]
29
+ local WaitFor = {}
30
+
31
+ --[=[
32
+ @within WaitFor
33
+ @prop Error {Unparented: string, ParentChanged: string}
34
+ ]=]
35
+ WaitFor.Error = {
36
+ Unparented = "Unparented",
37
+ ParentChanged = "ParentChanged",
38
+ }
39
+
40
+ local function PromiseWatchAncestry(instance: Instance, promise)
41
+ return Promise.race({
42
+ promise,
43
+ Promise.fromEvent(instance.AncestryChanged, function(_, newParent)
44
+ return newParent == nil
45
+ end):andThen(function()
46
+ return Promise.reject(WaitFor.Error.Unparented)
47
+ end),
48
+ })
49
+ end
50
+
51
+ --[=[
52
+ @return Promise<Instance>
53
+ Wait for a child to exist within a given parent based on the child name.
54
+
55
+ ```lua
56
+ WaitFor.Child(parent, "SomeObject"):andThen(function(someObject)
57
+ print(someObject, "now exists")
58
+ end):catch(warn)
59
+ ```
60
+ ]=]
61
+ function WaitFor.Child(parent: Instance, childName: string, timeout: number?)
62
+ local child = parent:FindFirstChild(childName)
63
+ if child then
64
+ return Promise.resolve(child)
65
+ end
66
+ return PromiseWatchAncestry(
67
+ parent,
68
+ Promise.fromEvent(parent.ChildAdded, function(c)
69
+ return c.Name == childName
70
+ end):timeout(timeout or DEFAULT_TIMEOUT)
71
+ )
72
+ end
73
+
74
+ --[=[
75
+ @return Promise<{Instance}>
76
+ Wait for all children to exist within the given parent.
77
+
78
+ ```lua
79
+ WaitFor.Children(parent, {"SomeObject01", "SomeObject02"}):andThen(function(children)
80
+ local someObject01, someObject02 = table.unpack(children)
81
+ end)
82
+ ```
83
+
84
+ :::note
85
+ Once all children are found, a second check is made to ensure that all children
86
+ are still directly parented to the given `parent` (since one child's parent
87
+ might have changed before another child was found). A rejected promise with the
88
+ `WaitFor.Error.ParentChanged` error will be thrown if any parents of the children
89
+ no longer match the given `parent`.
90
+ :::
91
+ ]=]
92
+ function WaitFor.Children(parent: Instance, childrenNames: { string }, timeout: number?)
93
+ local all = table.create(#childrenNames)
94
+ for i, childName in ipairs(childrenNames) do
95
+ all[i] = WaitFor.Child(parent, childName, timeout)
96
+ end
97
+ return Promise.all(all):andThen(function(children)
98
+ -- Check that all are still parented
99
+ for _, child in ipairs(children) do
100
+ if child.Parent ~= parent then
101
+ return Promise.reject(WaitFor.Error.ParentChanged)
102
+ end
103
+ end
104
+ return children
105
+ end)
106
+ end
107
+
108
+ --[=[
109
+ @return Promise<Instance>
110
+ Wait for a descendant to exist within a given parent. This is similar to
111
+ `WaitFor.Child`, except it looks for all descendants instead of immediate
112
+ children.
113
+
114
+ ```lua
115
+ WaitFor.Descendant(parent, "SomeDescendant"):andThen(function(someDescendant)
116
+ print("SomeDescendant now exists")
117
+ end)
118
+ ```
119
+ ]=]
120
+ function WaitFor.Descendant(parent: Instance, descendantName: string, timeout: number?)
121
+ local descendant = parent:FindFirstChild(descendantName, true)
122
+ if descendant then
123
+ return Promise.resolve(descendant)
124
+ end
125
+ return PromiseWatchAncestry(
126
+ parent,
127
+ Promise.fromEvent(parent.DescendantAdded, function(d)
128
+ return d.Name == descendantName
129
+ end):timeout(timeout or DEFAULT_TIMEOUT)
130
+ )
131
+ end
132
+
133
+ --[=[
134
+ @return Promise<{Instance}>
135
+ Wait for all descendants to exist within a given parent.
136
+
137
+ ```lua
138
+ WaitFor.Descendants(parent, {"SomeDescendant01", "SomeDescendant02"}):andThen(function(descendants)
139
+ local someDescendant01, someDescendant02 = table.unpack(descendants)
140
+ end)
141
+ ```
142
+
143
+ :::note
144
+ Once all descendants are found, a second check is made to ensure that none of the
145
+ instances have moved outside of the parent (since one instance might change before
146
+ another instance is found). A rejected promise with the `WaitFor.Error.ParentChanged`
147
+ error will be thrown if any of the instances are no longer descendants of the given
148
+ `parent`.
149
+ :::
150
+ ]=]
151
+ function WaitFor.Descendants(parent: Instance, descendantNames: { string }, timeout: number?)
152
+ local all = table.create(#descendantNames)
153
+ for i, descendantName in ipairs(descendantNames) do
154
+ all[i] = WaitFor.Descendant(parent, descendantName, timeout)
155
+ end
156
+ return Promise.all(all):andThen(function(descendants)
157
+ -- Check that all are still parented
158
+ for _, descendant in ipairs(descendants) do
159
+ if not descendant:IsDescendantOf(parent) then
160
+ return Promise.reject(WaitFor.Error.ParentChanged)
161
+ end
162
+ end
163
+ return descendants
164
+ end)
165
+ end
166
+
167
+ --[=[
168
+ @return Promise<Instance>
169
+ Wait for the PrimaryPart of a model to exist.
170
+
171
+ ```lua
172
+ WaitFor.PrimaryPart(model):andThen(function(primaryPart)
173
+ print(primaryPart == model.PrimaryPart)
174
+ end)
175
+ ```
176
+ ]=]
177
+ function WaitFor.PrimaryPart(model: Model, timeout: number?)
178
+ local primary = model.PrimaryPart
179
+ if primary then
180
+ return Promise.resolve(primary)
181
+ end
182
+ return PromiseWatchAncestry(
183
+ model,
184
+ Promise.fromEvent(model:GetPropertyChangedSignal("PrimaryPart"), function()
185
+ primary = model.PrimaryPart
186
+ return primary ~= nil
187
+ end)
188
+ :andThen(function()
189
+ return primary
190
+ end)
191
+ :timeout(timeout or DEFAULT_TIMEOUT)
192
+ )
193
+ end
194
+
195
+ --[=[
196
+ @return Promise<Instance>
197
+ Wait for the Value of an ObjectValue to exist.
198
+
199
+ ```lua
200
+ WaitFor.ObjectValue(someObjectValue):andThen(function(value)
201
+ print("someObjectValue's value is", value)
202
+ end)
203
+ ```
204
+ ]=]
205
+ function WaitFor.ObjectValue(objectValue: ObjectValue, timeout: number?)
206
+ local value = objectValue.Value
207
+ if value then
208
+ return Promise.resolve(value)
209
+ end
210
+ return PromiseWatchAncestry(
211
+ objectValue,
212
+ Promise.fromEvent(objectValue.Changed, function(v)
213
+ value = v
214
+ return value ~= nil
215
+ end)
216
+ :andThen(function()
217
+ return value
218
+ end)
219
+ :timeout(timeout or DEFAULT_TIMEOUT)
220
+ )
221
+ end
222
+
223
+ --[=[
224
+ @return Promise<T>
225
+ Wait for the given predicate function to return a non-nil value of
226
+ of type `T`. The predicate is fired every RunService Heartbeat step.
227
+
228
+ ```lua
229
+ -- Example, waiting for some property to be set:
230
+ WaitFor.Custom(function() return vectorForce.Attachment0 end):andThen(function(a0)
231
+ print(a0)
232
+ end)
233
+ ```
234
+ ]=]
235
+ function WaitFor.Custom<T>(predicate: () -> T?, timeout: number?)
236
+ local value = predicate()
237
+ if value ~= nil then
238
+ return Promise.resolve(value)
239
+ end
240
+ return Promise.new(function(resolve, _reject, onCancel)
241
+ local heartbeat
242
+ local function OnDone()
243
+ heartbeat:Disconnect()
244
+ end
245
+ local function Update()
246
+ local v = predicate()
247
+ if v ~= nil then
248
+ OnDone()
249
+ resolve(v)
250
+ end
251
+ end
252
+ heartbeat = RunService.Heartbeat:Connect(Update)
253
+ onCancel(OnDone)
254
+ end):timeout(timeout or DEFAULT_TIMEOUT)
255
+ end
256
+
257
+ return WaitFor