@trioforge/crucible 0.0.0-stage → 0.2.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/LICENSE +21 -0
- package/client/package.json +4 -0
- package/emit/package.json +4 -0
- package/out/all.d.ts +7 -0
- package/out/all.luau +2 -0
- package/out/attribute.d.ts +7 -0
- package/out/attribute.luau +7 -0
- package/out/client/index.d.ts +10 -0
- package/out/client/init.luau +55 -0
- package/out/configs.d.ts +37 -0
- package/out/configs.luau +46 -0
- package/out/crucible-behaviour.d.ts +16 -0
- package/out/crucible-behaviour.luau +78 -0
- package/out/crucible-object.d.ts +10 -0
- package/out/crucible-object.luau +69 -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 +45 -0
- package/out/emit/init.luau +101 -0
- 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 +20 -0
- package/out/init.luau +34 -0
- package/out/inject.d.ts +1 -0
- package/out/inject.luau +7 -0
- package/out/internal/binding.d.ts +1 -0
- package/out/internal/binding.luau +615 -0
- package/out/internal/boot.d.ts +1 -0
- package/out/internal/boot.luau +562 -0
- 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/construction-claim.d.ts +1 -0
- package/out/internal/construction-claim.luau +26 -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/dense-list.d.ts +1 -0
- package/out/internal/dense-list.luau +155 -0
- package/out/internal/diagnostics.d.ts +1 -0
- package/out/internal/diagnostics.luau +29 -0
- package/out/internal/hooks.d.ts +1 -0
- package/out/internal/hooks.luau +53 -0
- package/out/internal/implementers.d.ts +1 -0
- package/out/internal/implementers.luau +119 -0
- package/out/internal/lifecycle.d.ts +1 -0
- package/out/internal/lifecycle.luau +912 -0
- package/out/internal/log-output.d.ts +1 -0
- package/out/internal/log-output.luau +106 -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 +154 -0
- package/out/internal/network/client-session.d.ts +1 -0
- package/out/internal/network/client-session.luau +403 -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 +393 -0
- package/out/internal/network/session.d.ts +1 -0
- package/out/internal/network/session.luau +266 -0
- package/out/internal/port.d.ts +1 -0
- package/out/internal/port.luau +12 -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.d.ts +1 -0
- package/out/internal/registry.luau +455 -0
- package/out/internal/roblox-port.d.ts +1 -0
- package/out/internal/roblox-port.luau +117 -0
- package/out/internal/runner.d.ts +1 -0
- package/out/internal/runner.luau +86 -0
- package/out/internal/scheduler.d.ts +1 -0
- package/out/internal/scheduler.luau +207 -0
- package/out/internal/state.d.ts +1 -0
- package/out/internal/state.luau +41 -0
- 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/log-level.d.ts +7 -0
- package/out/log-level.luau +21 -0
- package/out/logging.d.ts +34 -0
- package/out/logging.luau +233 -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 +18 -0
- package/out/server/init.luau +62 -0
- package/out/server/publish.d.ts +20 -0
- package/out/server/publish.luau +24 -0
- package/out/subsystem.d.ts +4 -0
- package/out/subsystem.luau +30 -0
- package/out/vide/index.d.ts +7 -0
- package/out/vide/init.luau +50 -0
- package/package.json +52 -5
- package/server/package.json +4 -0
- package/transformer/data.cjs +72 -0
- package/transformer/declarations.cjs +153 -0
- package/transformer/diagnostics.cjs +19 -0
- package/transformer/index.js +741 -0
- package/transformer/network.cjs +961 -0
- package/transformer/type-id.cjs +80 -0
- package/vide/package.json +4 -0
- package/README.md +0 -3
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local LogLevel
|
|
3
|
+
do
|
|
4
|
+
local _inverse = {}
|
|
5
|
+
LogLevel = setmetatable({}, {
|
|
6
|
+
__index = _inverse,
|
|
7
|
+
})
|
|
8
|
+
LogLevel.Debug = 0
|
|
9
|
+
_inverse[0] = "Debug"
|
|
10
|
+
LogLevel.Info = 1
|
|
11
|
+
_inverse[1] = "Info"
|
|
12
|
+
LogLevel.Warning = 2
|
|
13
|
+
_inverse[2] = "Warning"
|
|
14
|
+
LogLevel.Error = 3
|
|
15
|
+
_inverse[3] = "Error"
|
|
16
|
+
LogLevel.Off = 4
|
|
17
|
+
_inverse[4] = "Off"
|
|
18
|
+
end
|
|
19
|
+
return {
|
|
20
|
+
LogLevel = LogLevel,
|
|
21
|
+
}
|
package/out/logging.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { LogLevel } from "./log-level";
|
|
2
|
+
export { LogLevel } from "./log-level";
|
|
3
|
+
export type LogContext = Readonly<Record<string, unknown>>;
|
|
4
|
+
export type LogProperties = Readonly<Record<string, string | number | boolean>>;
|
|
5
|
+
export interface LogRecord {
|
|
6
|
+
readonly sequence: number;
|
|
7
|
+
readonly time: number;
|
|
8
|
+
readonly source: string;
|
|
9
|
+
readonly level: Exclude<LogLevel, LogLevel.Off>;
|
|
10
|
+
readonly template: string;
|
|
11
|
+
readonly context: LogProperties;
|
|
12
|
+
readonly message: string;
|
|
13
|
+
readonly traceback?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface LogSink {
|
|
16
|
+
readonly write: (record: LogRecord) => void;
|
|
17
|
+
}
|
|
18
|
+
export interface SinkSubscription {
|
|
19
|
+
setMinimum(level: LogLevel): void;
|
|
20
|
+
disconnect(): void;
|
|
21
|
+
}
|
|
22
|
+
export interface Logger {
|
|
23
|
+
isEnabled(level: Exclude<LogLevel, LogLevel.Off>): boolean;
|
|
24
|
+
debug(template: string, context?: LogContext): void;
|
|
25
|
+
info(template: string, context?: LogContext): void;
|
|
26
|
+
warn(template: string, context?: LogContext): void;
|
|
27
|
+
error(template: string, context?: LogContext): void;
|
|
28
|
+
}
|
|
29
|
+
export declare class Logging {
|
|
30
|
+
private constructor();
|
|
31
|
+
static readonly defaultSink: SinkSubscription;
|
|
32
|
+
static getLogger(source: string): Logger;
|
|
33
|
+
static addSink(sink: LogSink, minimum?: LogLevel): SinkSubscription;
|
|
34
|
+
}
|
package/out/logging.luau
ADDED
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local exports = {}
|
|
4
|
+
local LogLevel = TS.import(script, script.Parent, "log-level").LogLevel
|
|
5
|
+
local runtimeDiagnostic = TS.import(script, script.Parent, "internal", "diagnostics").runtimeDiagnostic
|
|
6
|
+
local loggingPort = TS.import(script, script.Parent, "internal", "log-output").loggingPort
|
|
7
|
+
local call = TS.import(script, script.Parent, "internal", "runner").call
|
|
8
|
+
exports.LogLevel = TS.import(script, script.Parent, "log-level").LogLevel
|
|
9
|
+
local registrations = {}
|
|
10
|
+
local snapshot = {}
|
|
11
|
+
local minimum = LogLevel.Off
|
|
12
|
+
local sequence = 0
|
|
13
|
+
local emitting = false
|
|
14
|
+
local function derive(added)
|
|
15
|
+
local entries = {}
|
|
16
|
+
minimum = LogLevel.Off
|
|
17
|
+
-- roblox-ts Maps compile to unordered Luau tables. The array owns delivery order.
|
|
18
|
+
for _, registration in snapshot do
|
|
19
|
+
if not registration.connected then
|
|
20
|
+
continue
|
|
21
|
+
end
|
|
22
|
+
table.insert(entries, registration)
|
|
23
|
+
minimum = math.min(minimum, registration.minimum)
|
|
24
|
+
end
|
|
25
|
+
if added ~= nil then
|
|
26
|
+
local _added = added
|
|
27
|
+
table.insert(entries, _added)
|
|
28
|
+
minimum = math.min(minimum, added.minimum)
|
|
29
|
+
end
|
|
30
|
+
snapshot = table.freeze(entries)
|
|
31
|
+
end
|
|
32
|
+
local function validateMinimum(level)
|
|
33
|
+
local _arg0 = level >= LogLevel.Debug and level <= LogLevel.Off and level % 1 == 0
|
|
34
|
+
assert(_arg0, "Invalid log minimum")
|
|
35
|
+
end
|
|
36
|
+
local function register(sink, level)
|
|
37
|
+
validateMinimum(level)
|
|
38
|
+
local _sink = sink
|
|
39
|
+
local existing = registrations[_sink]
|
|
40
|
+
if existing ~= nil then
|
|
41
|
+
return existing.subscription
|
|
42
|
+
end
|
|
43
|
+
local _write = sink.write
|
|
44
|
+
local _arg0 = type(_write) == "function"
|
|
45
|
+
assert(_arg0, "Log sink requires write")
|
|
46
|
+
local registration
|
|
47
|
+
registration = {
|
|
48
|
+
sink = sink,
|
|
49
|
+
minimum = level,
|
|
50
|
+
connected = true,
|
|
51
|
+
subscription = {
|
|
52
|
+
setMinimum = function(self, value)
|
|
53
|
+
validateMinimum(value)
|
|
54
|
+
if not registration.connected then
|
|
55
|
+
return nil
|
|
56
|
+
end
|
|
57
|
+
registration.minimum = value
|
|
58
|
+
derive()
|
|
59
|
+
end,
|
|
60
|
+
disconnect = function(self)
|
|
61
|
+
if not registration.connected then
|
|
62
|
+
return nil
|
|
63
|
+
end
|
|
64
|
+
registration.connected = false
|
|
65
|
+
local _sink_1 = sink
|
|
66
|
+
registrations[_sink_1] = nil
|
|
67
|
+
derive()
|
|
68
|
+
end,
|
|
69
|
+
},
|
|
70
|
+
}
|
|
71
|
+
local _sink_1 = sink
|
|
72
|
+
registrations[_sink_1] = registration
|
|
73
|
+
derive(registration)
|
|
74
|
+
return registration.subscription
|
|
75
|
+
end
|
|
76
|
+
local function normalize(input)
|
|
77
|
+
local context = {}
|
|
78
|
+
if input ~= nil then
|
|
79
|
+
for key, value in pairs(input) do
|
|
80
|
+
context[key] = if typeof(value) == "Instance" then loggingPort().describeInstance(value) elseif type(value) == "string" or type(value) == "number" or type(value) == "boolean" then value else tostring(value)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
return table.freeze(context)
|
|
84
|
+
end
|
|
85
|
+
local function render(template, context)
|
|
86
|
+
local parts = {}
|
|
87
|
+
local index = 1
|
|
88
|
+
while index <= #template do
|
|
89
|
+
local _template = template
|
|
90
|
+
local _index = index
|
|
91
|
+
local _index_1 = index
|
|
92
|
+
local char = string.sub(_template, _index, _index_1)
|
|
93
|
+
local _template_1 = template
|
|
94
|
+
local _index_2 = index
|
|
95
|
+
local _arg1 = index + 1
|
|
96
|
+
local pair = string.sub(_template_1, _index_2, _arg1)
|
|
97
|
+
if pair == "{{" or pair == "}}" then
|
|
98
|
+
table.insert(parts, char)
|
|
99
|
+
index += 2
|
|
100
|
+
elseif char == "{" then
|
|
101
|
+
local _template_2 = template
|
|
102
|
+
local _arg1_1 = index + 1
|
|
103
|
+
local close = string.find(_template_2, "}", _arg1_1, true)
|
|
104
|
+
if close ~= nil then
|
|
105
|
+
local _template_3 = template
|
|
106
|
+
local _arg0 = index + 1
|
|
107
|
+
local _arg1_2 = close - 1
|
|
108
|
+
local key = string.sub(_template_3, _arg0, _arg1_2)
|
|
109
|
+
local value = context[key]
|
|
110
|
+
local _result
|
|
111
|
+
if value == nil then
|
|
112
|
+
local _template_4 = template
|
|
113
|
+
local _index_3 = index
|
|
114
|
+
_result = string.sub(_template_4, _index_3, close)
|
|
115
|
+
else
|
|
116
|
+
_result = tostring(value)
|
|
117
|
+
end
|
|
118
|
+
table.insert(parts, _result)
|
|
119
|
+
index = close + 1
|
|
120
|
+
else
|
|
121
|
+
table.insert(parts, char)
|
|
122
|
+
index += 1
|
|
123
|
+
end
|
|
124
|
+
else
|
|
125
|
+
table.insert(parts, char)
|
|
126
|
+
index += 1
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
return table.concat(parts, "")
|
|
130
|
+
end
|
|
131
|
+
local function emit(source, level, template, input)
|
|
132
|
+
if emitting or level < minimum then
|
|
133
|
+
return nil
|
|
134
|
+
end
|
|
135
|
+
emitting = true
|
|
136
|
+
local trace = if level == LogLevel.Error then debug.traceback("", 3) else nil
|
|
137
|
+
local result, failure = call(function()
|
|
138
|
+
-- ▼ ReadonlyArray.filter ▼
|
|
139
|
+
local _newValue = {}
|
|
140
|
+
local _callback = function(r)
|
|
141
|
+
return level >= r.minimum
|
|
142
|
+
end
|
|
143
|
+
local _length = 0
|
|
144
|
+
for _k, _v in snapshot do
|
|
145
|
+
if _callback(_v, _k - 1, snapshot) == true then
|
|
146
|
+
_length += 1
|
|
147
|
+
_newValue[_length] = _v
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
-- ▲ ReadonlyArray.filter ▲
|
|
151
|
+
local accepted = _newValue
|
|
152
|
+
local context = normalize(input)
|
|
153
|
+
local _object = {}
|
|
154
|
+
local _left = "sequence"
|
|
155
|
+
sequence += 1
|
|
156
|
+
_object[_left] = sequence
|
|
157
|
+
_object.time = loggingPort().now()
|
|
158
|
+
_object.source = source
|
|
159
|
+
_object.level = level
|
|
160
|
+
_object.template = template
|
|
161
|
+
_object.context = context
|
|
162
|
+
_object.message = render(template, context)
|
|
163
|
+
_object.traceback = trace
|
|
164
|
+
local record = table.freeze(_object)
|
|
165
|
+
for _, registration in accepted do
|
|
166
|
+
if not registration.connected then
|
|
167
|
+
continue
|
|
168
|
+
end
|
|
169
|
+
local status, err = call(registration.sink.write, record, nil)
|
|
170
|
+
if status ~= 0 then
|
|
171
|
+
registration.subscription:disconnect()
|
|
172
|
+
runtimeDiagnostic("error", `Log sink failed: {tostring(err)}`)
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end, nil, nil)
|
|
176
|
+
if result ~= 0 then
|
|
177
|
+
runtimeDiagnostic("error", `Logging failed: {tostring(failure)}`)
|
|
178
|
+
end
|
|
179
|
+
emitting = false
|
|
180
|
+
end
|
|
181
|
+
local Logging
|
|
182
|
+
do
|
|
183
|
+
Logging = setmetatable({}, {
|
|
184
|
+
__tostring = function()
|
|
185
|
+
return "Logging"
|
|
186
|
+
end,
|
|
187
|
+
})
|
|
188
|
+
Logging.__index = Logging
|
|
189
|
+
function Logging.new(...)
|
|
190
|
+
local self = setmetatable({}, Logging)
|
|
191
|
+
return self:constructor(...) or self
|
|
192
|
+
end
|
|
193
|
+
function Logging:constructor()
|
|
194
|
+
end
|
|
195
|
+
function Logging:getLogger(source)
|
|
196
|
+
local _arg0 = #source > 0 and #source <= 256 and (string.find(source, "%c")) == nil
|
|
197
|
+
assert(_arg0, "Invalid logger name")
|
|
198
|
+
for _, segment in string.split(source, ".") do
|
|
199
|
+
local _arg0_1 = #segment > 0
|
|
200
|
+
assert(_arg0_1, "Invalid logger name segment")
|
|
201
|
+
end
|
|
202
|
+
return {
|
|
203
|
+
isEnabled = function(self, level)
|
|
204
|
+
return level >= minimum
|
|
205
|
+
end,
|
|
206
|
+
debug = function(self, template, context)
|
|
207
|
+
emit(source, LogLevel.Debug, template, context)
|
|
208
|
+
end,
|
|
209
|
+
info = function(self, template, context)
|
|
210
|
+
emit(source, LogLevel.Info, template, context)
|
|
211
|
+
end,
|
|
212
|
+
warn = function(self, template, context)
|
|
213
|
+
emit(source, LogLevel.Warning, template, context)
|
|
214
|
+
end,
|
|
215
|
+
error = function(self, template, context)
|
|
216
|
+
emit(source, LogLevel.Error, template, context)
|
|
217
|
+
end,
|
|
218
|
+
}
|
|
219
|
+
end
|
|
220
|
+
function Logging:addSink(sink, minimum)
|
|
221
|
+
if minimum == nil then
|
|
222
|
+
minimum = LogLevel.Info
|
|
223
|
+
end
|
|
224
|
+
return register(sink, minimum)
|
|
225
|
+
end
|
|
226
|
+
Logging.defaultSink = register({
|
|
227
|
+
write = function(record)
|
|
228
|
+
return loggingPort().writeGame(record)
|
|
229
|
+
end,
|
|
230
|
+
}, if loggingPort().isStudio() then LogLevel.Debug else LogLevel.Info)
|
|
231
|
+
end
|
|
232
|
+
exports.Logging = Logging
|
|
233
|
+
return exports
|
package/out/network.d.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
declare const message: unique symbol;
|
|
2
|
+
declare const width: unique symbol;
|
|
3
|
+
export type f64 = number & {
|
|
4
|
+
readonly [width]?: "f64";
|
|
5
|
+
};
|
|
6
|
+
export type f32 = number & {
|
|
7
|
+
readonly [width]?: "f32";
|
|
8
|
+
};
|
|
9
|
+
export type u8 = number & {
|
|
10
|
+
readonly [width]?: "u8";
|
|
11
|
+
};
|
|
12
|
+
export type u16 = number & {
|
|
13
|
+
readonly [width]?: "u16";
|
|
14
|
+
};
|
|
15
|
+
export type u32 = number & {
|
|
16
|
+
readonly [width]?: "u32";
|
|
17
|
+
};
|
|
18
|
+
export interface ToServer<P> {
|
|
19
|
+
readonly [message]: {
|
|
20
|
+
readonly kind: "to-server";
|
|
21
|
+
readonly payload: (value: P) => P;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export interface ToClient<P> {
|
|
25
|
+
readonly [message]: {
|
|
26
|
+
readonly kind: "to-client";
|
|
27
|
+
readonly payload: (value: P) => P;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export interface AskServer<Request, Response> {
|
|
31
|
+
readonly [message]: {
|
|
32
|
+
readonly kind: "ask-server";
|
|
33
|
+
readonly request: (value: Request) => Request;
|
|
34
|
+
readonly response: (value: Response) => Response;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export interface ClientReady {
|
|
38
|
+
readonly [message]: {
|
|
39
|
+
readonly kind: "client-ready";
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
export declare const ClientReady: ClientReady;
|
|
43
|
+
export interface Receiver {
|
|
44
|
+
readonly [message]: {
|
|
45
|
+
readonly kind: "receiver";
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
export type PayloadArgs<P> = [P] extends [undefined] ? [] : [payload: P];
|
|
49
|
+
export type AskFailure = "timeout" | "disconnected" | "unavailable" | "handler-error" | "overloaded" | "invalid";
|
|
50
|
+
export type AskResult<T> = {
|
|
51
|
+
readonly ok: true;
|
|
52
|
+
readonly value: T;
|
|
53
|
+
} | {
|
|
54
|
+
readonly ok: false;
|
|
55
|
+
readonly reason: AskFailure;
|
|
56
|
+
};
|
|
57
|
+
export interface AskOptions {
|
|
58
|
+
readonly timeout?: number;
|
|
59
|
+
}
|
|
60
|
+
export type ReceiveTarget = ToServer<any> | ToClient<any> | AskServer<any, any> | ClientReady;
|
|
61
|
+
export type ReceiveCallback<T extends ReceiveTarget> = T extends ToServer<infer P> ? (player: Player, ...payload: PayloadArgs<P>) => void : T extends AskServer<infer Request, infer Response> ? (player: Player, ...request: PayloadArgs<Request>) => Response : T extends ToClient<infer P> ? (...payload: PayloadArgs<P>) => void : (player: Player) => (() => void) | void;
|
|
62
|
+
export declare function toServer<P>(_name: string): ToServer<P>;
|
|
63
|
+
export declare function toClient<P>(_name: string): ToClient<P>;
|
|
64
|
+
export declare function askServer<Request, Response>(_name: string, _options?: AskOptions): AskServer<Request, Response>;
|
|
65
|
+
export declare function receive<T extends ReceiveTarget>(_target: T, _callback: ReceiveCallback<T>): Receiver;
|
|
66
|
+
export {};
|
package/out/network.luau
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
-- Function-valued phantom positions keep every payload type invariant under strictFunctionTypes.
|
|
3
|
+
local ClientReady = table.freeze({})
|
|
4
|
+
-- `any` is the only argument every invariant token is assignable to.
|
|
5
|
+
local UNTRANSFORMED = "Crucible networking needs the @trioforge/crucible/transformer plugin"
|
|
6
|
+
local function toServer(_name)
|
|
7
|
+
error(UNTRANSFORMED)
|
|
8
|
+
end
|
|
9
|
+
local function toClient(_name)
|
|
10
|
+
error(UNTRANSFORMED)
|
|
11
|
+
end
|
|
12
|
+
local function askServer(_name, _options)
|
|
13
|
+
error(UNTRANSFORMED)
|
|
14
|
+
end
|
|
15
|
+
local function receive(_target, _callback)
|
|
16
|
+
error(UNTRANSFORMED)
|
|
17
|
+
end
|
|
18
|
+
return {
|
|
19
|
+
toServer = toServer,
|
|
20
|
+
toClient = toClient,
|
|
21
|
+
askServer = askServer,
|
|
22
|
+
receive = receive,
|
|
23
|
+
ClientReady = ClientReady,
|
|
24
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
declare const stateKind: unique symbol;
|
|
2
|
+
/**
|
|
3
|
+
* A value read by calling it. Any function of no arguments is one, so a getter that reads state, such as
|
|
4
|
+
* `() => this.open() && !this.locked()`, tracks like a state or a computed.
|
|
5
|
+
*/
|
|
6
|
+
export interface Readable<T> {
|
|
7
|
+
(): T;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* A writable local value. `set` stores its argument as is, and `update` stores what its callback returns for the
|
|
11
|
+
* current value. A write equal (`rawequal`) to the current value does nothing, so replace tables instead of
|
|
12
|
+
* mutating them. At runtime a State is a callable table, not a function: pass `() => s()` to code that tests
|
|
13
|
+
* `type(x) == "function"`.
|
|
14
|
+
*/
|
|
15
|
+
export interface State<T> extends Readable<T> {
|
|
16
|
+
readonly [stateKind]: {
|
|
17
|
+
readonly value: (value: T) => T;
|
|
18
|
+
};
|
|
19
|
+
set(value: T): void;
|
|
20
|
+
update(change: (current: T) => T): void;
|
|
21
|
+
}
|
|
22
|
+
/** A local source of truth. It needs no owner: a field initializer, a local or a module constant. */
|
|
23
|
+
export declare function state<T>(initial: T): State<T>;
|
|
24
|
+
/**
|
|
25
|
+
* A cached value derived from other readables. It evaluates on its first read and again only when read after a
|
|
26
|
+
* dependency changed. A result equal to the cached one stops propagation. A throw or a yield is cached and rethrown
|
|
27
|
+
* to every reader until a dependency changes. Writing state or creating an effect, watch, scope or cleanup inside
|
|
28
|
+
* `read` throws. It needs no owner.
|
|
29
|
+
*/
|
|
30
|
+
export declare function computed<T>(read: () => T): Readable<T>;
|
|
31
|
+
/**
|
|
32
|
+
* Keeps something outside the graph in step with state. The body runs on the next reactive flush, never inside
|
|
33
|
+
* the call that created it, and again after anything it read changed. It may return a cleanup, which runs before
|
|
34
|
+
* the next run and when the effect ends. It belongs to the code that created it: inside `onEnable` it ends at
|
|
35
|
+
* disable; otherwise it ends with its object, its parent effect run or its scope. A throw, a yield or another
|
|
36
|
+
* return value stops it for good, after what its run created is released. With no owner it throws.
|
|
37
|
+
*/
|
|
38
|
+
export declare function effect(body: () => void | (() => void)): void;
|
|
39
|
+
/**
|
|
40
|
+
* Calls `onChange(value, previous)` on the flushes where `source()` differs from the last value seen. The source is
|
|
41
|
+
* read now as the baseline, so a change before the first flush is seen. It observes the value at each flush, not
|
|
42
|
+
* each write. Owned and stopped like `effect`.
|
|
43
|
+
*/
|
|
44
|
+
export declare function watch<T>(source: Readable<T>, onChange: (value: T, previous: T) => void): void;
|
|
45
|
+
/** Calls `read` without tracking what it reads. Ownership is unchanged. */
|
|
46
|
+
export declare function untracked<T>(read: () => T): T;
|
|
47
|
+
/**
|
|
48
|
+
* Runs `setup` now as a new lifetime that owns every effect, watch, scope and cleanup created inside it. Returns
|
|
49
|
+
* an idempotent dispose. Inside another owner it also ends when that owner ends; outside every owner it is a root
|
|
50
|
+
* that only its dispose ends. If `setup` throws or yields, what it created ends and the error is rethrown.
|
|
51
|
+
*/
|
|
52
|
+
export declare function scope(setup: () => void): () => void;
|
|
53
|
+
/**
|
|
54
|
+
* Registers `release` to run once when the current owner ends: after the owner's effects and scopes ended, newest
|
|
55
|
+
* release first. Under an owner that already ended it runs at once. With no owner it throws.
|
|
56
|
+
*/
|
|
57
|
+
export declare function onCleanup(release: () => void): void;
|
|
58
|
+
/**
|
|
59
|
+
* What `own` releases: a function, called with no arguments; a connection, disconnected; an Instance, destroyed; a
|
|
60
|
+
* thread, cancelled with `task.cancel`; or an object, through its `destroy()` or else its `Destroy()`. A `State` is a
|
|
61
|
+
* callable table, not a function, so it is not one.
|
|
62
|
+
*/
|
|
63
|
+
export type Ownable = ((() => void) & {
|
|
64
|
+
readonly [stateKind]?: never;
|
|
65
|
+
}) | RBXScriptConnection | Instance | thread | {
|
|
66
|
+
destroy(): void;
|
|
67
|
+
} | {
|
|
68
|
+
Destroy(): void;
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Releases `value` once when the current owner ends, exactly as `onCleanup` would release a function that does it,
|
|
72
|
+
* and returns `value`. How it is released is decided now, from its type. Under an owner that already ended it is
|
|
73
|
+
* released at once. With no owner it throws, and so does a value that is not `Ownable`.
|
|
74
|
+
*/
|
|
75
|
+
export declare function own<T extends Ownable>(value: T): T;
|
|
76
|
+
export {};
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local _flush = TS.import(script, script.Parent, "internal", "reactive", "flush")
|
|
4
|
+
local createEffect = _flush.createEffect
|
|
5
|
+
local createWatch = _flush.createWatch
|
|
6
|
+
local _graph = TS.import(script, script.Parent, "internal", "reactive", "graph")
|
|
7
|
+
local createComputedNode = _graph.createComputedNode
|
|
8
|
+
local createStateNode = _graph.createStateNode
|
|
9
|
+
local readComputed = _graph.readComputed
|
|
10
|
+
local readState = _graph.readState
|
|
11
|
+
local readUntracked = _graph.readUntracked
|
|
12
|
+
local update = _graph.update
|
|
13
|
+
local write = _graph.write
|
|
14
|
+
local _ownership = TS.import(script, script.Parent, "internal", "reactive", "ownership")
|
|
15
|
+
local createScope = _ownership.createScope
|
|
16
|
+
local registerCleanup = _ownership.registerCleanup
|
|
17
|
+
local registerOwned = _ownership.registerOwned
|
|
18
|
+
--[[
|
|
19
|
+
*
|
|
20
|
+
* A value read by calling it. Any function of no arguments is one, so a getter that reads state, such as
|
|
21
|
+
* `() => this.open() && !this.locked()`, tracks like a state or a computed.
|
|
22
|
+
|
|
23
|
+
]]
|
|
24
|
+
--[[
|
|
25
|
+
*
|
|
26
|
+
* A writable local value. `set` stores its argument as is, and `update` stores what its callback returns for the
|
|
27
|
+
* current value. A write equal (`rawequal`) to the current value does nothing, so replace tables instead of
|
|
28
|
+
* mutating them. At runtime a State is a callable table, not a function: pass `() => s()` to code that tests
|
|
29
|
+
* `type(x) == "function"`.
|
|
30
|
+
|
|
31
|
+
]]
|
|
32
|
+
local stateMethods = {
|
|
33
|
+
set = function(self, value)
|
|
34
|
+
write(self, value)
|
|
35
|
+
end,
|
|
36
|
+
update = function(self, change)
|
|
37
|
+
update(self, change)
|
|
38
|
+
end,
|
|
39
|
+
}
|
|
40
|
+
local stateMeta = {
|
|
41
|
+
__index = stateMethods,
|
|
42
|
+
__call = function(node)
|
|
43
|
+
return readState(node)
|
|
44
|
+
end,
|
|
45
|
+
}
|
|
46
|
+
--* A local source of truth. It needs no owner: a field initializer, a local or a module constant.
|
|
47
|
+
local function state(initial)
|
|
48
|
+
return setmetatable(createStateNode(initial), stateMeta)
|
|
49
|
+
end
|
|
50
|
+
--[[
|
|
51
|
+
*
|
|
52
|
+
* A cached value derived from other readables. It evaluates on its first read and again only when read after a
|
|
53
|
+
* dependency changed. A result equal to the cached one stops propagation. A throw or a yield is cached and rethrown
|
|
54
|
+
* to every reader until a dependency changes. Writing state or creating an effect, watch, scope or cleanup inside
|
|
55
|
+
* `read` throws. It needs no owner.
|
|
56
|
+
|
|
57
|
+
]]
|
|
58
|
+
local function computed(read)
|
|
59
|
+
local node = createComputedNode(read)
|
|
60
|
+
return function()
|
|
61
|
+
return readComputed(node)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
--[[
|
|
65
|
+
*
|
|
66
|
+
* Keeps something outside the graph in step with state. The body runs on the next reactive flush, never inside
|
|
67
|
+
* the call that created it, and again after anything it read changed. It may return a cleanup, which runs before
|
|
68
|
+
* the next run and when the effect ends. It belongs to the code that created it: inside `onEnable` it ends at
|
|
69
|
+
* disable; otherwise it ends with its object, its parent effect run or its scope. A throw, a yield or another
|
|
70
|
+
* return value stops it for good, after what its run created is released. With no owner it throws.
|
|
71
|
+
|
|
72
|
+
]]
|
|
73
|
+
local function effect(body)
|
|
74
|
+
createEffect(body)
|
|
75
|
+
end
|
|
76
|
+
--[[
|
|
77
|
+
*
|
|
78
|
+
* Calls `onChange(value, previous)` on the flushes where `source()` differs from the last value seen. The source is
|
|
79
|
+
* read now as the baseline, so a change before the first flush is seen. It observes the value at each flush, not
|
|
80
|
+
* each write. Owned and stopped like `effect`.
|
|
81
|
+
|
|
82
|
+
]]
|
|
83
|
+
local function watch(source, onChange)
|
|
84
|
+
createWatch(source, onChange)
|
|
85
|
+
end
|
|
86
|
+
--* Calls `read` without tracking what it reads. Ownership is unchanged.
|
|
87
|
+
local function untracked(read)
|
|
88
|
+
return readUntracked(read)
|
|
89
|
+
end
|
|
90
|
+
--[[
|
|
91
|
+
*
|
|
92
|
+
* Runs `setup` now as a new lifetime that owns every effect, watch, scope and cleanup created inside it. Returns
|
|
93
|
+
* an idempotent dispose. Inside another owner it also ends when that owner ends; outside every owner it is a root
|
|
94
|
+
* that only its dispose ends. If `setup` throws or yields, what it created ends and the error is rethrown.
|
|
95
|
+
|
|
96
|
+
]]
|
|
97
|
+
local function scope(setup)
|
|
98
|
+
return createScope(setup)
|
|
99
|
+
end
|
|
100
|
+
--[[
|
|
101
|
+
*
|
|
102
|
+
* Registers `release` to run once when the current owner ends: after the owner's effects and scopes ended, newest
|
|
103
|
+
* release first. Under an owner that already ended it runs at once. With no owner it throws.
|
|
104
|
+
|
|
105
|
+
]]
|
|
106
|
+
local function onCleanup(release)
|
|
107
|
+
registerCleanup(release)
|
|
108
|
+
end
|
|
109
|
+
--[[
|
|
110
|
+
*
|
|
111
|
+
* What `own` releases: a function, called with no arguments; a connection, disconnected; an Instance, destroyed; a
|
|
112
|
+
* thread, cancelled with `task.cancel`; or an object, through its `destroy()` or else its `Destroy()`. A `State` is a
|
|
113
|
+
* callable table, not a function, so it is not one.
|
|
114
|
+
|
|
115
|
+
]]
|
|
116
|
+
--[[
|
|
117
|
+
*
|
|
118
|
+
* Releases `value` once when the current owner ends, exactly as `onCleanup` would release a function that does it,
|
|
119
|
+
* and returns `value`. How it is released is decided now, from its type. Under an owner that already ended it is
|
|
120
|
+
* released at once. With no owner it throws, and so does a value that is not `Ownable`.
|
|
121
|
+
|
|
122
|
+
]]
|
|
123
|
+
local function own(value)
|
|
124
|
+
registerOwned(value)
|
|
125
|
+
return value
|
|
126
|
+
end
|
|
127
|
+
return {
|
|
128
|
+
state = state,
|
|
129
|
+
computed = computed,
|
|
130
|
+
effect = effect,
|
|
131
|
+
watch = watch,
|
|
132
|
+
untracked = untracked,
|
|
133
|
+
scope = scope,
|
|
134
|
+
onCleanup = onCleanup,
|
|
135
|
+
own = own,
|
|
136
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Readable } from "./reactive";
|
|
2
|
+
declare const replicatedKind: unique symbol;
|
|
3
|
+
/** Whether a replicated value holds what the server published: before the first frame, after it, or failed. */
|
|
4
|
+
export type SyncStatus = "pending" | "ready" | "failed";
|
|
5
|
+
/**
|
|
6
|
+
* A value every client receives. On the server it reads the authoritative value; on a client, the last value the
|
|
7
|
+
* server sent, or `initial` before the first frame. At runtime it is a plain function, so it composes like any getter.
|
|
8
|
+
*/
|
|
9
|
+
export interface Replicated<T> extends Readable<T> {
|
|
10
|
+
readonly [replicatedKind]: {
|
|
11
|
+
readonly audience: "all";
|
|
12
|
+
readonly value: (value: T) => T;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* A value each player receives privately. On a client it reads the local player's value, or `initial` before the
|
|
17
|
+
* first frame. On the server there is no single value, so calling it throws.
|
|
18
|
+
*/
|
|
19
|
+
export interface ReplicatedPerPlayer<T> extends Readable<T> {
|
|
20
|
+
readonly [replicatedKind]: {
|
|
21
|
+
readonly audience: "player";
|
|
22
|
+
readonly value: (value: T) => T;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Declares a value every client receives. Write it as the initializer of an exported top-level const in a shared
|
|
27
|
+
* module, with an explicit type argument and a literal name. The server writes it through `publish`; fields the type
|
|
28
|
+
* does not declare are never sent.
|
|
29
|
+
*/
|
|
30
|
+
export declare function replicated<T = never>(_name: string, _initial: NoInfer<T>): Replicated<T>;
|
|
31
|
+
/** Declares a value each player receives privately. The server supplies it with `publish(declaration, project)`. */
|
|
32
|
+
export declare function replicatedPerPlayer<T = never>(_name: string, _initial: NoInfer<T>): ReplicatedPerPlayer<T>;
|
|
33
|
+
/**
|
|
34
|
+
* The declaration's sync status. Inside an effect or a computed it tracks like a value. On the server, a per-player
|
|
35
|
+
* declaration throws.
|
|
36
|
+
*/
|
|
37
|
+
export declare function syncStatus<T>(declaration: Replicated<T> | ReplicatedPerPlayer<T>): SyncStatus;
|
|
38
|
+
export {};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local statusOf = TS.import(script, script.Parent, "internal", "sync", "declarations").statusOf
|
|
4
|
+
--* Whether a replicated value holds what the server published: before the first frame, after it, or failed.
|
|
5
|
+
--[[
|
|
6
|
+
*
|
|
7
|
+
* A value every client receives. On the server it reads the authoritative value; on a client, the last value the
|
|
8
|
+
* server sent, or `initial` before the first frame. At runtime it is a plain function, so it composes like any getter.
|
|
9
|
+
|
|
10
|
+
]]
|
|
11
|
+
--[[
|
|
12
|
+
*
|
|
13
|
+
* A value each player receives privately. On a client it reads the local player's value, or `initial` before the
|
|
14
|
+
* first frame. On the server there is no single value, so calling it throws.
|
|
15
|
+
|
|
16
|
+
]]
|
|
17
|
+
local UNTRANSFORMED = "Crucible replicated state needs the @trioforge/crucible/transformer plugin"
|
|
18
|
+
--[[
|
|
19
|
+
*
|
|
20
|
+
* Declares a value every client receives. Write it as the initializer of an exported top-level const in a shared
|
|
21
|
+
* module, with an explicit type argument and a literal name. The server writes it through `publish`; fields the type
|
|
22
|
+
* does not declare are never sent.
|
|
23
|
+
|
|
24
|
+
]]
|
|
25
|
+
local function replicated(_name, _initial)
|
|
26
|
+
error(UNTRANSFORMED)
|
|
27
|
+
end
|
|
28
|
+
--* Declares a value each player receives privately. The server supplies it with `publish(declaration, project)`.
|
|
29
|
+
local function replicatedPerPlayer(_name, _initial)
|
|
30
|
+
error(UNTRANSFORMED)
|
|
31
|
+
end
|
|
32
|
+
--[[
|
|
33
|
+
*
|
|
34
|
+
* The declaration's sync status. Inside an effect or a computed it tracks like a value. On the server, a per-player
|
|
35
|
+
* declaration throws.
|
|
36
|
+
|
|
37
|
+
]]
|
|
38
|
+
local function syncStatus(declaration)
|
|
39
|
+
return statusOf(declaration)
|
|
40
|
+
end
|
|
41
|
+
return {
|
|
42
|
+
replicated = replicated,
|
|
43
|
+
replicatedPerPlayer = replicatedPerPlayer,
|
|
44
|
+
syncStatus = syncStatus,
|
|
45
|
+
}
|