@trioforge/crucible 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/maths/spline/package.json +4 -0
- package/out/client/index.d.ts +7 -0
- package/out/client/init.luau +36 -1
- package/out/configs.d.ts +37 -0
- package/out/configs.luau +46 -0
- package/out/data.d.ts +224 -0
- package/out/data.luau +97 -0
- package/out/emit/configs.d.ts +4 -0
- package/out/emit/configs.luau +22 -0
- package/out/emit/data.d.ts +6 -0
- package/out/emit/data.luau +19 -0
- package/out/emit/index.d.ts +5 -1
- package/out/emit/init.luau +23 -7
- package/out/emit/network.d.ts +6 -0
- package/out/emit/network.luau +36 -0
- package/out/emit/replicated.d.ts +4 -0
- package/out/emit/replicated.luau +13 -0
- package/out/index.d.ts +8 -0
- package/out/init.luau +23 -0
- package/out/internal/binding.luau +5 -0
- package/out/internal/boot.luau +112 -8
- package/out/internal/configs/limits.d.ts +10 -0
- package/out/internal/configs/limits.luau +25 -0
- package/out/internal/configs/port.d.ts +29 -0
- package/out/internal/configs/port.luau +99 -0
- package/out/internal/configs/runtime.d.ts +21 -0
- package/out/internal/configs/runtime.luau +981 -0
- package/out/internal/data/admission.d.ts +1 -0
- package/out/internal/data/admission.luau +673 -0
- package/out/internal/data/declarations.d.ts +1 -0
- package/out/internal/data/declarations.luau +384 -0
- package/out/internal/data/envelope.d.ts +1 -0
- package/out/internal/data/envelope.luau +318 -0
- package/out/internal/data/handles.d.ts +1 -0
- package/out/internal/data/handles.luau +255 -0
- package/out/internal/data/inbox-transforms.d.ts +1 -0
- package/out/internal/data/inbox-transforms.luau +458 -0
- package/out/internal/data/inbox.d.ts +1 -0
- package/out/internal/data/inbox.luau +437 -0
- package/out/internal/data/lease.d.ts +1 -0
- package/out/internal/data/lease.luau +304 -0
- package/out/internal/data/limits.d.ts +1 -0
- package/out/internal/data/limits.luau +234 -0
- package/out/internal/data/messages.d.ts +1 -0
- package/out/internal/data/messages.luau +69 -0
- package/out/internal/data/operation-id.d.ts +1 -0
- package/out/internal/data/operation-id.luau +61 -0
- package/out/internal/data/paths.d.ts +2 -0
- package/out/internal/data/paths.luau +323 -0
- package/out/internal/data/port.d.ts +1 -0
- package/out/internal/data/port.luau +290 -0
- package/out/internal/data/profiles.d.ts +1 -0
- package/out/internal/data/profiles.luau +862 -0
- package/out/internal/data/receipts.d.ts +1 -0
- package/out/internal/data/receipts.luau +190 -0
- package/out/internal/data/record-bindings.d.ts +1 -0
- package/out/internal/data/record-bindings.luau +92 -0
- package/out/internal/data/record-declarations.d.ts +1 -0
- package/out/internal/data/record-declarations.luau +140 -0
- package/out/internal/data/records.d.ts +1 -0
- package/out/internal/data/records.luau +400 -0
- package/out/internal/data/runtime.d.ts +1 -0
- package/out/internal/data/runtime.luau +918 -0
- package/out/internal/data/scheduler.d.ts +1 -0
- package/out/internal/data/scheduler.luau +507 -0
- package/out/internal/data/session.d.ts +1 -0
- package/out/internal/data/session.luau +234 -0
- package/out/internal/data/shutdown.d.ts +1 -0
- package/out/internal/data/shutdown.luau +91 -0
- package/out/internal/data/waiters.d.ts +1 -0
- package/out/internal/data/waiters.luau +65 -0
- package/out/internal/lifecycle.luau +45 -0
- package/out/internal/network/catalog.d.ts +26 -0
- package/out/internal/network/catalog.luau +182 -0
- package/out/internal/network/claims.d.ts +1 -0
- package/out/internal/network/claims.luau +146 -0
- package/out/internal/network/client-session.d.ts +1 -0
- package/out/internal/network/client-session.luau +405 -0
- package/out/internal/network/codec.d.ts +63 -0
- package/out/internal/network/codec.luau +1183 -0
- package/out/internal/network/envelope.d.ts +1 -0
- package/out/internal/network/envelope.luau +247 -0
- package/out/internal/network/limits.d.ts +26 -0
- package/out/internal/network/limits.luau +55 -0
- package/out/internal/network/port.d.ts +1 -0
- package/out/internal/network/port.luau +19 -0
- package/out/internal/network/roblox-network-port.d.ts +1 -0
- package/out/internal/network/roblox-network-port.luau +105 -0
- package/out/internal/network/schema.d.ts +72 -0
- package/out/internal/network/schema.luau +386 -0
- package/out/internal/network/server-session.d.ts +1 -0
- package/out/internal/network/server-session.luau +395 -0
- package/out/internal/network/session.d.ts +1 -0
- package/out/internal/network/session.luau +266 -0
- package/out/internal/reactive/context.d.ts +1 -0
- package/out/internal/reactive/context.luau +149 -0
- package/out/internal/reactive/flush.d.ts +1 -0
- package/out/internal/reactive/flush.luau +355 -0
- package/out/internal/reactive/graph.d.ts +1 -0
- package/out/internal/reactive/graph.luau +626 -0
- package/out/internal/reactive/limits.d.ts +1 -0
- package/out/internal/reactive/limits.luau +54 -0
- package/out/internal/reactive/ownership.d.ts +1 -0
- package/out/internal/reactive/ownership.luau +626 -0
- package/out/internal/registry.luau +10 -1
- package/out/internal/sync/client-sync.d.ts +1 -0
- package/out/internal/sync/client-sync.luau +157 -0
- package/out/internal/sync/declarations.d.ts +1 -0
- package/out/internal/sync/declarations.luau +276 -0
- package/out/internal/sync/frame.d.ts +1 -0
- package/out/internal/sync/frame.luau +91 -0
- package/out/internal/sync/server-sync.d.ts +1 -0
- package/out/internal/sync/server-sync.luau +502 -0
- package/out/internal/sync/values.d.ts +1 -0
- package/out/internal/sync/values.luau +930 -0
- package/out/maths/spline/curve.d.ts +35 -0
- package/out/maths/spline/curve.luau +1122 -0
- package/out/maths/spline/index.d.ts +2 -0
- package/out/maths/spline/init.luau +8 -0
- package/out/network.d.ts +66 -0
- package/out/network.luau +24 -0
- package/out/reactive.d.ts +76 -0
- package/out/reactive.luau +136 -0
- package/out/replicated.d.ts +38 -0
- package/out/replicated.luau +45 -0
- package/out/server/data.d.ts +54 -0
- package/out/server/data.luau +44 -0
- package/out/server/index.d.ts +17 -0
- package/out/server/init.luau +58 -4
- package/out/server/publish.d.ts +20 -0
- package/out/server/publish.luau +24 -0
- package/out/testing/index.d.ts +38 -0
- package/out/testing/init.luau +189 -0
- package/out/util/random/index.d.ts +24 -0
- package/out/util/random/init.luau +301 -0
- package/out/vide/index.d.ts +7 -0
- package/out/vide/init.luau +50 -0
- package/package.json +28 -2
- package/testing/package.json +4 -0
- package/transformer/data.cjs +72 -0
- package/transformer/declarations.cjs +153 -0
- package/transformer/index.js +87 -23
- package/transformer/network.cjs +961 -0
- package/util/random/package.json +4 -0
- package/vide/package.json +4 -0
package/out/index.d.ts
CHANGED
|
@@ -10,3 +10,11 @@ export interface BootOptions {
|
|
|
10
10
|
}
|
|
11
11
|
export { Logging, LogLevel } from "./logging";
|
|
12
12
|
export type { Logger, LogRecord, LogSink, SinkSubscription, LogContext, LogProperties } from "./logging";
|
|
13
|
+
export { state, computed, effect, watch, untracked, scope, onCleanup, own } from "./reactive";
|
|
14
|
+
export type { Readable, State, Ownable } from "./reactive";
|
|
15
|
+
export { replicated, replicatedPerPlayer, syncStatus } from "./replicated";
|
|
16
|
+
export type { Replicated, ReplicatedPerPlayer, SyncStatus } from "./replicated";
|
|
17
|
+
export { toServer, toClient, askServer, receive, ClientReady } from "./network";
|
|
18
|
+
export type { ToServer, ToClient, AskServer, Receiver, ReceiveTarget, ReceiveCallback, AskResult, AskFailure, AskOptions, PayloadArgs, f32, f64, u8, u16, u32, } from "./network";
|
|
19
|
+
export { profileStore, serverOnly, replicatedPaths } from "./data";
|
|
20
|
+
export type { ProfileStore, ProfileOptions, ServerOnly, ProfileData, ClientData, Profile, ClientProfile, DataHandle, ReadHandle, WriteHandle, ArrayWrites, ReservedName, Json, JsonRecord, Migration, } from "./data";
|
package/out/init.luau
CHANGED
|
@@ -8,4 +8,27 @@ exports.CrucibleBehaviour = TS.import(script, script, "crucible-behaviour").Cruc
|
|
|
8
8
|
local _logging = TS.import(script, script, "logging")
|
|
9
9
|
exports.Logging = _logging.Logging
|
|
10
10
|
exports.LogLevel = _logging.LogLevel
|
|
11
|
+
local _reactive = TS.import(script, script, "reactive")
|
|
12
|
+
exports.state = _reactive.state
|
|
13
|
+
exports.computed = _reactive.computed
|
|
14
|
+
exports.effect = _reactive.effect
|
|
15
|
+
exports.watch = _reactive.watch
|
|
16
|
+
exports.untracked = _reactive.untracked
|
|
17
|
+
exports.scope = _reactive.scope
|
|
18
|
+
exports.onCleanup = _reactive.onCleanup
|
|
19
|
+
exports.own = _reactive.own
|
|
20
|
+
local _replicated = TS.import(script, script, "replicated")
|
|
21
|
+
exports.replicated = _replicated.replicated
|
|
22
|
+
exports.replicatedPerPlayer = _replicated.replicatedPerPlayer
|
|
23
|
+
exports.syncStatus = _replicated.syncStatus
|
|
24
|
+
local _network = TS.import(script, script, "network")
|
|
25
|
+
exports.toServer = _network.toServer
|
|
26
|
+
exports.toClient = _network.toClient
|
|
27
|
+
exports.askServer = _network.askServer
|
|
28
|
+
exports.receive = _network.receive
|
|
29
|
+
exports.ClientReady = _network.ClientReady
|
|
30
|
+
local _data = TS.import(script, script, "data")
|
|
31
|
+
exports.profileStore = _data.profileStore
|
|
32
|
+
exports.serverOnly = _data.serverOnly
|
|
33
|
+
exports.replicatedPaths = _data.replicatedPaths
|
|
11
34
|
return exports
|
|
@@ -27,6 +27,10 @@ local scopeTarget
|
|
|
27
27
|
local function port()
|
|
28
28
|
return installed or error("Crucible binding used before boot")
|
|
29
29
|
end
|
|
30
|
+
--* @internal The port boot installed, for framework Subsystems that connect engine events.
|
|
31
|
+
local function enginePort()
|
|
32
|
+
return port()
|
|
33
|
+
end
|
|
30
34
|
--* @internal
|
|
31
35
|
local function useEngine(engine)
|
|
32
36
|
installed = engine
|
|
@@ -597,6 +601,7 @@ local function forget(state)
|
|
|
597
601
|
end
|
|
598
602
|
end
|
|
599
603
|
return {
|
|
604
|
+
enginePort = enginePort,
|
|
600
605
|
useEngine = useEngine,
|
|
601
606
|
defaultAccepts = defaultAccepts,
|
|
602
607
|
construct = construct,
|
package/out/internal/boot.luau
CHANGED
|
@@ -26,6 +26,16 @@ local records = _registry.records
|
|
|
26
26
|
local seal = _registry.seal
|
|
27
27
|
local robloxPort = TS.import(script, script.Parent, "roblox-port").robloxPort
|
|
28
28
|
local Scheduler = TS.import(script, script.Parent, "scheduler").Scheduler
|
|
29
|
+
local _flush = TS.import(script, script.Parent, "reactive", "flush")
|
|
30
|
+
local holdBarrier = _flush.holdBarrier
|
|
31
|
+
local releaseBarrier = _flush.releaseBarrier
|
|
32
|
+
local useReactivePort = _flush.useReactivePort
|
|
33
|
+
local endInterval = TS.import(script, script.Parent, "reactive", "ownership").endInterval
|
|
34
|
+
local _declarations = TS.import(script, script.Parent, "sync", "declarations")
|
|
35
|
+
local rollbackDeclarations = _declarations.rollbackDeclarations
|
|
36
|
+
local sealDeclarations = _declarations.sealDeclarations
|
|
37
|
+
local Logging = TS.import(script, script.Parent.Parent, "logging").Logging
|
|
38
|
+
local log = Logging:getLogger("Crucible.Boot")
|
|
29
39
|
--* @internal
|
|
30
40
|
local BOOT_CLASSES = { Subsystem, CrucibleBehaviour }
|
|
31
41
|
--* @internal
|
|
@@ -35,6 +45,45 @@ local PATTERN_PREFIX = "crucible-path:"
|
|
|
35
45
|
local SHUTDOWN_DEADLINE_SECONDS = 25
|
|
36
46
|
--* @internal
|
|
37
47
|
local SHUTDOWN_TIMEOUT_SECONDS = 28
|
|
48
|
+
local clock
|
|
49
|
+
local sweep
|
|
50
|
+
--* @internal
|
|
51
|
+
--* @internal The one monotonic clock, core's and data's (data rules 25, 105).
|
|
52
|
+
local function bootClock()
|
|
53
|
+
return (clock or os.clock)()
|
|
54
|
+
end
|
|
55
|
+
--* @internal Undefined until the sweep has begun.
|
|
56
|
+
local function shutdownProgress(subsystem)
|
|
57
|
+
if sweep == nil then
|
|
58
|
+
return nil
|
|
59
|
+
end
|
|
60
|
+
local pending = 0
|
|
61
|
+
local notStarted = 0
|
|
62
|
+
for _, record in sweep.order do
|
|
63
|
+
local _condition = sweep.finished[record] ~= nil
|
|
64
|
+
if not _condition then
|
|
65
|
+
local _result = record.state
|
|
66
|
+
if _result ~= nil then
|
|
67
|
+
_result = _result.object
|
|
68
|
+
end
|
|
69
|
+
_condition = _result == subsystem
|
|
70
|
+
end
|
|
71
|
+
if _condition then
|
|
72
|
+
continue
|
|
73
|
+
end
|
|
74
|
+
pending += 1
|
|
75
|
+
if not (sweep.started[record] ~= nil) then
|
|
76
|
+
notStarted += 1
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
return {
|
|
80
|
+
startedAt = sweep.startTime,
|
|
81
|
+
forceStartAt = sweep.startTime + SHUTDOWN_DEADLINE_SECONDS,
|
|
82
|
+
deadline = sweep.startTime + SHUTDOWN_TIMEOUT_SECONDS,
|
|
83
|
+
pending = pending,
|
|
84
|
+
notStarted = notStarted,
|
|
85
|
+
}
|
|
86
|
+
end
|
|
38
87
|
--* @internal
|
|
39
88
|
local function parsePattern(pattern)
|
|
40
89
|
local _pattern = pattern
|
|
@@ -214,6 +263,12 @@ local function shutdown(port, order)
|
|
|
214
263
|
end
|
|
215
264
|
end
|
|
216
265
|
local startTime = port.clock()
|
|
266
|
+
sweep = {
|
|
267
|
+
startTime = startTime,
|
|
268
|
+
order = order,
|
|
269
|
+
started = started,
|
|
270
|
+
finished = finished,
|
|
271
|
+
}
|
|
217
272
|
while true do
|
|
218
273
|
-- ▼ ReadonlySet.size ▼
|
|
219
274
|
local _size = 0
|
|
@@ -287,6 +342,8 @@ local function shutdown(port, order)
|
|
|
287
342
|
end
|
|
288
343
|
--* @internal
|
|
289
344
|
local function ignite(port, side, options)
|
|
345
|
+
clock = port.clock
|
|
346
|
+
sweep = nil
|
|
290
347
|
local singletons = seal({
|
|
291
348
|
renders = side.renders,
|
|
292
349
|
})
|
|
@@ -330,6 +387,8 @@ local function ignite(port, side, options)
|
|
|
330
387
|
end
|
|
331
388
|
end
|
|
332
389
|
useEngine(port)
|
|
390
|
+
holdBarrier()
|
|
391
|
+
useReactivePort(port)
|
|
333
392
|
useImplementerPort(port)
|
|
334
393
|
useEffects({
|
|
335
394
|
construct = function(s)
|
|
@@ -391,6 +450,7 @@ local function ignite(port, side, options)
|
|
|
391
450
|
diagnose = function(s, hook, err)
|
|
392
451
|
return runtimeDiagnostic("error", `{where(port, s)} {HOOK_NAMES[hook + 1]} failed: {tostring(err)}`)
|
|
393
452
|
end,
|
|
453
|
+
disabled = endInterval,
|
|
394
454
|
})
|
|
395
455
|
local ok, err = pcall(function()
|
|
396
456
|
local _exp_1 = records()
|
|
@@ -427,6 +487,36 @@ local function ignite(port, side, options)
|
|
|
427
487
|
if not ok then
|
|
428
488
|
reject(tostring(err))
|
|
429
489
|
end
|
|
490
|
+
if failure == nil then
|
|
491
|
+
local unbooted = nil
|
|
492
|
+
local finalized, finalizeErr = pcall(function()
|
|
493
|
+
-- Roblox cannot unbind BindToClose, so the callback checks that this boot committed.
|
|
494
|
+
if side.name == "server" then
|
|
495
|
+
port.bindToClose(function()
|
|
496
|
+
if stage ~= "committed" then
|
|
497
|
+
return nil
|
|
498
|
+
end
|
|
499
|
+
shutdown(port, singletons)
|
|
500
|
+
side.network:close()
|
|
501
|
+
end)
|
|
502
|
+
end
|
|
503
|
+
unbooted = side.booted()
|
|
504
|
+
if side.name == "client" then
|
|
505
|
+
sealDeclarations()
|
|
506
|
+
end
|
|
507
|
+
side.network:commit()
|
|
508
|
+
end)
|
|
509
|
+
if not finalized then
|
|
510
|
+
local undo = unbooted
|
|
511
|
+
if undo ~= nil then
|
|
512
|
+
local undone, undoErr = pcall(undo)
|
|
513
|
+
if not undone then
|
|
514
|
+
runtimeDiagnostic("error", `Crucible: undoing booted failed: {tostring(undoErr)}`)
|
|
515
|
+
end
|
|
516
|
+
end
|
|
517
|
+
reject(`boot finalization failed: {tostring(finalizeErr)}`)
|
|
518
|
+
end
|
|
519
|
+
end
|
|
430
520
|
if failure ~= nil then
|
|
431
521
|
for s in owned do
|
|
432
522
|
if not hasEnded(s) then
|
|
@@ -435,23 +525,37 @@ local function ignite(port, side, options)
|
|
|
435
525
|
end
|
|
436
526
|
drain()
|
|
437
527
|
table.clear(owned)
|
|
528
|
+
releaseBarrier()
|
|
438
529
|
error(`Crucible boot failed: {failure}`, 0)
|
|
439
530
|
end
|
|
440
531
|
stage = "committed"
|
|
441
532
|
table.clear(owned)
|
|
442
|
-
|
|
443
|
-
port.bindToClose(function()
|
|
444
|
-
return shutdown(port, singletons)
|
|
445
|
-
end)
|
|
446
|
-
end
|
|
447
|
-
side.booted()
|
|
533
|
+
releaseBarrier()
|
|
448
534
|
end
|
|
449
535
|
--* @internal
|
|
450
536
|
local function boot(side, options)
|
|
451
|
-
|
|
452
|
-
|
|
537
|
+
local ok, err = pcall(function()
|
|
538
|
+
side.network:open()
|
|
539
|
+
load(options.load)
|
|
540
|
+
side.network:loaded()
|
|
541
|
+
if side.name == "server" then
|
|
542
|
+
sealDeclarations()
|
|
543
|
+
end
|
|
544
|
+
ignite(robloxPort(), side, options)
|
|
545
|
+
end)
|
|
546
|
+
if ok then
|
|
547
|
+
log:debug("Crucible booted on the {side}", {
|
|
548
|
+
side = side.name,
|
|
549
|
+
})
|
|
550
|
+
return nil
|
|
551
|
+
end
|
|
552
|
+
side.network:close()
|
|
553
|
+
rollbackDeclarations()
|
|
554
|
+
error(err, 0)
|
|
453
555
|
end
|
|
454
556
|
return {
|
|
557
|
+
bootClock = bootClock,
|
|
558
|
+
shutdownProgress = shutdownProgress,
|
|
455
559
|
parsePattern = parsePattern,
|
|
456
560
|
load = load,
|
|
457
561
|
ignite = ignite,
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const MAX_CONFIG_DECLARATIONS = 1000;
|
|
2
|
+
export declare const CONFIG_NAME_MAX_BYTES = 64;
|
|
3
|
+
export declare const CONFIG_VALUE_MAX_BYTES = 100000;
|
|
4
|
+
export declare const CONFIG_ADMISSION_VISITS = 100000;
|
|
5
|
+
export declare const CONFIG_REQUEST_CONCURRENCY = 4;
|
|
6
|
+
export declare const CONFIG_FETCH_RETRY_BASE_SECONDS = 1;
|
|
7
|
+
export declare const CONFIG_FETCH_RETRY_CAP_SECONDS = 30;
|
|
8
|
+
export declare const CONFIG_REFRESH_TIMEOUT_SECONDS = 10;
|
|
9
|
+
export declare const CONFIG_VALUE_DEPTH = 28;
|
|
10
|
+
export declare const CONFIG_STRING_MAX_BYTES = 65536;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local MAX_CONFIG_DECLARATIONS = 1_000
|
|
3
|
+
local CONFIG_NAME_MAX_BYTES = 64
|
|
4
|
+
local CONFIG_VALUE_MAX_BYTES = 100_000
|
|
5
|
+
local CONFIG_ADMISSION_VISITS = 100_000
|
|
6
|
+
local CONFIG_REQUEST_CONCURRENCY = 4
|
|
7
|
+
local CONFIG_FETCH_RETRY_BASE_SECONDS = 1
|
|
8
|
+
local CONFIG_FETCH_RETRY_CAP_SECONDS = 30
|
|
9
|
+
local CONFIG_REFRESH_TIMEOUT_SECONDS = 10
|
|
10
|
+
-- Rule 97 admits configs by rule 76's walk, whose depth and string bounds are data's PERSIST_DEPTH and
|
|
11
|
+
-- PERSIST_STRING_BYTES. Data's limits module is not under configs yet, so the values are restated here.
|
|
12
|
+
local CONFIG_VALUE_DEPTH = 28
|
|
13
|
+
local CONFIG_STRING_MAX_BYTES = 65_536
|
|
14
|
+
return {
|
|
15
|
+
MAX_CONFIG_DECLARATIONS = MAX_CONFIG_DECLARATIONS,
|
|
16
|
+
CONFIG_NAME_MAX_BYTES = CONFIG_NAME_MAX_BYTES,
|
|
17
|
+
CONFIG_VALUE_MAX_BYTES = CONFIG_VALUE_MAX_BYTES,
|
|
18
|
+
CONFIG_ADMISSION_VISITS = CONFIG_ADMISSION_VISITS,
|
|
19
|
+
CONFIG_REQUEST_CONCURRENCY = CONFIG_REQUEST_CONCURRENCY,
|
|
20
|
+
CONFIG_FETCH_RETRY_BASE_SECONDS = CONFIG_FETCH_RETRY_BASE_SECONDS,
|
|
21
|
+
CONFIG_FETCH_RETRY_CAP_SECONDS = CONFIG_FETCH_RETRY_CAP_SECONDS,
|
|
22
|
+
CONFIG_REFRESH_TIMEOUT_SECONDS = CONFIG_REFRESH_TIMEOUT_SECONDS,
|
|
23
|
+
CONFIG_VALUE_DEPTH = CONFIG_VALUE_DEPTH,
|
|
24
|
+
CONFIG_STRING_MAX_BYTES = CONFIG_STRING_MAX_BYTES,
|
|
25
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Disconnect } from "../port";
|
|
2
|
+
export interface ConfigSnapshotPort {
|
|
3
|
+
/** `GetValue`: nil for a missing key. A JSON config may arrive as a table or as its text. */
|
|
4
|
+
readonly get: (key: string) => unknown;
|
|
5
|
+
/** `Refresh`. Yields and may throw. */
|
|
6
|
+
readonly refresh: () => void;
|
|
7
|
+
/** Unmeasured in Studio: whether this turns true without `UpdateAvailable`. Runtime treats the two as independent. */
|
|
8
|
+
readonly outdated: () => boolean;
|
|
9
|
+
/** `Error` is `LoadFailed`. */
|
|
10
|
+
readonly failed: () => boolean;
|
|
11
|
+
readonly onUpdateAvailable: (listener: () => void) => Disconnect;
|
|
12
|
+
}
|
|
13
|
+
/** What configs ask of the engine. Requests yield and may throw. */
|
|
14
|
+
export interface ConfigPort {
|
|
15
|
+
readonly global: () => ConfigSnapshotPort;
|
|
16
|
+
readonly forPlayer: (player: Player) => ConfigSnapshotPort;
|
|
17
|
+
readonly players: () => readonly Player[];
|
|
18
|
+
readonly onPlayerAdded: (listener: (player: Player) => void) => Disconnect;
|
|
19
|
+
readonly onPlayerRemoving: (listener: (player: Player) => void) => Disconnect;
|
|
20
|
+
readonly wait: (seconds: number) => void;
|
|
21
|
+
/** Uniform in [0, 1). */
|
|
22
|
+
readonly random: () => number;
|
|
23
|
+
readonly decodeJson: (text: string) => unknown;
|
|
24
|
+
/** The JSON text length of a decoded value. Throws for a value JSON cannot hold. */
|
|
25
|
+
readonly jsonBytes: (value: object) => number;
|
|
26
|
+
}
|
|
27
|
+
export declare function installConfigPort(value: ConfigPort): void;
|
|
28
|
+
export declare function configPort(): ConfigPort;
|
|
29
|
+
export declare function createRobloxConfigPort(): ConfigPort;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
--* What configs ask of the engine. Requests yield and may throw.
|
|
3
|
+
local port
|
|
4
|
+
local function installConfigPort(value)
|
|
5
|
+
local _arg0 = port == nil
|
|
6
|
+
assert(_arg0, "Config port already selected")
|
|
7
|
+
port = value
|
|
8
|
+
end
|
|
9
|
+
local createRobloxConfigPort
|
|
10
|
+
local function configPort()
|
|
11
|
+
if port == nil then
|
|
12
|
+
port = createRobloxConfigPort()
|
|
13
|
+
end
|
|
14
|
+
return port
|
|
15
|
+
end
|
|
16
|
+
local EMPTY = table.freeze({
|
|
17
|
+
get = function()
|
|
18
|
+
return nil
|
|
19
|
+
end,
|
|
20
|
+
refresh = function() end,
|
|
21
|
+
outdated = function()
|
|
22
|
+
return false
|
|
23
|
+
end,
|
|
24
|
+
failed = function()
|
|
25
|
+
return false
|
|
26
|
+
end,
|
|
27
|
+
onUpdateAvailable = function()
|
|
28
|
+
return function() end
|
|
29
|
+
end,
|
|
30
|
+
})
|
|
31
|
+
local function snapshotPort(snapshot)
|
|
32
|
+
return {
|
|
33
|
+
get = function(key)
|
|
34
|
+
return snapshot:GetValue(key)
|
|
35
|
+
end,
|
|
36
|
+
refresh = function()
|
|
37
|
+
return snapshot:Refresh()
|
|
38
|
+
end,
|
|
39
|
+
outdated = function()
|
|
40
|
+
return snapshot.Outdated
|
|
41
|
+
end,
|
|
42
|
+
failed = function()
|
|
43
|
+
return snapshot.Error == Enum.ConfigSnapshotErrorState.LoadFailed
|
|
44
|
+
end,
|
|
45
|
+
onUpdateAvailable = function(listener)
|
|
46
|
+
local connection = snapshot.UpdateAvailable:Connect(listener)
|
|
47
|
+
return function()
|
|
48
|
+
return connection:Disconnect()
|
|
49
|
+
end
|
|
50
|
+
end,
|
|
51
|
+
}
|
|
52
|
+
end
|
|
53
|
+
function createRobloxConfigPort()
|
|
54
|
+
local players = game:GetService("Players")
|
|
55
|
+
local http = game:GetService("HttpService")
|
|
56
|
+
local live = not game:GetService("RunService"):IsStudio() or game:GetService("ServerStorage"):GetAttribute("CrucibleLiveData") == true
|
|
57
|
+
local service = if live then game:GetService("ConfigService") else nil
|
|
58
|
+
local random = Random.new()
|
|
59
|
+
return {
|
|
60
|
+
global = function()
|
|
61
|
+
return if service == nil then EMPTY else snapshotPort(service:GetConfigAsync())
|
|
62
|
+
end,
|
|
63
|
+
forPlayer = function(player)
|
|
64
|
+
return if service == nil then EMPTY else snapshotPort(service:GetConfigForPlayerAsync(player))
|
|
65
|
+
end,
|
|
66
|
+
players = function()
|
|
67
|
+
return players:GetPlayers()
|
|
68
|
+
end,
|
|
69
|
+
onPlayerAdded = function(listener)
|
|
70
|
+
local connection = players.PlayerAdded:Connect(listener)
|
|
71
|
+
return function()
|
|
72
|
+
return connection:Disconnect()
|
|
73
|
+
end
|
|
74
|
+
end,
|
|
75
|
+
onPlayerRemoving = function(listener)
|
|
76
|
+
local connection = players.PlayerRemoving:Connect(listener)
|
|
77
|
+
return function()
|
|
78
|
+
return connection:Disconnect()
|
|
79
|
+
end
|
|
80
|
+
end,
|
|
81
|
+
wait = function(seconds)
|
|
82
|
+
task.wait(seconds)
|
|
83
|
+
end,
|
|
84
|
+
random = function()
|
|
85
|
+
return random:NextNumber()
|
|
86
|
+
end,
|
|
87
|
+
decodeJson = function(text)
|
|
88
|
+
return http:JSONDecode(text)
|
|
89
|
+
end,
|
|
90
|
+
jsonBytes = function(value)
|
|
91
|
+
return #http:JSONEncode(value)
|
|
92
|
+
end,
|
|
93
|
+
}
|
|
94
|
+
end
|
|
95
|
+
return {
|
|
96
|
+
installConfigPort = installConfigPort,
|
|
97
|
+
configPort = configPort,
|
|
98
|
+
createRobloxConfigPort = createRobloxConfigPort,
|
|
99
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type Node } from "../network/schema";
|
|
2
|
+
import { type StateNode } from "../reactive/graph";
|
|
3
|
+
export type ConfigKind = "global" | "player";
|
|
4
|
+
/** One value a reader sees. Commit is its only writer. */
|
|
5
|
+
/** A config value as reactive state, so a read is tracked (rule 93) and a commit wakes its readers once. */
|
|
6
|
+
type Cell = StateNode;
|
|
7
|
+
export interface Declaration {
|
|
8
|
+
readonly name: string;
|
|
9
|
+
readonly kind: ConfigKind;
|
|
10
|
+
readonly node: Node;
|
|
11
|
+
readonly fallback: unknown;
|
|
12
|
+
/** The value admitted from the global snapshot. */
|
|
13
|
+
readonly global: Cell;
|
|
14
|
+
}
|
|
15
|
+
export declare function declare(name: string, kind: ConfigKind, fallback: unknown, node: Node): Declaration;
|
|
16
|
+
export declare function readGlobal(declaration: Declaration): unknown;
|
|
17
|
+
export declare function readPlayer(declaration: Declaration, player: Player): unknown;
|
|
18
|
+
export declare function ready(player?: Player): boolean;
|
|
19
|
+
export declare function refresh(): boolean;
|
|
20
|
+
export declare function installConfigRuntime(): void;
|
|
21
|
+
export {};
|