@trioforge/crucible 0.1.0 → 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.
Files changed (134) hide show
  1. package/out/client/index.d.ts +7 -0
  2. package/out/client/init.luau +36 -1
  3. package/out/configs.d.ts +37 -0
  4. package/out/configs.luau +46 -0
  5. package/out/data.d.ts +224 -0
  6. package/out/data.luau +97 -0
  7. package/out/emit/configs.d.ts +4 -0
  8. package/out/emit/configs.luau +22 -0
  9. package/out/emit/data.d.ts +6 -0
  10. package/out/emit/data.luau +19 -0
  11. package/out/emit/index.d.ts +5 -1
  12. package/out/emit/init.luau +23 -7
  13. package/out/emit/network.d.ts +6 -0
  14. package/out/emit/network.luau +36 -0
  15. package/out/emit/replicated.d.ts +4 -0
  16. package/out/emit/replicated.luau +13 -0
  17. package/out/index.d.ts +8 -0
  18. package/out/init.luau +23 -0
  19. package/out/internal/binding.luau +5 -0
  20. package/out/internal/boot.luau +107 -8
  21. package/out/internal/configs/limits.d.ts +10 -0
  22. package/out/internal/configs/limits.luau +25 -0
  23. package/out/internal/configs/port.d.ts +29 -0
  24. package/out/internal/configs/port.luau +99 -0
  25. package/out/internal/configs/runtime.d.ts +21 -0
  26. package/out/internal/configs/runtime.luau +981 -0
  27. package/out/internal/data/admission.d.ts +1 -0
  28. package/out/internal/data/admission.luau +673 -0
  29. package/out/internal/data/declarations.d.ts +1 -0
  30. package/out/internal/data/declarations.luau +384 -0
  31. package/out/internal/data/envelope.d.ts +1 -0
  32. package/out/internal/data/envelope.luau +318 -0
  33. package/out/internal/data/handles.d.ts +1 -0
  34. package/out/internal/data/handles.luau +255 -0
  35. package/out/internal/data/inbox-transforms.d.ts +1 -0
  36. package/out/internal/data/inbox-transforms.luau +458 -0
  37. package/out/internal/data/inbox.d.ts +1 -0
  38. package/out/internal/data/inbox.luau +437 -0
  39. package/out/internal/data/lease.d.ts +1 -0
  40. package/out/internal/data/lease.luau +304 -0
  41. package/out/internal/data/limits.d.ts +1 -0
  42. package/out/internal/data/limits.luau +234 -0
  43. package/out/internal/data/messages.d.ts +1 -0
  44. package/out/internal/data/messages.luau +69 -0
  45. package/out/internal/data/operation-id.d.ts +1 -0
  46. package/out/internal/data/operation-id.luau +61 -0
  47. package/out/internal/data/paths.d.ts +2 -0
  48. package/out/internal/data/paths.luau +323 -0
  49. package/out/internal/data/port.d.ts +1 -0
  50. package/out/internal/data/port.luau +290 -0
  51. package/out/internal/data/profiles.d.ts +1 -0
  52. package/out/internal/data/profiles.luau +862 -0
  53. package/out/internal/data/receipts.d.ts +1 -0
  54. package/out/internal/data/receipts.luau +190 -0
  55. package/out/internal/data/record-bindings.d.ts +1 -0
  56. package/out/internal/data/record-bindings.luau +92 -0
  57. package/out/internal/data/record-declarations.d.ts +1 -0
  58. package/out/internal/data/record-declarations.luau +140 -0
  59. package/out/internal/data/records.d.ts +1 -0
  60. package/out/internal/data/records.luau +400 -0
  61. package/out/internal/data/runtime.d.ts +1 -0
  62. package/out/internal/data/runtime.luau +918 -0
  63. package/out/internal/data/scheduler.d.ts +1 -0
  64. package/out/internal/data/scheduler.luau +507 -0
  65. package/out/internal/data/session.d.ts +1 -0
  66. package/out/internal/data/session.luau +234 -0
  67. package/out/internal/data/shutdown.d.ts +1 -0
  68. package/out/internal/data/shutdown.luau +91 -0
  69. package/out/internal/data/waiters.d.ts +1 -0
  70. package/out/internal/data/waiters.luau +65 -0
  71. package/out/internal/lifecycle.luau +45 -0
  72. package/out/internal/network/catalog.d.ts +26 -0
  73. package/out/internal/network/catalog.luau +182 -0
  74. package/out/internal/network/claims.d.ts +1 -0
  75. package/out/internal/network/claims.luau +154 -0
  76. package/out/internal/network/client-session.d.ts +1 -0
  77. package/out/internal/network/client-session.luau +403 -0
  78. package/out/internal/network/codec.d.ts +63 -0
  79. package/out/internal/network/codec.luau +1183 -0
  80. package/out/internal/network/envelope.d.ts +1 -0
  81. package/out/internal/network/envelope.luau +247 -0
  82. package/out/internal/network/limits.d.ts +26 -0
  83. package/out/internal/network/limits.luau +55 -0
  84. package/out/internal/network/port.d.ts +1 -0
  85. package/out/internal/network/port.luau +19 -0
  86. package/out/internal/network/roblox-network-port.d.ts +1 -0
  87. package/out/internal/network/roblox-network-port.luau +105 -0
  88. package/out/internal/network/schema.d.ts +72 -0
  89. package/out/internal/network/schema.luau +386 -0
  90. package/out/internal/network/server-session.d.ts +1 -0
  91. package/out/internal/network/server-session.luau +393 -0
  92. package/out/internal/network/session.d.ts +1 -0
  93. package/out/internal/network/session.luau +266 -0
  94. package/out/internal/reactive/context.d.ts +1 -0
  95. package/out/internal/reactive/context.luau +149 -0
  96. package/out/internal/reactive/flush.d.ts +1 -0
  97. package/out/internal/reactive/flush.luau +355 -0
  98. package/out/internal/reactive/graph.d.ts +1 -0
  99. package/out/internal/reactive/graph.luau +626 -0
  100. package/out/internal/reactive/limits.d.ts +1 -0
  101. package/out/internal/reactive/limits.luau +54 -0
  102. package/out/internal/reactive/ownership.d.ts +1 -0
  103. package/out/internal/reactive/ownership.luau +626 -0
  104. package/out/internal/registry.luau +10 -1
  105. package/out/internal/sync/client-sync.d.ts +1 -0
  106. package/out/internal/sync/client-sync.luau +157 -0
  107. package/out/internal/sync/declarations.d.ts +1 -0
  108. package/out/internal/sync/declarations.luau +276 -0
  109. package/out/internal/sync/frame.d.ts +1 -0
  110. package/out/internal/sync/frame.luau +91 -0
  111. package/out/internal/sync/server-sync.d.ts +1 -0
  112. package/out/internal/sync/server-sync.luau +502 -0
  113. package/out/internal/sync/values.d.ts +1 -0
  114. package/out/internal/sync/values.luau +930 -0
  115. package/out/network.d.ts +66 -0
  116. package/out/network.luau +24 -0
  117. package/out/reactive.d.ts +76 -0
  118. package/out/reactive.luau +136 -0
  119. package/out/replicated.d.ts +38 -0
  120. package/out/replicated.luau +45 -0
  121. package/out/server/data.d.ts +54 -0
  122. package/out/server/data.luau +44 -0
  123. package/out/server/index.d.ts +16 -0
  124. package/out/server/init.luau +49 -3
  125. package/out/server/publish.d.ts +20 -0
  126. package/out/server/publish.luau +24 -0
  127. package/out/vide/index.d.ts +7 -0
  128. package/out/vide/init.luau +50 -0
  129. package/package.json +13 -2
  130. package/transformer/data.cjs +72 -0
  131. package/transformer/declarations.cjs +153 -0
  132. package/transformer/index.js +37 -11
  133. package/transformer/network.cjs +961 -0
  134. package/vide/package.json +4 -0
@@ -0,0 +1,393 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local TS = _G[script]
3
+ local runtimeDiagnostic = TS.import(script, script.Parent.Parent, "diagnostics").runtimeDiagnostic
4
+ local _catalog = TS.import(script, script.Parent, "catalog")
5
+ local definitionAt = _catalog.definitionAt
6
+ local definitionOf = _catalog.definitionOf
7
+ local discardIndices = _catalog.discardIndices
8
+ local seal = _catalog.seal
9
+ local _claims = TS.import(script, script.Parent, "claims")
10
+ local closeClaims = _claims.closeClaims
11
+ local freezeClaims = _claims.freezeClaims
12
+ local isLive = _claims.isLive
13
+ local openClaims = _claims.openClaims
14
+ local readyClaims = _claims.readyClaims
15
+ local receiverOf = _claims.receiverOf
16
+ local _envelope = TS.import(script, script.Parent, "envelope")
17
+ local argumentCount = _envelope.argumentCount
18
+ local controlPacket = _envelope.controlPacket
19
+ local decodeBody = _envelope.decodeBody
20
+ local encodeBody = _envelope.encodeBody
21
+ local failureReason = _envelope.failureReason
22
+ local frame = _envelope.frame
23
+ local missingInstance = _envelope.missingInstance
24
+ local openBody = _envelope.openBody
25
+ local readHeader = _envelope.readHeader
26
+ local L = TS.import(script, script.Parent, "limits")
27
+ local _session = TS.import(script, script.Parent, "session")
28
+ local newPeer = _session.newPeer
29
+ local Session = _session.Session
30
+ local FAIL_NAMES = { "overflow", "overloaded", "closing", "malformed" }
31
+ --* @internal
32
+ local toClient
33
+ local ServerSession
34
+ do
35
+ local super = Session
36
+ ServerSession = setmetatable({}, {
37
+ __tostring = function()
38
+ return "ServerSession"
39
+ end,
40
+ __index = super,
41
+ })
42
+ ServerSession.__index = ServerSession
43
+ function ServerSession.new(...)
44
+ local self = setmetatable({}, ServerSession)
45
+ return self:constructor(...) or self
46
+ end
47
+ function ServerSession:constructor(...)
48
+ super.constructor(self, ...)
49
+ self.peers = {}
50
+ self.order = {}
51
+ self.connections = {}
52
+ self.catalog = ""
53
+ self.published = false
54
+ self.reportedNoPeer = false
55
+ end
56
+ function ServerSession:open()
57
+ self.stage = 1
58
+ openClaims({
59
+ side = "server",
60
+ retired = function(claim)
61
+ return self:retired(claim)
62
+ end,
63
+ })
64
+ self.port.create(function(player, ...)
65
+ local args = { ... }
66
+ return self:receive(player, argumentCount(args), args[1], args[2])
67
+ end)
68
+ local _connections = self.connections
69
+ local _arg0 = self.port.onPlayerAdded(function(player)
70
+ return self:add(player)
71
+ end)
72
+ table.insert(_connections, _arg0)
73
+ local _connections_1 = self.connections
74
+ local _arg0_1 = self.port.onPlayerRemoving(function(player)
75
+ local _peers = self.peers
76
+ local _player = player
77
+ local peer = _peers[_player]
78
+ if peer ~= nil then
79
+ self["end"](self, peer)
80
+ end
81
+ end)
82
+ table.insert(_connections_1, _arg0_1)
83
+ for _, player in self.port.players() do
84
+ self:add(player)
85
+ end
86
+ end
87
+ function ServerSession:loaded()
88
+ self.catalog = seal()
89
+ self.stage = 2
90
+ end
91
+ function ServerSession:commit()
92
+ freezeClaims()
93
+ self.port.publish(L.PROTOCOL_VERSION, self.catalog)
94
+ self.published = true
95
+ self.stage = 3
96
+ end
97
+ function ServerSession:close()
98
+ if self.stage == 4 then
99
+ return nil
100
+ end
101
+ local committed = self.stage == 3
102
+ self.stage = 4
103
+ local closing = controlPacket(5, {}, 2)
104
+ local _array = {}
105
+ local _length = #_array
106
+ local _array_1 = self.order
107
+ table.move(_array_1, 1, #_array_1, _length + 1, _array)
108
+ for _, peer in _array do
109
+ if self.published then
110
+ pcall(function()
111
+ return self:fire(peer, closing)
112
+ end)
113
+ end
114
+ pcall(function()
115
+ return self["end"](self, peer)
116
+ end)
117
+ end
118
+ for _, disconnect in self.connections do
119
+ pcall(disconnect)
120
+ end
121
+ table.clear(self.connections)
122
+ pcall(function()
123
+ return self.port.destroy()
124
+ end)
125
+ closeClaims(not committed)
126
+ if not committed then
127
+ discardIndices()
128
+ end
129
+ end
130
+ function ServerSession:send(player, token, value)
131
+ local sendable = self:sendable()
132
+ local definition = toClient(token, "Network.send")
133
+ local body = encodeBody(definition.name, definition.input, "payload", value)
134
+ if not sendable then
135
+ return false
136
+ end
137
+ local _peers = self.peers
138
+ local _player = player
139
+ local peer = _peers[_player]
140
+ return peer ~= nil and self:deliver(peer, frame(body, 0, { definition.index }))
141
+ end
142
+ function ServerSession:broadcast(token, value)
143
+ local sendable = self:sendable()
144
+ local definition = toClient(token, "Network.broadcast")
145
+ local body = encodeBody(definition.name, definition.input, "payload", value)
146
+ if not sendable then
147
+ return nil
148
+ end
149
+ local packet = frame(body, 0, { definition.index })
150
+ local _array = {}
151
+ local _length = #_array
152
+ local _array_1 = self.order
153
+ table.move(_array_1, 1, #_array_1, _length + 1, _array)
154
+ for _, peer in _array do
155
+ self:deliver(peer, packet)
156
+ end
157
+ end
158
+ function ServerSession:fire(peer, packet)
159
+ self.port.fireClient(peer.player, packet.bytes, packet.sidecar)
160
+ end
161
+ ServerSession["end"] = function(self, peer)
162
+ if peer.state == 2 then
163
+ return false
164
+ end
165
+ local player = peer.player
166
+ if self.peers[player] == peer then
167
+ self.peers[player] = nil
168
+ end
169
+ local _order = self.order
170
+ local _peer = peer
171
+ local index = (table.find(_order, _peer) or 0) - 1
172
+ if index ~= -1 then
173
+ table.remove(self.order, index + 1)
174
+ end
175
+ return super["end"](self, peer)
176
+ end
177
+ function ServerSession:fail(peer, reason)
178
+ if peer.state == 2 then
179
+ return nil
180
+ end
181
+ local player = peer.player
182
+ runtimeDiagnostic("error", `Crucible network peer {player.Name} failed ({FAIL_NAMES[reason + 1]}); kicking`)
183
+ local packet = controlPacket(5, {}, reason)
184
+ pcall(function()
185
+ return self:fire(peer, packet)
186
+ end)
187
+ self["end"](self, peer)
188
+ pcall(function()
189
+ return self.port.kick(player, L.KICK_MESSAGE)
190
+ end)
191
+ end
192
+ function ServerSession:add(player)
193
+ local _condition = self.stage == 4
194
+ if not _condition then
195
+ local _peers = self.peers
196
+ local _player = player
197
+ _condition = _peers[_player] ~= nil
198
+ end
199
+ if _condition then
200
+ return nil
201
+ end
202
+ local peer = newPeer(player)
203
+ local _peers = self.peers
204
+ local _player = player
205
+ _peers[_player] = peer
206
+ local _exp = self.order
207
+ table.insert(_exp, peer)
208
+ end
209
+ function ServerSession:retired(claim)
210
+ local cleanups = {}
211
+ for _, peer in self.order do
212
+ for _1, entry in peer.running do
213
+ local request = entry.request
214
+ if entry.claim ~= claim or request == nil or entry.settled then
215
+ continue
216
+ end
217
+ entry.settled = true
218
+ self:fire(peer, controlPacket(3, { request.definition.index, request.nonce }, 0))
219
+ end
220
+ for i = #peer.cleanups - 1, 0, -1 do
221
+ local entry = peer.cleanups[i + 1]
222
+ if entry.claim ~= claim then
223
+ continue
224
+ end
225
+ local _cleanups = peer.cleanups
226
+ local _i = i
227
+ table.remove(_cleanups, _i + 1)
228
+ local _arg0 = { peer, entry }
229
+ table.insert(cleanups, _arg0)
230
+ end
231
+ end
232
+ for _, _binding in cleanups do
233
+ local peer = _binding[1]
234
+ local entry = _binding[2]
235
+ self:deferCleanup(peer, entry)
236
+ end
237
+ end
238
+ function ServerSession:reject(peer, key, what, detail)
239
+ local _rejected = peer.rejected
240
+ local _key = key
241
+ if _rejected[_key] ~= nil then
242
+ return nil
243
+ end
244
+ local _rejected_1 = peer.rejected
245
+ local _key_1 = key
246
+ _rejected_1[_key_1] = true
247
+ local reason = if detail == nil then "" else `: {detail}`
248
+ runtimeDiagnostic("warning", `Crucible dropped {what} from {peer.player.Name}{reason}`)
249
+ end
250
+ function ServerSession:receive(player, count, packet, sidecar)
251
+ local ok, err = pcall(function()
252
+ return self:dispatch(player, count, packet, sidecar)
253
+ end)
254
+ if not ok then
255
+ runtimeDiagnostic("error", `Crucible network receive failed: {tostring(err)}`)
256
+ end
257
+ end
258
+ function ServerSession:dispatch(player, count, packet, sidecar)
259
+ local _peers = self.peers
260
+ local _player = player
261
+ local peer = _peers[_player]
262
+ if peer == nil then
263
+ if self.reportedNoPeer then
264
+ return nil
265
+ end
266
+ self.reportedNoPeer = true
267
+ runtimeDiagnostic("warning", "Crucible dropped a network packet from a player with no peer")
268
+ return nil
269
+ end
270
+ if self.stage ~= 3 then
271
+ return self:reject(peer, "envelope", "a packet before the network commit")
272
+ end
273
+ local header = readHeader(count, packet, sidecar)
274
+ if header == nil then
275
+ return self:reject(peer, "envelope", "a malformed network packet")
276
+ end
277
+ if header.opcode == 4 then
278
+ if peer.state ~= 0 then
279
+ return self:reject(peer, "envelope", "a second READY")
280
+ end
281
+ return self:ready(peer)
282
+ end
283
+ if header.opcode == 5 then
284
+ local _condition = FAIL_NAMES[header.reason + 1]
285
+ if _condition == nil then
286
+ _condition = `unknown reason {header.reason}`
287
+ end
288
+ local reason = _condition
289
+ runtimeDiagnostic("error", `Crucible network peer {player.Name} sent FAIL ({reason}); kicking`)
290
+ self["end"](self, peer)
291
+ pcall(function()
292
+ return self.port.kick(player, L.KICK_MESSAGE)
293
+ end)
294
+ return nil
295
+ end
296
+ if header.opcode ~= 0 and header.opcode ~= 1 then
297
+ return self:reject(peer, "envelope", "a server-to-client packet")
298
+ end
299
+ if peer.state ~= 1 then
300
+ return self:reject(peer, "envelope", "a game packet before READY")
301
+ end
302
+ local definition = definitionAt(header.index)
303
+ if definition == nil then
304
+ return self:reject(peer, "envelope", "an unknown message index")
305
+ end
306
+ local event = header.opcode == 0
307
+ if definition.kind ~= (if event then "to-server" else "ask-server") then
308
+ return self:reject(peer, definition, `{definition.name} sent as the wrong kind of packet`)
309
+ end
310
+ local opened, reader = pcall(openBody, packet, sidecar, header)
311
+ if not opened then
312
+ return self:reject(peer, definition, definition.name, failureReason(reader))
313
+ end
314
+ if header.opcode == 0 then
315
+ local decoded, value = pcall(decodeBody, definition.input, "payload", reader)
316
+ if not decoded then
317
+ if not missingInstance(value) then
318
+ self:reject(peer, definition, definition.name, failureReason(value))
319
+ end
320
+ return nil
321
+ end
322
+ local receiver = receiverOf(definition)
323
+ if receiver == nil then
324
+ return self:unreceived(definition)
325
+ end
326
+ if peer.counted >= L.MAX_ACTIVE_HANDLERS then
327
+ return self:fail(peer, 1)
328
+ end
329
+ return self:start(peer, receiver, { player, value })
330
+ end
331
+ local nonce = header.nonce
332
+ if nonce <= peer.lastRequestNonce then
333
+ return self:reject(peer, definition, `{definition.name} with a nonce already used`)
334
+ end
335
+ peer.lastRequestNonce = nonce
336
+ local refuse = function(reason)
337
+ return self:fire(peer, controlPacket(3, { header.index, nonce }, reason))
338
+ end
339
+ local decoded, value = pcall(decodeBody, definition.input, "request", reader)
340
+ if not decoded then
341
+ if not missingInstance(value) then
342
+ self:reject(peer, definition, definition.name, failureReason(value))
343
+ end
344
+ return refuse(3)
345
+ end
346
+ local receiver = receiverOf(definition)
347
+ if receiver == nil then
348
+ return refuse(0)
349
+ end
350
+ if peer.counted >= L.MAX_ACTIVE_HANDLERS then
351
+ return refuse(2)
352
+ end
353
+ self:start(peer, receiver, { player, value }, {
354
+ definition = definition,
355
+ nonce = nonce,
356
+ })
357
+ end
358
+ function ServerSession:ready(peer)
359
+ peer.state = 1
360
+ self:flush(peer)
361
+ local player = peer.player
362
+ for _, claim in readyClaims() do
363
+ if peer.state ~= 1 then
364
+ return nil
365
+ end
366
+ if not isLive(claim) then
367
+ continue
368
+ end
369
+ local ok, value = self:runReady(peer, claim, claim.callback, player)
370
+ if not ok then
371
+ continue
372
+ end
373
+ if type(value) == "function" then
374
+ self:keep(peer, {
375
+ claim = claim,
376
+ cleanup = value,
377
+ })
378
+ elseif value ~= nil then
379
+ self:reportCallback(peer, claim, nil, `returned a {typeof(value)}; ClientReady callbacks return nothing or a cleanup function`)
380
+ end
381
+ end
382
+ end
383
+ end
384
+ function toClient(token, call)
385
+ local definition = definitionOf(token)
386
+ if definition == nil or definition.kind ~= "to-client" then
387
+ error(`{call} needs a message declared with toClient`, 0)
388
+ end
389
+ return definition
390
+ end
391
+ return {
392
+ ServerSession = ServerSession,
393
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,266 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local TS = _G[script]
3
+ local runtimeDiagnostic = TS.import(script, script.Parent.Parent, "diagnostics").runtimeDiagnostic
4
+ local _lifecycle = TS.import(script, script.Parent.Parent, "lifecycle")
5
+ local defer = _lifecycle.defer
6
+ local within = _lifecycle.within
7
+ local _runner = TS.import(script, script.Parent.Parent, "runner")
8
+ local disown = _runner.disown
9
+ local own = _runner.own
10
+ local isLive = TS.import(script, script.Parent, "claims").isLive
11
+ local _envelope = TS.import(script, script.Parent, "envelope")
12
+ local controlPacket = _envelope.controlPacket
13
+ local encodeBody = _envelope.encodeBody
14
+ local frame = _envelope.frame
15
+ local L = TS.import(script, script.Parent, "limits")
16
+ --* @internal
17
+ --* @internal
18
+ --* @internal
19
+ --* @internal
20
+ --* @internal
21
+ --* @internal
22
+ --* @internal
23
+ local function newPeer(player)
24
+ return {
25
+ player = player,
26
+ state = 0,
27
+ queue = {},
28
+ queuedBytes = 0,
29
+ running = {},
30
+ counted = 0,
31
+ lastRequestNonce = 0,
32
+ cleanups = {},
33
+ rejected = {},
34
+ failedClaims = {},
35
+ }
36
+ end
37
+ local function traceback(err)
38
+ return debug.traceback(tostring(err), 2)
39
+ end
40
+ local function invoke(callback, argument)
41
+ return callback(argument)
42
+ end
43
+ -- compiler-types 3.0.0-types.0 does not declare Promise.is; the RuntimeLib's TS.Promise has it.
44
+ local function isPromise(value)
45
+ return (TS.Promise).is(value)
46
+ end
47
+ --* @internal
48
+ local Session
49
+ do
50
+ Session = {}
51
+ function Session:constructor(port)
52
+ self.port = port
53
+ self.stage = 0
54
+ self.lateFailures = {}
55
+ self.noReceiver = {}
56
+ end
57
+ function Session:sendable()
58
+ if self.stage == 0 or self.stage == 1 then
59
+ error("Crucible networking is not ready; send from a constructor, a hook, or later", 0)
60
+ end
61
+ return self.stage ~= 4
62
+ end
63
+ function Session:deliver(peer, packet)
64
+ if peer.state == 1 then
65
+ self:fire(peer, packet)
66
+ return true
67
+ end
68
+ if peer.state == 2 then
69
+ return false
70
+ end
71
+ if #peer.queue >= L.MAX_QUEUED_PACKETS or packet.charge > L.MAX_QUEUED_BYTES - peer.queuedBytes then
72
+ self:fail(peer, 0)
73
+ return false
74
+ end
75
+ local _queue = peer.queue
76
+ local _packet = packet
77
+ table.insert(_queue, _packet)
78
+ peer.queuedBytes += packet.charge
79
+ return true
80
+ end
81
+ function Session:flush(peer)
82
+ local _array = {}
83
+ local _length = #_array
84
+ local _array_1 = peer.queue
85
+ table.move(_array_1, 1, #_array_1, _length + 1, _array)
86
+ local queue = _array
87
+ table.clear(peer.queue)
88
+ peer.queuedBytes = 0
89
+ for _, packet in queue do
90
+ self:fire(peer, packet)
91
+ end
92
+ end
93
+ function Session:start(peer, claim, args, request)
94
+ local entry = {
95
+ claim = claim,
96
+ request = request,
97
+ done = false,
98
+ counted = true,
99
+ settled = false,
100
+ reported = false,
101
+ }
102
+ local _exp = peer.running
103
+ table.insert(_exp, entry)
104
+ peer.counted += 1
105
+ local thread = coroutine.create(function()
106
+ local ok, value = xpcall(claim.callback, traceback, unpack(args))
107
+ disown(coroutine.running())
108
+ self:finish(peer, entry, ok, value)
109
+ end)
110
+ own(thread, claim.owner)
111
+ self.port.resume(thread)
112
+ if not entry.done and peer.state ~= 2 then
113
+ entry.lifetime = self.port.delay(L.HANDLER_LIFETIME_SECONDS, function()
114
+ return self:overrun(peer, entry)
115
+ end)
116
+ end
117
+ end
118
+ function Session:uncount(peer, entry)
119
+ if not entry.counted then
120
+ return nil
121
+ end
122
+ entry.counted = false
123
+ peer.counted -= 1
124
+ end
125
+ function Session:overrun(peer, entry)
126
+ entry.lifetime = nil
127
+ if entry.done then
128
+ return nil
129
+ end
130
+ self:reportCallback(peer, entry.claim, entry, `still running after {L.HANDLER_LIFETIME_SECONDS} seconds`)
131
+ self:uncount(peer, entry)
132
+ end
133
+ function Session:finish(peer, entry, ok, value)
134
+ entry.done = true
135
+ local _result = entry.lifetime
136
+ if _result ~= nil then
137
+ _result()
138
+ end
139
+ entry.lifetime = nil
140
+ local _running = peer.running
141
+ local _entry = entry
142
+ local index = (table.find(_running, _entry) or 0) - 1
143
+ if index ~= -1 then
144
+ table.remove(peer.running, index + 1)
145
+ end
146
+ self:uncount(peer, entry)
147
+ local failure
148
+ local request = entry.request
149
+ if not ok then
150
+ failure = tostring(value)
151
+ elseif request == nil then
152
+ if value ~= nil then
153
+ local _value = value
154
+ failure = `returned a {typeof(_value)}; event callbacks return nothing`
155
+ end
156
+ elseif isPromise(value) then
157
+ failure = "returned a Promise; request callbacks return the response"
158
+ end
159
+ local replies = request ~= nil and not entry.settled and peer.state ~= 2
160
+ local packet
161
+ if replies and failure == nil then
162
+ local _binding = request
163
+ local definition = _binding.definition
164
+ local nonce = _binding.nonce
165
+ local encoded, result = pcall(function()
166
+ return frame(encodeBody(definition.name, definition.output, "response", value), 2, { definition.index, nonce })
167
+ end)
168
+ if encoded then
169
+ packet = result
170
+ else
171
+ failure = tostring(result)
172
+ end
173
+ end
174
+ if failure ~= nil then
175
+ self:reportCallback(peer, entry.claim, entry, failure)
176
+ end
177
+ if not replies then
178
+ return nil
179
+ end
180
+ entry.settled = true
181
+ self:fire(peer, packet or controlPacket(3, { request.definition.index, request.nonce }, 1))
182
+ end
183
+ function Session:reportCallback(peer, claim, entry, message)
184
+ if entry ~= nil then
185
+ if entry.reported then
186
+ return nil
187
+ end
188
+ entry.reported = true
189
+ end
190
+ local player = peer.player
191
+ local live = player ~= nil and peer.state ~= 2
192
+ local seen = if live then peer.failedClaims else self.lateFailures
193
+ local _claim = claim
194
+ if seen[_claim] ~= nil then
195
+ return nil
196
+ end
197
+ local _claim_1 = claim
198
+ seen[_claim_1] = true
199
+ runtimeDiagnostic("error", `{claim.label}{if live then ` for {player.Name}` else ""} failed: {message}`)
200
+ end
201
+ function Session:runReady(peer, claim, work, argument)
202
+ local result, value = within(claim.owner, nil, 8, invoke, work, argument)
203
+ if result == 0 then
204
+ return true, value
205
+ end
206
+ self:reportCallback(peer, claim, nil, tostring(value))
207
+ return false, nil
208
+ end
209
+ function Session:deferCleanup(peer, entry)
210
+ defer(function()
211
+ return self:runReady(peer, entry.claim, entry.cleanup, nil)
212
+ end)
213
+ end
214
+ function Session:keep(peer, entry)
215
+ if isLive(entry.claim) and peer.state == 1 then
216
+ local _cleanups = peer.cleanups
217
+ local _entry = entry
218
+ table.insert(_cleanups, _entry)
219
+ else
220
+ self:deferCleanup(peer, entry)
221
+ end
222
+ end
223
+ Session["end"] = function(self, peer)
224
+ if peer.state == 2 then
225
+ return false
226
+ end
227
+ peer.state = 2
228
+ table.clear(peer.queue)
229
+ peer.queuedBytes = 0
230
+ for _, entry in peer.running do
231
+ local _result = entry.lifetime
232
+ if _result ~= nil then
233
+ _result()
234
+ end
235
+ entry.lifetime = nil
236
+ end
237
+ table.clear(peer.running)
238
+ table.clear(peer.rejected)
239
+ table.clear(peer.failedClaims)
240
+ local _array = {}
241
+ local _length = #_array
242
+ local _array_1 = peer.cleanups
243
+ table.move(_array_1, 1, #_array_1, _length + 1, _array)
244
+ local cleanups = _array
245
+ table.clear(peer.cleanups)
246
+ for i = #cleanups - 1, 0, -1 do
247
+ self:deferCleanup(peer, cleanups[i + 1])
248
+ end
249
+ return true
250
+ end
251
+ function Session:unreceived(definition)
252
+ local _noReceiver = self.noReceiver
253
+ local _definition = definition
254
+ if _noReceiver[_definition] ~= nil then
255
+ return nil
256
+ end
257
+ local _noReceiver_1 = self.noReceiver
258
+ local _definition_1 = definition
259
+ _noReceiver_1[_definition_1] = true
260
+ runtimeDiagnostic("warning", `Crucible dropped {definition.name}: it has no live receiver`)
261
+ end
262
+ end
263
+ return {
264
+ newPeer = newPeer,
265
+ Session = Session,
266
+ }
@@ -0,0 +1 @@
1
+ export {};