roblox-opencode 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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 +877 -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 +1618 -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,18 +1,18 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@rbxutil/stream",
|
|
3
|
-
"version": "0.1.1",
|
|
4
|
-
"main": "init.luau",
|
|
5
|
-
"repository": {
|
|
6
|
-
"url": "git+https://github.com/Sleitnick/RbxUtil.git"
|
|
7
|
-
},
|
|
8
|
-
"license": "MIT",
|
|
9
|
-
"types": "index.d.ts",
|
|
10
|
-
"files": [
|
|
11
|
-
"./*",
|
|
12
|
-
"!*.toml",
|
|
13
|
-
"!*.json"
|
|
14
|
-
],
|
|
15
|
-
"publishConfig": {
|
|
16
|
-
"access": "public"
|
|
17
|
-
}
|
|
18
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@rbxutil/stream",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"main": "init.luau",
|
|
5
|
+
"repository": {
|
|
6
|
+
"url": "git+https://github.com/Sleitnick/RbxUtil.git"
|
|
7
|
+
},
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"types": "index.d.ts",
|
|
10
|
+
"files": [
|
|
11
|
+
"./*",
|
|
12
|
+
"!*.toml",
|
|
13
|
+
"!*.json"
|
|
14
|
+
],
|
|
15
|
+
"publishConfig": {
|
|
16
|
+
"access": "public"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
[package]
|
|
2
|
-
name = "sleitnick/stream"
|
|
3
|
-
description = "Stream abstraction wrapper around buffers"
|
|
4
|
-
version = "0.1.1"
|
|
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/stream"
|
|
3
|
+
description = "Stream abstraction wrapper around buffers"
|
|
4
|
+
version = "0.1.1"
|
|
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,202 +1,202 @@
|
|
|
1
|
-
--!strict
|
|
2
|
-
|
|
3
|
-
-- Streamable
|
|
4
|
-
-- Stephen Leitnick
|
|
5
|
-
-- March 03, 2021
|
|
6
|
-
|
|
7
|
-
type StreamableWithInstance = {
|
|
8
|
-
Instance: Instance?,
|
|
9
|
-
[any]: any,
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
local Trove = require(script.Parent.Parent.Trove)
|
|
13
|
-
local Signal = require(script.Parent.Parent.Signal)
|
|
14
|
-
|
|
15
|
-
--[=[
|
|
16
|
-
@within Streamable
|
|
17
|
-
@prop Instance Instance
|
|
18
|
-
The current instance represented by the Streamable. If this
|
|
19
|
-
is being observed, it will always exist. If not currently
|
|
20
|
-
being observed, this will be `nil`.
|
|
21
|
-
]=]
|
|
22
|
-
|
|
23
|
-
--[=[
|
|
24
|
-
@class Streamable
|
|
25
|
-
@client
|
|
26
|
-
Because parts in StreamingEnabled games can stream in and out of existence at
|
|
27
|
-
any point in time, it is hard to write code to interact with them. This is
|
|
28
|
-
where Streamables come into play. Streamables will observe the existence of
|
|
29
|
-
a given instance, and will signal when the instance exists and does not
|
|
30
|
-
exist.
|
|
31
|
-
|
|
32
|
-
The API is very simple. Create a Streamable that points to a certain parent
|
|
33
|
-
and looks for a specific child instance (typically a BasePart). Then, call
|
|
34
|
-
the `Observe` method to observe when the instance streams in and out.
|
|
35
|
-
|
|
36
|
-
```lua
|
|
37
|
-
local Streamable = require(packages.Streamable).Streamable
|
|
38
|
-
|
|
39
|
-
-- Models might take a bit to load, but the model instance
|
|
40
|
-
-- is never removed, thus we can use WaitForChild.
|
|
41
|
-
local model = workspace:WaitForChild("MyModel")
|
|
42
|
-
|
|
43
|
-
-- Watch for a specific part in the model:
|
|
44
|
-
local partStreamable = Streamable.new(model, "SomePart")
|
|
45
|
-
|
|
46
|
-
partStreamable:Observe(function(part, trove)
|
|
47
|
-
print(part:GetFullName() .. " added")
|
|
48
|
-
-- Run code on the part here.
|
|
49
|
-
-- Use the trove to manage cleanup when the part goes away.
|
|
50
|
-
trove:Add(function()
|
|
51
|
-
-- General cleanup stuff
|
|
52
|
-
print(part.Name .. " removed")
|
|
53
|
-
end)
|
|
54
|
-
end)
|
|
55
|
-
|
|
56
|
-
-- Watch for the PrimaryPart of a model to exist:
|
|
57
|
-
local primaryStreamable = Streamable.primary(model)
|
|
58
|
-
primaryStreamable:Observe(function(primary, trove)
|
|
59
|
-
print("Model now has a PrimaryPart:", primary.Name)
|
|
60
|
-
trove:Add(function()
|
|
61
|
-
print("Model's PrimaryPart has been removed")
|
|
62
|
-
end)
|
|
63
|
-
end)
|
|
64
|
-
|
|
65
|
-
-- At any given point, accessing the Instance field will
|
|
66
|
-
-- reference the observed part, if it exists:
|
|
67
|
-
if partStreamable.Instance then
|
|
68
|
-
print("Streamable has its instance:", partStreamable.Instance)
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
-- When/if done, call Destroy on the streamable, which will
|
|
72
|
-
-- also clean up any observers:
|
|
73
|
-
partStreamable:Destroy()
|
|
74
|
-
primaryStreamable:Destroy()
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
For more information on the mechanics of how StreamingEnabled works
|
|
78
|
-
and what sort of behavior to expect, see the
|
|
79
|
-
[Content Streaming](https://developer.roblox.com/en-us/articles/content-streaming#technical-behavior)
|
|
80
|
-
page. It is important to understand that only BaseParts and their descendants are streamed in/out,
|
|
81
|
-
whereas other instances are loaded during the initial client load. It is also important to understand
|
|
82
|
-
that streaming only occurs on the client. The server has immediate access to everything right away.
|
|
83
|
-
]=]
|
|
84
|
-
local Streamable = {}
|
|
85
|
-
Streamable.__index = Streamable
|
|
86
|
-
|
|
87
|
-
--[=[
|
|
88
|
-
@return Streamable
|
|
89
|
-
@param parent Instance
|
|
90
|
-
@param childName string
|
|
91
|
-
|
|
92
|
-
Constructs a Streamable that watches for a direct child of name `childName`
|
|
93
|
-
within the `parent` Instance. Call `Observe` to observe the existence of
|
|
94
|
-
the child within the parent.
|
|
95
|
-
]=]
|
|
96
|
-
function Streamable.new(parent: Instance, childName: string)
|
|
97
|
-
local self: StreamableWithInstance = {}
|
|
98
|
-
setmetatable(self, Streamable)
|
|
99
|
-
|
|
100
|
-
self._trove = Trove.new()
|
|
101
|
-
self._shown = self._trove:Construct(Signal)
|
|
102
|
-
self._shownTrove = Trove.new()
|
|
103
|
-
self._trove:Add(self._shownTrove)
|
|
104
|
-
|
|
105
|
-
self.Instance = parent:FindFirstChild(childName)
|
|
106
|
-
|
|
107
|
-
local function OnInstanceSet()
|
|
108
|
-
local instance = self.Instance
|
|
109
|
-
if typeof(instance) == "Instance" then
|
|
110
|
-
self._shown:Fire(instance, self._shownTrove)
|
|
111
|
-
self._shownTrove:Connect(instance:GetPropertyChangedSignal("Parent"), function()
|
|
112
|
-
if not instance.Parent then
|
|
113
|
-
self._shownTrove:Clean()
|
|
114
|
-
end
|
|
115
|
-
end)
|
|
116
|
-
self._shownTrove:Add(function()
|
|
117
|
-
if self.Instance == instance then
|
|
118
|
-
self.Instance = nil
|
|
119
|
-
end
|
|
120
|
-
end)
|
|
121
|
-
end
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
local function OnChildAdded(child: Instance)
|
|
125
|
-
if child.Name == childName and not self.Instance then
|
|
126
|
-
self.Instance = child
|
|
127
|
-
OnInstanceSet()
|
|
128
|
-
end
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
self._trove:Connect(parent.ChildAdded, OnChildAdded)
|
|
132
|
-
if self.Instance then
|
|
133
|
-
OnInstanceSet()
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
return self
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
--[=[
|
|
140
|
-
@return Streamable
|
|
141
|
-
@param parent Model
|
|
142
|
-
|
|
143
|
-
Constructs a streamable that watches for the PrimaryPart of the
|
|
144
|
-
given `parent` Model.
|
|
145
|
-
]=]
|
|
146
|
-
function Streamable.primary(parent: Model)
|
|
147
|
-
local self: StreamableWithInstance = {}
|
|
148
|
-
setmetatable(self, Streamable)
|
|
149
|
-
|
|
150
|
-
self._trove = Trove.new()
|
|
151
|
-
self._shown = self._trove:Construct(Signal)
|
|
152
|
-
self._shownTrove = Trove.new()
|
|
153
|
-
self._trove:Add(self._shownTrove)
|
|
154
|
-
|
|
155
|
-
self.Instance = parent.PrimaryPart
|
|
156
|
-
|
|
157
|
-
local function OnPrimaryPartChanged()
|
|
158
|
-
local primaryPart = parent.PrimaryPart
|
|
159
|
-
self._shownTrove:Clean()
|
|
160
|
-
self.Instance = primaryPart
|
|
161
|
-
if primaryPart then
|
|
162
|
-
self._shown:Fire(primaryPart, self._shownTrove)
|
|
163
|
-
end
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
self._trove:Connect(parent:GetPropertyChangedSignal("PrimaryPart"), OnPrimaryPartChanged)
|
|
167
|
-
if self.Instance then
|
|
168
|
-
OnPrimaryPartChanged()
|
|
169
|
-
end
|
|
170
|
-
|
|
171
|
-
return self
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
--[=[
|
|
175
|
-
@param handler (instance: Instance, trove: Trove) -> nil
|
|
176
|
-
@return Connection
|
|
177
|
-
|
|
178
|
-
Observes the instance. The handler is called anytime the
|
|
179
|
-
instance comes into existence, and the trove given is
|
|
180
|
-
cleaned up when the instance goes away.
|
|
181
|
-
|
|
182
|
-
To stop observing, disconnect the returned connection.
|
|
183
|
-
]=]
|
|
184
|
-
function Streamable:Observe(handler)
|
|
185
|
-
if self.Instance then
|
|
186
|
-
task.spawn(handler, self.Instance, self._shownTrove)
|
|
187
|
-
end
|
|
188
|
-
return self._shown:Connect(handler)
|
|
189
|
-
end
|
|
190
|
-
|
|
191
|
-
--[=[
|
|
192
|
-
Destroys the Streamable. Any observers will be disconnected,
|
|
193
|
-
which also means that troves within observers will be cleaned
|
|
194
|
-
up. This should be called when a streamable is no longer needed.
|
|
195
|
-
]=]
|
|
196
|
-
function Streamable:Destroy()
|
|
197
|
-
self._trove:Destroy()
|
|
198
|
-
end
|
|
199
|
-
|
|
200
|
-
export type Streamable = typeof(Streamable.new(workspace, "X"))
|
|
201
|
-
|
|
202
|
-
return Streamable
|
|
1
|
+
--!strict
|
|
2
|
+
|
|
3
|
+
-- Streamable
|
|
4
|
+
-- Stephen Leitnick
|
|
5
|
+
-- March 03, 2021
|
|
6
|
+
|
|
7
|
+
type StreamableWithInstance = {
|
|
8
|
+
Instance: Instance?,
|
|
9
|
+
[any]: any,
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
local Trove = require(script.Parent.Parent.Trove)
|
|
13
|
+
local Signal = require(script.Parent.Parent.Signal)
|
|
14
|
+
|
|
15
|
+
--[=[
|
|
16
|
+
@within Streamable
|
|
17
|
+
@prop Instance Instance
|
|
18
|
+
The current instance represented by the Streamable. If this
|
|
19
|
+
is being observed, it will always exist. If not currently
|
|
20
|
+
being observed, this will be `nil`.
|
|
21
|
+
]=]
|
|
22
|
+
|
|
23
|
+
--[=[
|
|
24
|
+
@class Streamable
|
|
25
|
+
@client
|
|
26
|
+
Because parts in StreamingEnabled games can stream in and out of existence at
|
|
27
|
+
any point in time, it is hard to write code to interact with them. This is
|
|
28
|
+
where Streamables come into play. Streamables will observe the existence of
|
|
29
|
+
a given instance, and will signal when the instance exists and does not
|
|
30
|
+
exist.
|
|
31
|
+
|
|
32
|
+
The API is very simple. Create a Streamable that points to a certain parent
|
|
33
|
+
and looks for a specific child instance (typically a BasePart). Then, call
|
|
34
|
+
the `Observe` method to observe when the instance streams in and out.
|
|
35
|
+
|
|
36
|
+
```lua
|
|
37
|
+
local Streamable = require(packages.Streamable).Streamable
|
|
38
|
+
|
|
39
|
+
-- Models might take a bit to load, but the model instance
|
|
40
|
+
-- is never removed, thus we can use WaitForChild.
|
|
41
|
+
local model = workspace:WaitForChild("MyModel")
|
|
42
|
+
|
|
43
|
+
-- Watch for a specific part in the model:
|
|
44
|
+
local partStreamable = Streamable.new(model, "SomePart")
|
|
45
|
+
|
|
46
|
+
partStreamable:Observe(function(part, trove)
|
|
47
|
+
print(part:GetFullName() .. " added")
|
|
48
|
+
-- Run code on the part here.
|
|
49
|
+
-- Use the trove to manage cleanup when the part goes away.
|
|
50
|
+
trove:Add(function()
|
|
51
|
+
-- General cleanup stuff
|
|
52
|
+
print(part.Name .. " removed")
|
|
53
|
+
end)
|
|
54
|
+
end)
|
|
55
|
+
|
|
56
|
+
-- Watch for the PrimaryPart of a model to exist:
|
|
57
|
+
local primaryStreamable = Streamable.primary(model)
|
|
58
|
+
primaryStreamable:Observe(function(primary, trove)
|
|
59
|
+
print("Model now has a PrimaryPart:", primary.Name)
|
|
60
|
+
trove:Add(function()
|
|
61
|
+
print("Model's PrimaryPart has been removed")
|
|
62
|
+
end)
|
|
63
|
+
end)
|
|
64
|
+
|
|
65
|
+
-- At any given point, accessing the Instance field will
|
|
66
|
+
-- reference the observed part, if it exists:
|
|
67
|
+
if partStreamable.Instance then
|
|
68
|
+
print("Streamable has its instance:", partStreamable.Instance)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
-- When/if done, call Destroy on the streamable, which will
|
|
72
|
+
-- also clean up any observers:
|
|
73
|
+
partStreamable:Destroy()
|
|
74
|
+
primaryStreamable:Destroy()
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
For more information on the mechanics of how StreamingEnabled works
|
|
78
|
+
and what sort of behavior to expect, see the
|
|
79
|
+
[Content Streaming](https://developer.roblox.com/en-us/articles/content-streaming#technical-behavior)
|
|
80
|
+
page. It is important to understand that only BaseParts and their descendants are streamed in/out,
|
|
81
|
+
whereas other instances are loaded during the initial client load. It is also important to understand
|
|
82
|
+
that streaming only occurs on the client. The server has immediate access to everything right away.
|
|
83
|
+
]=]
|
|
84
|
+
local Streamable = {}
|
|
85
|
+
Streamable.__index = Streamable
|
|
86
|
+
|
|
87
|
+
--[=[
|
|
88
|
+
@return Streamable
|
|
89
|
+
@param parent Instance
|
|
90
|
+
@param childName string
|
|
91
|
+
|
|
92
|
+
Constructs a Streamable that watches for a direct child of name `childName`
|
|
93
|
+
within the `parent` Instance. Call `Observe` to observe the existence of
|
|
94
|
+
the child within the parent.
|
|
95
|
+
]=]
|
|
96
|
+
function Streamable.new(parent: Instance, childName: string)
|
|
97
|
+
local self: StreamableWithInstance = {}
|
|
98
|
+
setmetatable(self, Streamable)
|
|
99
|
+
|
|
100
|
+
self._trove = Trove.new()
|
|
101
|
+
self._shown = self._trove:Construct(Signal)
|
|
102
|
+
self._shownTrove = Trove.new()
|
|
103
|
+
self._trove:Add(self._shownTrove)
|
|
104
|
+
|
|
105
|
+
self.Instance = parent:FindFirstChild(childName)
|
|
106
|
+
|
|
107
|
+
local function OnInstanceSet()
|
|
108
|
+
local instance = self.Instance
|
|
109
|
+
if typeof(instance) == "Instance" then
|
|
110
|
+
self._shown:Fire(instance, self._shownTrove)
|
|
111
|
+
self._shownTrove:Connect(instance:GetPropertyChangedSignal("Parent"), function()
|
|
112
|
+
if not instance.Parent then
|
|
113
|
+
self._shownTrove:Clean()
|
|
114
|
+
end
|
|
115
|
+
end)
|
|
116
|
+
self._shownTrove:Add(function()
|
|
117
|
+
if self.Instance == instance then
|
|
118
|
+
self.Instance = nil
|
|
119
|
+
end
|
|
120
|
+
end)
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
local function OnChildAdded(child: Instance)
|
|
125
|
+
if child.Name == childName and not self.Instance then
|
|
126
|
+
self.Instance = child
|
|
127
|
+
OnInstanceSet()
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
self._trove:Connect(parent.ChildAdded, OnChildAdded)
|
|
132
|
+
if self.Instance then
|
|
133
|
+
OnInstanceSet()
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
return self
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
--[=[
|
|
140
|
+
@return Streamable
|
|
141
|
+
@param parent Model
|
|
142
|
+
|
|
143
|
+
Constructs a streamable that watches for the PrimaryPart of the
|
|
144
|
+
given `parent` Model.
|
|
145
|
+
]=]
|
|
146
|
+
function Streamable.primary(parent: Model)
|
|
147
|
+
local self: StreamableWithInstance = {}
|
|
148
|
+
setmetatable(self, Streamable)
|
|
149
|
+
|
|
150
|
+
self._trove = Trove.new()
|
|
151
|
+
self._shown = self._trove:Construct(Signal)
|
|
152
|
+
self._shownTrove = Trove.new()
|
|
153
|
+
self._trove:Add(self._shownTrove)
|
|
154
|
+
|
|
155
|
+
self.Instance = parent.PrimaryPart
|
|
156
|
+
|
|
157
|
+
local function OnPrimaryPartChanged()
|
|
158
|
+
local primaryPart = parent.PrimaryPart
|
|
159
|
+
self._shownTrove:Clean()
|
|
160
|
+
self.Instance = primaryPart
|
|
161
|
+
if primaryPart then
|
|
162
|
+
self._shown:Fire(primaryPart, self._shownTrove)
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
self._trove:Connect(parent:GetPropertyChangedSignal("PrimaryPart"), OnPrimaryPartChanged)
|
|
167
|
+
if self.Instance then
|
|
168
|
+
OnPrimaryPartChanged()
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
return self
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
--[=[
|
|
175
|
+
@param handler (instance: Instance, trove: Trove) -> nil
|
|
176
|
+
@return Connection
|
|
177
|
+
|
|
178
|
+
Observes the instance. The handler is called anytime the
|
|
179
|
+
instance comes into existence, and the trove given is
|
|
180
|
+
cleaned up when the instance goes away.
|
|
181
|
+
|
|
182
|
+
To stop observing, disconnect the returned connection.
|
|
183
|
+
]=]
|
|
184
|
+
function Streamable:Observe(handler)
|
|
185
|
+
if self.Instance then
|
|
186
|
+
task.spawn(handler, self.Instance, self._shownTrove)
|
|
187
|
+
end
|
|
188
|
+
return self._shown:Connect(handler)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
--[=[
|
|
192
|
+
Destroys the Streamable. Any observers will be disconnected,
|
|
193
|
+
which also means that troves within observers will be cleaned
|
|
194
|
+
up. This should be called when a streamable is no longer needed.
|
|
195
|
+
]=]
|
|
196
|
+
function Streamable:Destroy()
|
|
197
|
+
self._trove:Destroy()
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
export type Streamable = typeof(Streamable.new(workspace, "X"))
|
|
201
|
+
|
|
202
|
+
return Streamable
|
|
@@ -1,80 +1,80 @@
|
|
|
1
|
-
--!strict
|
|
2
|
-
|
|
3
|
-
-- StreamableUtil
|
|
4
|
-
-- Stephen Leitnick
|
|
5
|
-
-- March 03, 2021
|
|
6
|
-
|
|
7
|
-
local Trove = require(script.Parent.Parent.Trove)
|
|
8
|
-
local _Streamable = require(script.Parent.Streamable)
|
|
9
|
-
|
|
10
|
-
type Streamables = { _Streamable.Streamable }
|
|
11
|
-
type CompoundHandler = (Streamables, any) -> nil
|
|
12
|
-
|
|
13
|
-
--[=[
|
|
14
|
-
@class StreamableUtil
|
|
15
|
-
@client
|
|
16
|
-
A utility library for the Streamable class.
|
|
17
|
-
|
|
18
|
-
```lua
|
|
19
|
-
local StreamableUtil = require(packages.Streamable).StreamableUtil
|
|
20
|
-
```
|
|
21
|
-
]=]
|
|
22
|
-
local StreamableUtil = {}
|
|
23
|
-
|
|
24
|
-
--[=[
|
|
25
|
-
@param streamables {Streamable}
|
|
26
|
-
@param handler ({[child: string]: Instance}, trove: Trove) -> nil
|
|
27
|
-
@return Trove
|
|
28
|
-
|
|
29
|
-
Creates a compound streamable around all the given streamables. The compound
|
|
30
|
-
streamable's observer handler will be fired once _all_ the given streamables
|
|
31
|
-
are in existence, and will be cleaned up when _any_ of the streamables
|
|
32
|
-
disappear.
|
|
33
|
-
|
|
34
|
-
```lua
|
|
35
|
-
local s1 = Streamable.new(workspace, "Part1")
|
|
36
|
-
local s2 = Streamable.new(workspace, "Part2")
|
|
37
|
-
|
|
38
|
-
local compoundTrove = StreamableUtil.Compound({S1 = s1, S2 = s2}, function(streamables, trove)
|
|
39
|
-
local part1 = streamables.S1.Instance
|
|
40
|
-
local part2 = streamables.S2.Instance
|
|
41
|
-
trove:Add(function()
|
|
42
|
-
print("Cleanup")
|
|
43
|
-
end)
|
|
44
|
-
end)
|
|
45
|
-
```
|
|
46
|
-
]=]
|
|
47
|
-
function StreamableUtil.Compound(streamables: Streamables, handler: CompoundHandler)
|
|
48
|
-
local compoundTrove = Trove.new()
|
|
49
|
-
local observeAllTrove = Trove.new()
|
|
50
|
-
local allAvailable = false
|
|
51
|
-
local function Check()
|
|
52
|
-
if allAvailable then
|
|
53
|
-
return
|
|
54
|
-
end
|
|
55
|
-
for _, streamable in pairs(streamables) do
|
|
56
|
-
if not streamable.Instance then
|
|
57
|
-
return
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
allAvailable = true
|
|
61
|
-
handler(streamables, observeAllTrove)
|
|
62
|
-
end
|
|
63
|
-
local function Cleanup()
|
|
64
|
-
if not allAvailable then
|
|
65
|
-
return
|
|
66
|
-
end
|
|
67
|
-
allAvailable = false
|
|
68
|
-
observeAllTrove:Clean()
|
|
69
|
-
end
|
|
70
|
-
for _, streamable in pairs(streamables) do
|
|
71
|
-
compoundTrove:Add(streamable:Observe(function(_child, trove)
|
|
72
|
-
Check()
|
|
73
|
-
trove:Add(Cleanup)
|
|
74
|
-
end))
|
|
75
|
-
end
|
|
76
|
-
compoundTrove:Add(Cleanup)
|
|
77
|
-
return compoundTrove
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
return StreamableUtil
|
|
1
|
+
--!strict
|
|
2
|
+
|
|
3
|
+
-- StreamableUtil
|
|
4
|
+
-- Stephen Leitnick
|
|
5
|
+
-- March 03, 2021
|
|
6
|
+
|
|
7
|
+
local Trove = require(script.Parent.Parent.Trove)
|
|
8
|
+
local _Streamable = require(script.Parent.Streamable)
|
|
9
|
+
|
|
10
|
+
type Streamables = { _Streamable.Streamable }
|
|
11
|
+
type CompoundHandler = (Streamables, any) -> nil
|
|
12
|
+
|
|
13
|
+
--[=[
|
|
14
|
+
@class StreamableUtil
|
|
15
|
+
@client
|
|
16
|
+
A utility library for the Streamable class.
|
|
17
|
+
|
|
18
|
+
```lua
|
|
19
|
+
local StreamableUtil = require(packages.Streamable).StreamableUtil
|
|
20
|
+
```
|
|
21
|
+
]=]
|
|
22
|
+
local StreamableUtil = {}
|
|
23
|
+
|
|
24
|
+
--[=[
|
|
25
|
+
@param streamables {Streamable}
|
|
26
|
+
@param handler ({[child: string]: Instance}, trove: Trove) -> nil
|
|
27
|
+
@return Trove
|
|
28
|
+
|
|
29
|
+
Creates a compound streamable around all the given streamables. The compound
|
|
30
|
+
streamable's observer handler will be fired once _all_ the given streamables
|
|
31
|
+
are in existence, and will be cleaned up when _any_ of the streamables
|
|
32
|
+
disappear.
|
|
33
|
+
|
|
34
|
+
```lua
|
|
35
|
+
local s1 = Streamable.new(workspace, "Part1")
|
|
36
|
+
local s2 = Streamable.new(workspace, "Part2")
|
|
37
|
+
|
|
38
|
+
local compoundTrove = StreamableUtil.Compound({S1 = s1, S2 = s2}, function(streamables, trove)
|
|
39
|
+
local part1 = streamables.S1.Instance
|
|
40
|
+
local part2 = streamables.S2.Instance
|
|
41
|
+
trove:Add(function()
|
|
42
|
+
print("Cleanup")
|
|
43
|
+
end)
|
|
44
|
+
end)
|
|
45
|
+
```
|
|
46
|
+
]=]
|
|
47
|
+
function StreamableUtil.Compound(streamables: Streamables, handler: CompoundHandler)
|
|
48
|
+
local compoundTrove = Trove.new()
|
|
49
|
+
local observeAllTrove = Trove.new()
|
|
50
|
+
local allAvailable = false
|
|
51
|
+
local function Check()
|
|
52
|
+
if allAvailable then
|
|
53
|
+
return
|
|
54
|
+
end
|
|
55
|
+
for _, streamable in pairs(streamables) do
|
|
56
|
+
if not streamable.Instance then
|
|
57
|
+
return
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
allAvailable = true
|
|
61
|
+
handler(streamables, observeAllTrove)
|
|
62
|
+
end
|
|
63
|
+
local function Cleanup()
|
|
64
|
+
if not allAvailable then
|
|
65
|
+
return
|
|
66
|
+
end
|
|
67
|
+
allAvailable = false
|
|
68
|
+
observeAllTrove:Clean()
|
|
69
|
+
end
|
|
70
|
+
for _, streamable in pairs(streamables) do
|
|
71
|
+
compoundTrove:Add(streamable:Observe(function(_child, trove)
|
|
72
|
+
Check()
|
|
73
|
+
trove:Add(Cleanup)
|
|
74
|
+
end))
|
|
75
|
+
end
|
|
76
|
+
compoundTrove:Add(Cleanup)
|
|
77
|
+
return compoundTrove
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
return StreamableUtil
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
-- Streamable
|
|
2
|
-
-- Stephen Leitnick
|
|
3
|
-
-- November 08, 2021
|
|
4
|
-
|
|
5
|
-
return {
|
|
6
|
-
Streamable = require(script.Streamable),
|
|
7
|
-
StreamableUtil = require(script.StreamableUtil),
|
|
8
|
-
}
|
|
1
|
+
-- Streamable
|
|
2
|
+
-- Stephen Leitnick
|
|
3
|
+
-- November 08, 2021
|
|
4
|
+
|
|
5
|
+
return {
|
|
6
|
+
Streamable = require(script.Streamable),
|
|
7
|
+
StreamableUtil = require(script.StreamableUtil),
|
|
8
|
+
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
[package]
|
|
2
|
-
name = "sleitnick/streamable"
|
|
3
|
-
description = "Streamable class and StreamableUtil"
|
|
4
|
-
version = "1.2.4"
|
|
5
|
-
license = "MIT"
|
|
6
|
-
authors = ["Stephen Leitnick"]
|
|
7
|
-
registry = "https://github.com/UpliftGames/wally-index"
|
|
8
|
-
realm = "shared"
|
|
9
|
-
|
|
10
|
-
[dependencies]
|
|
11
|
-
Trove = "sleitnick/trove@^0.4"
|
|
12
|
-
Signal = "sleitnick/signal@^1"
|
|
1
|
+
[package]
|
|
2
|
+
name = "sleitnick/streamable"
|
|
3
|
+
description = "Streamable class and StreamableUtil"
|
|
4
|
+
version = "1.2.4"
|
|
5
|
+
license = "MIT"
|
|
6
|
+
authors = ["Stephen Leitnick"]
|
|
7
|
+
registry = "https://github.com/UpliftGames/wally-index"
|
|
8
|
+
realm = "shared"
|
|
9
|
+
|
|
10
|
+
[dependencies]
|
|
11
|
+
Trove = "sleitnick/trove@^0.4"
|
|
12
|
+
Signal = "sleitnick/signal@^1"
|