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,75 +1,75 @@
|
|
|
1
|
-
--!strict
|
|
2
|
-
--!nolint LocalUnused
|
|
3
|
-
--!nolint LocalShadow
|
|
4
|
-
local task = nil -- Disable usage of Roblox's task scheduler
|
|
5
|
-
|
|
6
|
-
--[[
|
|
7
|
-
Calculates how the lifetimes of the two values relate. Specifically, it
|
|
8
|
-
calculates which value will be destroyed earlier or later, if it is possible
|
|
9
|
-
to infer this from their scopes.
|
|
10
|
-
]]
|
|
11
|
-
local Package = script.Parent.Parent
|
|
12
|
-
local Types = require(Package.Types)
|
|
13
|
-
local External = require(Package.External)
|
|
14
|
-
|
|
15
|
-
local function whichScopeLivesLonger(
|
|
16
|
-
scopeA: Types.Scope<unknown>,
|
|
17
|
-
scopeB: Types.Scope<unknown>
|
|
18
|
-
): "definitely-a" | "definitely-b" | "unsure"
|
|
19
|
-
-- If we can prove one scope is inside of the other scope, then the outer
|
|
20
|
-
-- scope must live longer than the inner scope (assuming idiomatic scopes).
|
|
21
|
-
-- So, we will search the scopes recursively until we find one of them, at
|
|
22
|
-
-- which point we know they must have been found inside the other scope.
|
|
23
|
-
local openSet: {Types.Scope<unknown>} = {scopeA, scopeB}
|
|
24
|
-
local nextOpenSet: {Types.Scope<unknown>} = {}
|
|
25
|
-
local openSetSize, nextOpenSetSize = 2, 0
|
|
26
|
-
local closedSet = {}
|
|
27
|
-
while openSetSize > 0 do
|
|
28
|
-
for _, scope in openSet do
|
|
29
|
-
closedSet[scope] = true
|
|
30
|
-
for _, inScope in ipairs(scope) do
|
|
31
|
-
if inScope == scopeA then
|
|
32
|
-
return "definitely-b"
|
|
33
|
-
elseif inScope == scopeB then
|
|
34
|
-
return "definitely-a"
|
|
35
|
-
elseif typeof(inScope) == "table" then
|
|
36
|
-
local inScope = inScope :: {unknown}
|
|
37
|
-
if inScope[1] ~= nil and closedSet[scope] == nil then
|
|
38
|
-
nextOpenSetSize += 1
|
|
39
|
-
nextOpenSet[nextOpenSetSize] = inScope :: Types.Scope<unknown>
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
table.clear(openSet)
|
|
45
|
-
openSet, nextOpenSet = nextOpenSet, openSet
|
|
46
|
-
openSetSize, nextOpenSetSize = nextOpenSetSize, 0
|
|
47
|
-
end
|
|
48
|
-
return "unsure"
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
local function whichLivesLonger(
|
|
52
|
-
scopeA: Types.Scope<unknown>,
|
|
53
|
-
a: unknown,
|
|
54
|
-
scopeB: Types.Scope<unknown>,
|
|
55
|
-
b: unknown
|
|
56
|
-
): "definitely-a" | "definitely-b" | "unsure"
|
|
57
|
-
if External.isTimeCritical() then
|
|
58
|
-
return "unsure"
|
|
59
|
-
elseif scopeA == scopeB then
|
|
60
|
-
local scopeA: {unknown} = scopeA
|
|
61
|
-
for index = #scopeA, 1, -1 do
|
|
62
|
-
local value = scopeA[index]
|
|
63
|
-
if value == a then
|
|
64
|
-
return "definitely-b"
|
|
65
|
-
elseif value == b then
|
|
66
|
-
return "definitely-a"
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
return "unsure"
|
|
70
|
-
else
|
|
71
|
-
return whichScopeLivesLonger(scopeA, scopeB)
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
|
|
1
|
+
--!strict
|
|
2
|
+
--!nolint LocalUnused
|
|
3
|
+
--!nolint LocalShadow
|
|
4
|
+
local task = nil -- Disable usage of Roblox's task scheduler
|
|
5
|
+
|
|
6
|
+
--[[
|
|
7
|
+
Calculates how the lifetimes of the two values relate. Specifically, it
|
|
8
|
+
calculates which value will be destroyed earlier or later, if it is possible
|
|
9
|
+
to infer this from their scopes.
|
|
10
|
+
]]
|
|
11
|
+
local Package = script.Parent.Parent
|
|
12
|
+
local Types = require(Package.Types)
|
|
13
|
+
local External = require(Package.External)
|
|
14
|
+
|
|
15
|
+
local function whichScopeLivesLonger(
|
|
16
|
+
scopeA: Types.Scope<unknown>,
|
|
17
|
+
scopeB: Types.Scope<unknown>
|
|
18
|
+
): "definitely-a" | "definitely-b" | "unsure"
|
|
19
|
+
-- If we can prove one scope is inside of the other scope, then the outer
|
|
20
|
+
-- scope must live longer than the inner scope (assuming idiomatic scopes).
|
|
21
|
+
-- So, we will search the scopes recursively until we find one of them, at
|
|
22
|
+
-- which point we know they must have been found inside the other scope.
|
|
23
|
+
local openSet: {Types.Scope<unknown>} = {scopeA, scopeB}
|
|
24
|
+
local nextOpenSet: {Types.Scope<unknown>} = {}
|
|
25
|
+
local openSetSize, nextOpenSetSize = 2, 0
|
|
26
|
+
local closedSet = {}
|
|
27
|
+
while openSetSize > 0 do
|
|
28
|
+
for _, scope in openSet do
|
|
29
|
+
closedSet[scope] = true
|
|
30
|
+
for _, inScope in ipairs(scope) do
|
|
31
|
+
if inScope == scopeA then
|
|
32
|
+
return "definitely-b"
|
|
33
|
+
elseif inScope == scopeB then
|
|
34
|
+
return "definitely-a"
|
|
35
|
+
elseif typeof(inScope) == "table" then
|
|
36
|
+
local inScope = inScope :: {unknown}
|
|
37
|
+
if inScope[1] ~= nil and closedSet[scope] == nil then
|
|
38
|
+
nextOpenSetSize += 1
|
|
39
|
+
nextOpenSet[nextOpenSetSize] = inScope :: Types.Scope<unknown>
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
table.clear(openSet)
|
|
45
|
+
openSet, nextOpenSet = nextOpenSet, openSet
|
|
46
|
+
openSetSize, nextOpenSetSize = nextOpenSetSize, 0
|
|
47
|
+
end
|
|
48
|
+
return "unsure"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
local function whichLivesLonger(
|
|
52
|
+
scopeA: Types.Scope<unknown>,
|
|
53
|
+
a: unknown,
|
|
54
|
+
scopeB: Types.Scope<unknown>,
|
|
55
|
+
b: unknown
|
|
56
|
+
): "definitely-a" | "definitely-b" | "unsure"
|
|
57
|
+
if External.isTimeCritical() then
|
|
58
|
+
return "unsure"
|
|
59
|
+
elseif scopeA == scopeB then
|
|
60
|
+
local scopeA: {unknown} = scopeA
|
|
61
|
+
for index = #scopeA, 1, -1 do
|
|
62
|
+
local value = scopeA[index]
|
|
63
|
+
if value == a then
|
|
64
|
+
return "definitely-b"
|
|
65
|
+
elseif value == b then
|
|
66
|
+
return "definitely-a"
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
return "unsure"
|
|
70
|
+
else
|
|
71
|
+
return whichScopeLivesLonger(scopeA, scopeB)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
75
|
return whichLivesLonger
|
|
@@ -1,98 +1,98 @@
|
|
|
1
|
-
--!strict
|
|
2
|
-
--!nolint LocalUnused
|
|
3
|
-
--!nolint LocalShadow
|
|
4
|
-
|
|
5
|
-
--[[
|
|
6
|
-
Roblox implementation for Fusion's abstract provider layer.
|
|
7
|
-
]]
|
|
8
|
-
|
|
9
|
-
local RunService = game:GetService("RunService")
|
|
10
|
-
local HttpService = game:GetService("HttpService")
|
|
11
|
-
|
|
12
|
-
local Package = script.Parent
|
|
13
|
-
local External = require(Package.External)
|
|
14
|
-
|
|
15
|
-
local RobloxExternal = {}
|
|
16
|
-
|
|
17
|
-
RobloxExternal.policies = {
|
|
18
|
-
allowWebLinks = RunService:IsStudio()
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
--[[
|
|
22
|
-
Sends an immediate task to the external provider. Throws if none is set.
|
|
23
|
-
]]
|
|
24
|
-
function RobloxExternal.doTaskImmediate(
|
|
25
|
-
resume: () -> ()
|
|
26
|
-
)
|
|
27
|
-
task.spawn(resume)
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
--[[
|
|
31
|
-
Sends a deferred task to the external provider. Throws if none is set.
|
|
32
|
-
]]
|
|
33
|
-
function RobloxExternal.doTaskDeferred(
|
|
34
|
-
resume: () -> ()
|
|
35
|
-
)
|
|
36
|
-
task.defer(resume)
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
--[[
|
|
40
|
-
Errors in a different thread to preserve the flow of execution.
|
|
41
|
-
]]
|
|
42
|
-
function RobloxExternal.logErrorNonFatal(
|
|
43
|
-
errorString: string
|
|
44
|
-
)
|
|
45
|
-
task.spawn(error, errorString, 0)
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
--[[
|
|
49
|
-
Shows a warning message in the output.
|
|
50
|
-
]]
|
|
51
|
-
RobloxExternal.logWarn = warn
|
|
52
|
-
|
|
53
|
-
--[[
|
|
54
|
-
Sends an update step to Fusion using the Roblox clock time.
|
|
55
|
-
]]
|
|
56
|
-
local function performUpdateStep()
|
|
57
|
-
External.performUpdateStep(os.clock())
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
--[[
|
|
61
|
-
Binds Fusion's update step to RunService step events.
|
|
62
|
-
]]
|
|
63
|
-
local stopSchedulerFunc = nil :: (() -> ())?
|
|
64
|
-
function RobloxExternal.startScheduler()
|
|
65
|
-
if stopSchedulerFunc ~= nil then
|
|
66
|
-
return
|
|
67
|
-
end
|
|
68
|
-
if RunService:IsClient() then
|
|
69
|
-
-- In cases where multiple Fusion modules are running simultaneously,
|
|
70
|
-
-- this prevents collisions.
|
|
71
|
-
local id = "FusionUpdateStep_" .. HttpService:GenerateGUID()
|
|
72
|
-
RunService:BindToRenderStep(
|
|
73
|
-
id,
|
|
74
|
-
Enum.RenderPriority.First.Value,
|
|
75
|
-
performUpdateStep
|
|
76
|
-
)
|
|
77
|
-
stopSchedulerFunc = function()
|
|
78
|
-
RunService:UnbindFromRenderStep(id)
|
|
79
|
-
end
|
|
80
|
-
else
|
|
81
|
-
local connection = RunService.Heartbeat:Connect(performUpdateStep)
|
|
82
|
-
stopSchedulerFunc = function()
|
|
83
|
-
connection:Disconnect()
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
--[[
|
|
89
|
-
Unbinds Fusion's update step from RunService step events.
|
|
90
|
-
]]
|
|
91
|
-
function RobloxExternal.stopScheduler()
|
|
92
|
-
if stopSchedulerFunc ~= nil then
|
|
93
|
-
stopSchedulerFunc()
|
|
94
|
-
stopSchedulerFunc = nil
|
|
95
|
-
end
|
|
96
|
-
end
|
|
97
|
-
|
|
1
|
+
--!strict
|
|
2
|
+
--!nolint LocalUnused
|
|
3
|
+
--!nolint LocalShadow
|
|
4
|
+
|
|
5
|
+
--[[
|
|
6
|
+
Roblox implementation for Fusion's abstract provider layer.
|
|
7
|
+
]]
|
|
8
|
+
|
|
9
|
+
local RunService = game:GetService("RunService")
|
|
10
|
+
local HttpService = game:GetService("HttpService")
|
|
11
|
+
|
|
12
|
+
local Package = script.Parent
|
|
13
|
+
local External = require(Package.External)
|
|
14
|
+
|
|
15
|
+
local RobloxExternal = {}
|
|
16
|
+
|
|
17
|
+
RobloxExternal.policies = {
|
|
18
|
+
allowWebLinks = RunService:IsStudio()
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
--[[
|
|
22
|
+
Sends an immediate task to the external provider. Throws if none is set.
|
|
23
|
+
]]
|
|
24
|
+
function RobloxExternal.doTaskImmediate(
|
|
25
|
+
resume: () -> ()
|
|
26
|
+
)
|
|
27
|
+
task.spawn(resume)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
--[[
|
|
31
|
+
Sends a deferred task to the external provider. Throws if none is set.
|
|
32
|
+
]]
|
|
33
|
+
function RobloxExternal.doTaskDeferred(
|
|
34
|
+
resume: () -> ()
|
|
35
|
+
)
|
|
36
|
+
task.defer(resume)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
--[[
|
|
40
|
+
Errors in a different thread to preserve the flow of execution.
|
|
41
|
+
]]
|
|
42
|
+
function RobloxExternal.logErrorNonFatal(
|
|
43
|
+
errorString: string
|
|
44
|
+
)
|
|
45
|
+
task.spawn(error, errorString, 0)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
--[[
|
|
49
|
+
Shows a warning message in the output.
|
|
50
|
+
]]
|
|
51
|
+
RobloxExternal.logWarn = warn
|
|
52
|
+
|
|
53
|
+
--[[
|
|
54
|
+
Sends an update step to Fusion using the Roblox clock time.
|
|
55
|
+
]]
|
|
56
|
+
local function performUpdateStep()
|
|
57
|
+
External.performUpdateStep(os.clock())
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
--[[
|
|
61
|
+
Binds Fusion's update step to RunService step events.
|
|
62
|
+
]]
|
|
63
|
+
local stopSchedulerFunc = nil :: (() -> ())?
|
|
64
|
+
function RobloxExternal.startScheduler()
|
|
65
|
+
if stopSchedulerFunc ~= nil then
|
|
66
|
+
return
|
|
67
|
+
end
|
|
68
|
+
if RunService:IsClient() then
|
|
69
|
+
-- In cases where multiple Fusion modules are running simultaneously,
|
|
70
|
+
-- this prevents collisions.
|
|
71
|
+
local id = "FusionUpdateStep_" .. HttpService:GenerateGUID()
|
|
72
|
+
RunService:BindToRenderStep(
|
|
73
|
+
id,
|
|
74
|
+
Enum.RenderPriority.First.Value,
|
|
75
|
+
performUpdateStep
|
|
76
|
+
)
|
|
77
|
+
stopSchedulerFunc = function()
|
|
78
|
+
RunService:UnbindFromRenderStep(id)
|
|
79
|
+
end
|
|
80
|
+
else
|
|
81
|
+
local connection = RunService.Heartbeat:Connect(performUpdateStep)
|
|
82
|
+
stopSchedulerFunc = function()
|
|
83
|
+
connection:Disconnect()
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
--[[
|
|
89
|
+
Unbinds Fusion's update step from RunService step events.
|
|
90
|
+
]]
|
|
91
|
+
function RobloxExternal.stopScheduler()
|
|
92
|
+
if stopSchedulerFunc ~= nil then
|
|
93
|
+
stopSchedulerFunc()
|
|
94
|
+
stopSchedulerFunc = nil
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
98
|
return RobloxExternal
|
|
@@ -1,139 +1,139 @@
|
|
|
1
|
-
--!strict
|
|
2
|
-
--!nolint LocalUnused
|
|
3
|
-
--!nolint LocalShadow
|
|
4
|
-
local task = nil -- Disable usage of Roblox's task scheduler
|
|
5
|
-
|
|
6
|
-
--[[
|
|
7
|
-
A specialised state object for tracking single values computed from a
|
|
8
|
-
user-defined computation.
|
|
9
|
-
|
|
10
|
-
https://elttob.uk/Fusion/0.3/api-reference/state/types/computed/
|
|
11
|
-
]]
|
|
12
|
-
|
|
13
|
-
local Package = script.Parent.Parent
|
|
14
|
-
local Types = require(Package.Types)
|
|
15
|
-
local External = require(Package.External)
|
|
16
|
-
-- Logging
|
|
17
|
-
local parseError = require(Package.Logging.parseError)
|
|
18
|
-
-- Utility
|
|
19
|
-
local isSimilar = require(Package.Utility.isSimilar)
|
|
20
|
-
local never = require(Package.Utility.never)
|
|
21
|
-
-- Graph
|
|
22
|
-
local depend = require(Package.Graph.depend)
|
|
23
|
-
-- State
|
|
24
|
-
local castToState = require(Package.State.castToState)
|
|
25
|
-
local peek = require(Package.State.peek)
|
|
26
|
-
-- Memory
|
|
27
|
-
local doCleanup = require(Package.Memory.doCleanup)
|
|
28
|
-
local deriveScope = require(Package.Memory.deriveScope)
|
|
29
|
-
local checkLifetime = require(Package.Memory.checkLifetime)
|
|
30
|
-
local scopePool = require(Package.Memory.scopePool)
|
|
31
|
-
-- Utility
|
|
32
|
-
local nicknames = require(Package.Utility.nicknames)
|
|
33
|
-
|
|
34
|
-
type Self<T, S> = Types.Computed<T> & {
|
|
35
|
-
_innerScope: Types.Scope<S>?,
|
|
36
|
-
_processor: (Types.Use, Types.Scope<S>) -> T
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
local class = {}
|
|
40
|
-
class.type = "State"
|
|
41
|
-
class.kind = "Computed"
|
|
42
|
-
class.timeliness = "lazy"
|
|
43
|
-
|
|
44
|
-
local METATABLE = table.freeze {__index = class}
|
|
45
|
-
|
|
46
|
-
local function Computed<T, S>(
|
|
47
|
-
scope: S & Types.Scope<unknown>,
|
|
48
|
-
processor: (Types.Use, S) -> T,
|
|
49
|
-
destructor: unknown?
|
|
50
|
-
): Types.Computed<T>
|
|
51
|
-
local createdAt = os.clock()
|
|
52
|
-
if typeof(scope) == "function" then
|
|
53
|
-
External.logError("scopeMissing", nil, "Computeds", "myScope:Computed(function(use, scope) ... end)")
|
|
54
|
-
elseif destructor ~= nil then
|
|
55
|
-
External.logWarn("destructorRedundant", "Computed")
|
|
56
|
-
end
|
|
57
|
-
local self: Self<T, S> = setmetatable(
|
|
58
|
-
{
|
|
59
|
-
createdAt = createdAt,
|
|
60
|
-
dependencySet = {},
|
|
61
|
-
dependentSet = {},
|
|
62
|
-
lastChange = nil,
|
|
63
|
-
scope = scope,
|
|
64
|
-
validity = "invalid",
|
|
65
|
-
_EXTREMELY_DANGEROUS_usedAsValue = nil,
|
|
66
|
-
_innerScope = nil,
|
|
67
|
-
_processor = processor
|
|
68
|
-
},
|
|
69
|
-
METATABLE
|
|
70
|
-
) :: any
|
|
71
|
-
local destroy = function()
|
|
72
|
-
self.scope = nil
|
|
73
|
-
for dependency in pairs(self.dependencySet) do
|
|
74
|
-
dependency.dependentSet[self] = nil
|
|
75
|
-
end
|
|
76
|
-
if self._innerScope ~= nil then
|
|
77
|
-
doCleanup(self._innerScope)
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
self.oldestTask = destroy
|
|
81
|
-
nicknames[self.oldestTask] = "Computed"
|
|
82
|
-
table.insert(scope, destroy)
|
|
83
|
-
return self
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
function class.get<T, S>(
|
|
87
|
-
_self: Self<T, S>
|
|
88
|
-
): never
|
|
89
|
-
External.logError("stateGetWasRemoved")
|
|
90
|
-
return never()
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
function class._evaluate<T, S>(
|
|
94
|
-
self: Self<T, S>
|
|
95
|
-
): boolean
|
|
96
|
-
if self.scope == nil then
|
|
97
|
-
return false
|
|
98
|
-
end
|
|
99
|
-
local outerScope = self.scope :: S & Types.Scope<unknown>
|
|
100
|
-
local innerScope = deriveScope(outerScope)
|
|
101
|
-
local function use<T>(target: Types.UsedAs<T>): T
|
|
102
|
-
local targetState = castToState(target)
|
|
103
|
-
if targetState ~= nil then
|
|
104
|
-
checkLifetime.bOutlivesA(
|
|
105
|
-
outerScope, self.oldestTask,
|
|
106
|
-
targetState.scope, targetState.oldestTask,
|
|
107
|
-
checkLifetime.formatters.useFunction
|
|
108
|
-
)
|
|
109
|
-
depend(self, targetState)
|
|
110
|
-
end
|
|
111
|
-
return peek(target)
|
|
112
|
-
end
|
|
113
|
-
local ok, newValue = xpcall(self._processor, parseError, use, innerScope)
|
|
114
|
-
local innerScope = scopePool.giveIfEmpty(innerScope)
|
|
115
|
-
if ok then
|
|
116
|
-
local similar = isSimilar(self._EXTREMELY_DANGEROUS_usedAsValue, newValue)
|
|
117
|
-
if self._innerScope ~= nil then
|
|
118
|
-
doCleanup(self._innerScope)
|
|
119
|
-
end
|
|
120
|
-
self._innerScope = innerScope
|
|
121
|
-
|
|
122
|
-
self._EXTREMELY_DANGEROUS_usedAsValue = newValue
|
|
123
|
-
return not similar
|
|
124
|
-
else
|
|
125
|
-
local errorObj = (newValue :: any) :: Types.Error
|
|
126
|
-
if innerScope ~= nil then
|
|
127
|
-
doCleanup(innerScope)
|
|
128
|
-
end
|
|
129
|
-
innerScope = nil
|
|
130
|
-
|
|
131
|
-
-- this needs to be non-fatal, because otherwise it'd disrupt the
|
|
132
|
-
-- update process
|
|
133
|
-
External.logErrorNonFatal("callbackError", errorObj)
|
|
134
|
-
return false
|
|
135
|
-
end
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
table.freeze(class)
|
|
1
|
+
--!strict
|
|
2
|
+
--!nolint LocalUnused
|
|
3
|
+
--!nolint LocalShadow
|
|
4
|
+
local task = nil -- Disable usage of Roblox's task scheduler
|
|
5
|
+
|
|
6
|
+
--[[
|
|
7
|
+
A specialised state object for tracking single values computed from a
|
|
8
|
+
user-defined computation.
|
|
9
|
+
|
|
10
|
+
https://elttob.uk/Fusion/0.3/api-reference/state/types/computed/
|
|
11
|
+
]]
|
|
12
|
+
|
|
13
|
+
local Package = script.Parent.Parent
|
|
14
|
+
local Types = require(Package.Types)
|
|
15
|
+
local External = require(Package.External)
|
|
16
|
+
-- Logging
|
|
17
|
+
local parseError = require(Package.Logging.parseError)
|
|
18
|
+
-- Utility
|
|
19
|
+
local isSimilar = require(Package.Utility.isSimilar)
|
|
20
|
+
local never = require(Package.Utility.never)
|
|
21
|
+
-- Graph
|
|
22
|
+
local depend = require(Package.Graph.depend)
|
|
23
|
+
-- State
|
|
24
|
+
local castToState = require(Package.State.castToState)
|
|
25
|
+
local peek = require(Package.State.peek)
|
|
26
|
+
-- Memory
|
|
27
|
+
local doCleanup = require(Package.Memory.doCleanup)
|
|
28
|
+
local deriveScope = require(Package.Memory.deriveScope)
|
|
29
|
+
local checkLifetime = require(Package.Memory.checkLifetime)
|
|
30
|
+
local scopePool = require(Package.Memory.scopePool)
|
|
31
|
+
-- Utility
|
|
32
|
+
local nicknames = require(Package.Utility.nicknames)
|
|
33
|
+
|
|
34
|
+
type Self<T, S> = Types.Computed<T> & {
|
|
35
|
+
_innerScope: Types.Scope<S>?,
|
|
36
|
+
_processor: (Types.Use, Types.Scope<S>) -> T
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
local class = {}
|
|
40
|
+
class.type = "State"
|
|
41
|
+
class.kind = "Computed"
|
|
42
|
+
class.timeliness = "lazy"
|
|
43
|
+
|
|
44
|
+
local METATABLE = table.freeze {__index = class}
|
|
45
|
+
|
|
46
|
+
local function Computed<T, S>(
|
|
47
|
+
scope: S & Types.Scope<unknown>,
|
|
48
|
+
processor: (Types.Use, S) -> T,
|
|
49
|
+
destructor: unknown?
|
|
50
|
+
): Types.Computed<T>
|
|
51
|
+
local createdAt = os.clock()
|
|
52
|
+
if typeof(scope) == "function" then
|
|
53
|
+
External.logError("scopeMissing", nil, "Computeds", "myScope:Computed(function(use, scope) ... end)")
|
|
54
|
+
elseif destructor ~= nil then
|
|
55
|
+
External.logWarn("destructorRedundant", "Computed")
|
|
56
|
+
end
|
|
57
|
+
local self: Self<T, S> = setmetatable(
|
|
58
|
+
{
|
|
59
|
+
createdAt = createdAt,
|
|
60
|
+
dependencySet = {},
|
|
61
|
+
dependentSet = {},
|
|
62
|
+
lastChange = nil,
|
|
63
|
+
scope = scope,
|
|
64
|
+
validity = "invalid",
|
|
65
|
+
_EXTREMELY_DANGEROUS_usedAsValue = nil,
|
|
66
|
+
_innerScope = nil,
|
|
67
|
+
_processor = processor
|
|
68
|
+
},
|
|
69
|
+
METATABLE
|
|
70
|
+
) :: any
|
|
71
|
+
local destroy = function()
|
|
72
|
+
self.scope = nil
|
|
73
|
+
for dependency in pairs(self.dependencySet) do
|
|
74
|
+
dependency.dependentSet[self] = nil
|
|
75
|
+
end
|
|
76
|
+
if self._innerScope ~= nil then
|
|
77
|
+
doCleanup(self._innerScope)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
self.oldestTask = destroy
|
|
81
|
+
nicknames[self.oldestTask] = "Computed"
|
|
82
|
+
table.insert(scope, destroy)
|
|
83
|
+
return self
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
function class.get<T, S>(
|
|
87
|
+
_self: Self<T, S>
|
|
88
|
+
): never
|
|
89
|
+
External.logError("stateGetWasRemoved")
|
|
90
|
+
return never()
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
function class._evaluate<T, S>(
|
|
94
|
+
self: Self<T, S>
|
|
95
|
+
): boolean
|
|
96
|
+
if self.scope == nil then
|
|
97
|
+
return false
|
|
98
|
+
end
|
|
99
|
+
local outerScope = self.scope :: S & Types.Scope<unknown>
|
|
100
|
+
local innerScope = deriveScope(outerScope)
|
|
101
|
+
local function use<T>(target: Types.UsedAs<T>): T
|
|
102
|
+
local targetState = castToState(target)
|
|
103
|
+
if targetState ~= nil then
|
|
104
|
+
checkLifetime.bOutlivesA(
|
|
105
|
+
outerScope, self.oldestTask,
|
|
106
|
+
targetState.scope, targetState.oldestTask,
|
|
107
|
+
checkLifetime.formatters.useFunction
|
|
108
|
+
)
|
|
109
|
+
depend(self, targetState)
|
|
110
|
+
end
|
|
111
|
+
return peek(target)
|
|
112
|
+
end
|
|
113
|
+
local ok, newValue = xpcall(self._processor, parseError, use, innerScope)
|
|
114
|
+
local innerScope = scopePool.giveIfEmpty(innerScope)
|
|
115
|
+
if ok then
|
|
116
|
+
local similar = isSimilar(self._EXTREMELY_DANGEROUS_usedAsValue, newValue)
|
|
117
|
+
if self._innerScope ~= nil then
|
|
118
|
+
doCleanup(self._innerScope)
|
|
119
|
+
end
|
|
120
|
+
self._innerScope = innerScope
|
|
121
|
+
|
|
122
|
+
self._EXTREMELY_DANGEROUS_usedAsValue = newValue
|
|
123
|
+
return not similar
|
|
124
|
+
else
|
|
125
|
+
local errorObj = (newValue :: any) :: Types.Error
|
|
126
|
+
if innerScope ~= nil then
|
|
127
|
+
doCleanup(innerScope)
|
|
128
|
+
end
|
|
129
|
+
innerScope = nil
|
|
130
|
+
|
|
131
|
+
-- this needs to be non-fatal, because otherwise it'd disrupt the
|
|
132
|
+
-- update process
|
|
133
|
+
External.logErrorNonFatal("callbackError", errorObj)
|
|
134
|
+
return false
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
table.freeze(class)
|
|
139
139
|
return Computed :: Types.ComputedConstructor
|