@axpecter/lync 2.3.2 → 3.0.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 (135) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +302 -299
  3. package/Types.luau +215 -0
  4. package/api/Define.luau +154 -0
  5. package/api/Lifecycle.luau +119 -0
  6. package/api/Packet.luau +108 -0
  7. package/api/Query.luau +149 -0
  8. package/api/Set.luau +189 -0
  9. package/channel/Blocks.luau +124 -0
  10. package/channel/Group.luau +118 -0
  11. package/channel/Link.luau +135 -0
  12. package/channel/Outbox.luau +261 -0
  13. package/channel/Recipients.luau +129 -0
  14. package/channel/Transport.luau +138 -0
  15. package/codec/Base.luau +236 -0
  16. package/codec/Composites.luau +128 -0
  17. package/codec/Datatypes.luau +162 -0
  18. package/codec/Legality.luau +61 -0
  19. package/codec/Scalars.luau +72 -0
  20. package/codec/Text.luau +89 -0
  21. package/codec/init.luau +39 -0
  22. package/index.d.ts +285 -0
  23. package/init.luau +91 -0
  24. package/kernel/Bits.luau +16 -0
  25. package/kernel/Catalog.luau +121 -0
  26. package/kernel/Heap.luau +80 -0
  27. package/kernel/Listeners.luau +95 -0
  28. package/kernel/Log.luau +197 -0
  29. package/kernel/Tally.luau +128 -0
  30. package/kernel/Threads.luau +44 -0
  31. package/kernel/Wide.luau +267 -0
  32. package/package.json +15 -32
  33. package/runtime/Boundary.luau +180 -0
  34. package/runtime/Dispatch.luau +91 -0
  35. package/runtime/Handles.luau +114 -0
  36. package/runtime/Handshake.luau +90 -0
  37. package/runtime/Pending.luau +196 -0
  38. package/runtime/Router.luau +379 -0
  39. package/runtime/Session.luau +731 -0
  40. package/shape/Compile.luau +340 -0
  41. package/shape/Folds.luau +332 -0
  42. package/shape/Frames.luau +170 -0
  43. package/shape/Grid.luau +169 -0
  44. package/shape/Ir.luau +540 -0
  45. package/shape/Joins.luau +125 -0
  46. package/shape/Legality.luau +273 -0
  47. package/shape/Lower.luau +419 -0
  48. package/shape/Order.luau +64 -0
  49. package/shape/Regions.luau +113 -0
  50. package/shape/Rotation.luau +472 -0
  51. package/shape/Serial.luau +258 -0
  52. package/shape/Words.luau +89 -0
  53. package/shape/emit/Block.luau +453 -0
  54. package/shape/emit/Column.luau +338 -0
  55. package/shape/emit/Leaf.luau +462 -0
  56. package/shape/emit/Word.luau +234 -0
  57. package/shape/emit/init.luau +222 -0
  58. package/shape/init.luau +78 -0
  59. package/state/Apply.luau +330 -0
  60. package/state/Audience.luau +126 -0
  61. package/state/Catchup.luau +218 -0
  62. package/state/Coalesce.luau +43 -0
  63. package/state/Fieldset.luau +177 -0
  64. package/state/Newest.luau +339 -0
  65. package/state/Plan.luau +441 -0
  66. package/state/Sections.luau +468 -0
  67. package/state/Store.luau +188 -0
  68. package/state/Sync.luau +762 -0
  69. package/wire/Bytes.luau +118 -0
  70. package/wire/Clock.luau +37 -0
  71. package/wire/Protocol.luau +110 -0
  72. package/wire/Sequence.luau +40 -0
  73. package/wire/Varint.luau +124 -0
  74. package/src/Types.luau +0 -180
  75. package/src/api/Group.luau +0 -156
  76. package/src/api/Packet.luau +0 -319
  77. package/src/api/Query.luau +0 -338
  78. package/src/api/Scope.luau +0 -90
  79. package/src/api/Signal.luau +0 -188
  80. package/src/codec/Base.luau +0 -136
  81. package/src/codec/composite/Array.luau +0 -456
  82. package/src/codec/composite/Map.luau +0 -469
  83. package/src/codec/composite/Optional.luau +0 -54
  84. package/src/codec/composite/Shared.luau +0 -291
  85. package/src/codec/composite/Struct.luau +0 -494
  86. package/src/codec/composite/Tagged.luau +0 -103
  87. package/src/codec/composite/Tuple.luau +0 -143
  88. package/src/codec/datatype/Buffer.luau +0 -66
  89. package/src/codec/datatype/CFrame.luau +0 -109
  90. package/src/codec/datatype/Color.luau +0 -32
  91. package/src/codec/datatype/Instance.luau +0 -52
  92. package/src/codec/datatype/IntVector.luau +0 -39
  93. package/src/codec/datatype/NumberRange.luau +0 -39
  94. package/src/codec/datatype/Ray.luau +0 -36
  95. package/src/codec/datatype/Rect.luau +0 -31
  96. package/src/codec/datatype/Region.luau +0 -62
  97. package/src/codec/datatype/Sequence.luau +0 -184
  98. package/src/codec/datatype/String.luau +0 -94
  99. package/src/codec/datatype/UDim.luau +0 -46
  100. package/src/codec/datatype/Vector.luau +0 -130
  101. package/src/codec/meta/Auto.luau +0 -318
  102. package/src/codec/meta/Bitfield.luau +0 -147
  103. package/src/codec/meta/Custom.luau +0 -33
  104. package/src/codec/meta/DeltaScalar.luau +0 -390
  105. package/src/codec/meta/Enum.luau +0 -50
  106. package/src/codec/meta/Float.luau +0 -38
  107. package/src/codec/meta/Nothing.luau +0 -13
  108. package/src/codec/meta/Unknown.luau +0 -41
  109. package/src/codec/primitive/Bool.luau +0 -26
  110. package/src/codec/primitive/Float16.luau +0 -99
  111. package/src/codec/primitive/Int.luau +0 -59
  112. package/src/codec/primitive/Number.luau +0 -24
  113. package/src/codec/primitive/Signed.luau +0 -32
  114. package/src/codec/primitive/Varint.luau +0 -165
  115. package/src/codec/primitive/Zint.luau +0 -99
  116. package/src/index.d.ts +0 -423
  117. package/src/init.luau +0 -362
  118. package/src/internal/Baseline.luau +0 -57
  119. package/src/internal/Channel.luau +0 -390
  120. package/src/internal/Middleware.luau +0 -100
  121. package/src/internal/Pool.luau +0 -65
  122. package/src/internal/Registry.luau +0 -119
  123. package/src/internal/Transport.luau +0 -28
  124. package/src/transport/Bridge.luau +0 -110
  125. package/src/transport/Client.luau +0 -97
  126. package/src/transport/Gate.luau +0 -488
  127. package/src/transport/Reader.luau +0 -331
  128. package/src/transport/Server.luau +0 -211
  129. package/src/util/Array.luau +0 -18
  130. package/src/util/Buffer.luau +0 -90
  131. package/src/util/Constants.luau +0 -30
  132. package/src/util/Log.luau +0 -68
  133. package/src/util/Player.luau +0 -14
  134. package/src/util/Quantize.luau +0 -84
  135. package/src/util/Quat.luau +0 -124
@@ -1,390 +0,0 @@
1
- --!strict
2
- --!native
3
- -- Per-channel buffer state with MSB batch framing, XOR delta, timestamps.
4
-
5
- local Base = require(script.Parent.Parent.codec.Base)
6
- local Buf = require(script.Parent.Parent.util.Buffer)
7
- local Constants = require(script.Parent.Parent.util.Constants)
8
- local Log = require(script.Parent.Parent.util.Log)
9
- local Types = require(script.Parent.Parent.Types)
10
- local Varint = require(script.Parent.Parent.codec.primitive.Varint)
11
-
12
- -- Constants --------------------------------------------------------------
13
-
14
- local TS_NONE = 0
15
- local TS_FRAME = 1
16
- local TS_OFFSET = 2
17
- local TS_FULL = 3
18
-
19
- local INITIAL_BUF = 1024
20
- local HEADER_BYTE = 1
21
- local FRAME_MSB = Constants.FRAME_MSB
22
- local U8_MAX = Constants.U8_MAX
23
- local U16_MAX = Constants.U16_MAX
24
- local MAX_BATCH_ITEMS = Constants.MAX_BATCH_ITEMS
25
-
26
- -- 65.535s window so round((clock % win) * 1000) cannot overflow u16.
27
- local OFFSET_WIN = 65.535
28
-
29
- local TS_BYTES = table.freeze({
30
- [TS_NONE] = 0,
31
- [TS_FRAME] = 1,
32
- [TS_OFFSET] = 2,
33
- [TS_FULL] = 8,
34
- })
35
-
36
- -- State ------------------------------------------------------------------
37
-
38
- local _timestampsEnabled = false
39
- local _statsEnabled = false
40
-
41
- -- Refreshed by updateTimestamp once per flush.
42
- local _frameCounter = 0
43
- local _offsetMs = 0
44
- local _clock = 0.0
45
-
46
- local EMPTY_REFS = table.freeze({}) :: { Instance }
47
-
48
- -- Private ----------------------------------------------------------------
49
-
50
- local alloc = Base.alloc
51
- local ensure = Base.ensure
52
- local band = bit32.band
53
- local bor = bit32.bor
54
- local bufCopy = buffer.copy
55
- local writeu8 = buffer.writeu8
56
- local writeu16 = buffer.writeu16
57
- local writef64 = buffer.writef64
58
- local round = math.round
59
- local osClock = os.clock
60
-
61
- local function writeTimestamp(b: buffer, off: number, mode: number): ()
62
- if mode == TS_FRAME then
63
- writeu8(b, off, _frameCounter)
64
- elseif mode == TS_OFFSET then
65
- writeu16(b, off, _offsetMs)
66
- elseif mode == TS_FULL then
67
- writef64(b, off, _clock)
68
- end
69
- end
70
-
71
- --[[
72
- Single -> multi upgrade. Patches the previously-emitted single-item
73
- header, splices a 2-byte count cell after the timestamp, and shifts the
74
- payload right. Hot only when a packet fires twice in a row to the same
75
- channel without an intervening flush.
76
- ]]
77
- local function upgradeSingleToMulti(ch: Types.ChannelState, regId: number, headerSize: number): ()
78
- local headerPos = ch.singlePos
79
- writeu8(ch.buff, headerPos, regId)
80
-
81
- local afterTs = headerPos + headerSize
82
- local cursor = ch.cursor
83
- local payloadLen = cursor - afterTs
84
- ensure(ch, 2)
85
- -- Re-bind: ensure() may have realloced the buffer.
86
- local b = ch.buff
87
- bufCopy(b, afterTs + 2, b, afterTs, payloadLen)
88
-
89
- ch.countPos = afterTs
90
- writeu16(b, afterTs, 0)
91
- ch.cursor = cursor + 2
92
- ch.singleMode = false
93
- end
94
-
95
- -- itemCount bump is left to the caller, AFTER the body write succeeds.
96
- local function openOrUpgrade(ch: Types.ChannelState, reg: Types.Registration): ()
97
- if reg.id ~= ch.lastId or ch.itemCount >= MAX_BATCH_ITEMS then
98
- reg._openFn(ch, reg.id)
99
- elseif ch.singleMode then
100
- upgradeSingleToMulti(ch, reg.id, reg.headerSize)
101
- end
102
- end
103
-
104
- local function spliceEncoded(ch: Types.ChannelState, payload: buffer, payloadLen: number): ()
105
- local cursor = ch.cursor
106
- if cursor + payloadLen > ch.size then
107
- alloc(ch, payloadLen)
108
- end
109
- bufCopy(ch.buff, cursor, payload, 0, payloadLen)
110
- ch.cursor = cursor + payloadLen
111
- end
112
-
113
- --[[
114
- Hot-swapped by enableStats() so the per-item dispatch avoids a runtime
115
- branch on the stats flag. itemCount bumps AFTER codec.write so a
116
- throwing codec leaves the count consistent with the buffer.
117
- ]]
118
- local writeBatchPlain: (Types.ChannelState, Types.Registration, any) -> ()
119
- local writeBatchStats: (Types.ChannelState, Types.Registration, any) -> ()
120
-
121
- writeBatchPlain = function(ch: Types.ChannelState, reg: Types.Registration, data: any): ()
122
- openOrUpgrade(ch, reg)
123
- reg.codec.write(ch, data)
124
- ch.itemCount += 1
125
- end
126
-
127
- writeBatchStats = function(ch: Types.ChannelState, reg: Types.Registration, data: any): ()
128
- openOrUpgrade(ch, reg)
129
- local before = ch.cursor
130
- reg.codec.write(ch, data)
131
- ch.itemCount += 1
132
- reg.bytesSent += ch.cursor - before
133
- end
134
-
135
- --[[
136
- Splice a pre-encoded payload into the channel. Used by Packet.broadcast
137
- to encode the codec output once per fanout instead of N times.
138
- ]]
139
- local writeBatchEncodedPlain: (Types.ChannelState, Types.Registration, buffer, number) -> ()
140
- local writeBatchEncodedStats: (Types.ChannelState, Types.Registration, buffer, number) -> ()
141
-
142
- writeBatchEncodedPlain = function(
143
- ch: Types.ChannelState,
144
- reg: Types.Registration,
145
- payload: buffer,
146
- payloadLen: number
147
- ): ()
148
- openOrUpgrade(ch, reg)
149
- spliceEncoded(ch, payload, payloadLen)
150
- ch.itemCount += 1
151
- end
152
-
153
- writeBatchEncodedStats = function(
154
- ch: Types.ChannelState,
155
- reg: Types.Registration,
156
- payload: buffer,
157
- payloadLen: number
158
- ): ()
159
- openOrUpgrade(ch, reg)
160
- spliceEncoded(ch, payload, payloadLen)
161
- ch.itemCount += 1
162
- reg.bytesSent += payloadLen
163
- end
164
-
165
- -- Public -----------------------------------------------------------------
166
-
167
- -- Module table is intentionally unfrozen: enableStats() hot-swaps writeBatch.
168
- local Channel = {}
169
-
170
- Channel.TS_NONE = TS_NONE
171
- Channel.TS_FRAME = TS_FRAME
172
- Channel.TS_OFFSET = TS_OFFSET
173
- Channel.TS_FULL = TS_FULL
174
-
175
- function Channel.create(): Types.ChannelState
176
- return {
177
- buff = buffer.create(INITIAL_BUF),
178
- cursor = 0,
179
- size = INITIAL_BUF,
180
- refs = {},
181
- refCount = 0,
182
- lastId = -1,
183
- countPos = -1,
184
- itemCount = 0,
185
- singleMode = false,
186
- singlePos = 0,
187
- deltas = {},
188
- prevDump = nil,
189
- prevDumpLen = 0,
190
- currentPacket = nil,
191
- }
192
- end
193
-
194
- function Channel.writeByte(ch: Types.ChannelState, byte: number): ()
195
- local cursor = ch.cursor
196
- if cursor + HEADER_BYTE > ch.size then
197
- alloc(ch, HEADER_BYTE)
198
- end
199
- writeu8(ch.buff, cursor, byte)
200
- ch.cursor = cursor + HEADER_BYTE
201
- end
202
-
203
- -- Append `value` to the sidecar refs, write its 1-based u16 index.
204
- function Channel.pushRef(ch: Types.ChannelState, value: any): ()
205
- local idx = ch.refCount + 1
206
- Log.assert(idx <= U16_MAX, "ref overflow, max 65535")
207
- ch.refs[idx] = value
208
- ch.refCount = idx
209
-
210
- local cursor = ch.cursor
211
- if cursor + 2 > ch.size then
212
- alloc(ch, 2)
213
- end
214
- writeu16(ch.buff, cursor, idx)
215
- ch.cursor = cursor + 2
216
- end
217
-
218
- --[[
219
- Per-flush reset. Preserves prevDump/prevDumpLen (XOR baseline) and
220
- ch.deltas (delta caches): both must outlive flushes for the same owner.
221
- ]]
222
- function Channel.reset(ch: Types.ChannelState): ()
223
- ch.cursor = 0
224
- ch.lastId = -1
225
- ch.countPos = -1
226
- ch.itemCount = 0
227
- ch.singleMode = false
228
- ch.singlePos = 0
229
- ch.currentPacket = nil
230
- if ch.refCount > 0 then
231
- table.clear(ch.refs)
232
- ch.refCount = 0
233
- end
234
- end
235
-
236
- --[[
237
- Full reset including XOR baseline and delta caches. Pool.acquire calls
238
- this so a recycled state cannot leak the previous owner's baseline.
239
- ]]
240
- function Channel.fullReset(ch: Types.ChannelState): ()
241
- Channel.reset(ch)
242
- ch.prevDump = nil
243
- ch.prevDumpLen = 0
244
- table.clear(ch.deltas)
245
- end
246
-
247
- --[[
248
- Resolve the batch-open closure for a given timestamp mode and packet
249
- name. Returned function seals the prior batch, writes the single-mode
250
- header [0x80 | id] + optional timestamp, and records the cursor so
251
- writeBatch can upgrade single -> multi later.
252
- ]]
253
- function Channel.resolveOpenFn(
254
- timestampMode: number,
255
- name: string
256
- ): (ch: Types.ChannelState, id: number) -> ()
257
- local headerLen = HEADER_BYTE + TS_BYTES[timestampMode]
258
-
259
- return function(ch: Types.ChannelState, id: number): ()
260
- --[[
261
- Inline sealCount: this is the only call site that can take the
262
- multi-mode branch on a non-fresh channel.
263
- ]]
264
- if ch.lastId >= 0 and not ch.singleMode then
265
- writeu16(ch.buff, ch.countPos, ch.itemCount)
266
- end
267
-
268
- ch.currentPacket = name
269
- ch.lastId = id
270
- ch.itemCount = 0
271
-
272
- local cursor = ch.cursor
273
- if cursor + headerLen > ch.size then
274
- alloc(ch, headerLen)
275
- end
276
- local b = ch.buff
277
- writeu8(b, cursor, bor(FRAME_MSB, id))
278
- writeTimestamp(b, cursor + 1, timestampMode)
279
-
280
- ch.singleMode = true
281
- ch.singlePos = cursor
282
- ch.cursor = cursor + headerLen
283
- end
284
- end
285
-
286
- Channel.writeBatch = writeBatchPlain
287
- Channel.writeBatchEncoded = writeBatchEncodedPlain
288
-
289
- --[[
290
- Every caller (Server.flushReliable / flushUnreliable, Client.flush)
291
- pre-checks `ch.cursor > 0`, so cursor here is always positive.
292
- ]]
293
- function Channel.sealAndDump(ch: Types.ChannelState): (buffer, { Instance }, number, number)
294
- if ch.lastId >= 0 and not ch.singleMode then
295
- writeu16(ch.buff, ch.countPos, ch.itemCount)
296
- end
297
-
298
- local cursor = ch.cursor
299
- local snapshot = buffer.create(cursor)
300
- bufCopy(snapshot, 0, ch.buff, 0, cursor)
301
-
302
- local refCount = ch.refCount
303
- local refs = if refCount > 0 then table.clone(ch.refs) else EMPTY_REFS
304
- return snapshot, refs, cursor, refCount
305
- end
306
-
307
- Channel.xorApply = Buf.xorApply
308
-
309
- --[[
310
- Query frame. MSB on the id byte = nil response; cleared = payload follows.
311
- Correlation IDs are varint-encoded.
312
- ]]
313
- function Channel.writeQuery(
314
- ch: Types.ChannelState,
315
- id: number,
316
- correlationId: number,
317
- codec: Types.InternalCodec<any>?,
318
- data: any
319
- ): ()
320
- if ch.lastId >= 0 and not ch.singleMode then
321
- writeu16(ch.buff, ch.countPos, ch.itemCount)
322
- end
323
- --[[
324
- lastId = -1 forces the next writeBatch to call _openFn (which resets
325
- singleMode). Every other reader of singleMode (writeQuery,
326
- sealAndDump) is gated by `lastId >= 0` first, so stamping singleMode
327
- here would never be observed before the next reset overwrites it.
328
- ]]
329
- ch.lastId = -1
330
-
331
- local hasPayload = codec ~= nil and data ~= nil
332
- local headerByte = if hasPayload then id else bor(FRAME_MSB, id)
333
-
334
- local cursor = ch.cursor
335
- if cursor + 1 > ch.size then
336
- alloc(ch, 1)
337
- end
338
- writeu8(ch.buff, cursor, headerByte)
339
- ch.cursor = cursor + 1
340
-
341
- Varint.write(ch, correlationId)
342
- if hasPayload then
343
- (codec :: Types.InternalCodec<any>).write(ch, data)
344
- end
345
- end
346
-
347
- -- Configuration ----------------------------------------------------------
348
-
349
- function Channel.setMaxSize(bytes: number): ()
350
- Base.setMaxSize(bytes)
351
- end
352
-
353
- function Channel.updateTimestamp(): ()
354
- _frameCounter = band(_frameCounter + 1, U8_MAX)
355
- local now = osClock()
356
- _offsetMs = round((now % OFFSET_WIN) * 1000)
357
- _clock = now
358
- end
359
-
360
- function Channel.enableTimestamps(): ()
361
- _timestampsEnabled = true
362
- end
363
-
364
- function Channel.hasTimestamps(): boolean
365
- return _timestampsEnabled
366
- end
367
-
368
- function Channel.enableStats(): ()
369
- _statsEnabled = true
370
- Channel.writeBatch = writeBatchStats
371
- Channel.writeBatchEncoded = writeBatchEncodedStats
372
- end
373
-
374
- function Channel.statsEnabled(): boolean
375
- return _statsEnabled
376
- end
377
-
378
- -- Module-level config + timestamp counters. Distinct from Channel.reset(ch).
379
- function Channel.resetGlobals(): ()
380
- Base.reset()
381
- _timestampsEnabled = false
382
- _statsEnabled = false
383
- _frameCounter = 0
384
- _offsetMs = 0
385
- _clock = 0.0
386
- Channel.writeBatch = writeBatchPlain
387
- Channel.writeBatchEncoded = writeBatchEncodedPlain
388
- end
389
-
390
- return Channel
@@ -1,100 +0,0 @@
1
- --!strict
2
- --!optimize 2
3
- -- Ordered intercept chains for send/receive/drop hooks.
4
-
5
- local Signal = require(script.Parent.Parent.api.Signal)
6
- local Types = require(script.Parent.Parent.Types)
7
-
8
- -- State ------------------------------------------------------------------
9
-
10
- local _sendSignal = Signal.create()
11
- local _receiveSignal = Signal.create()
12
- local _dropSignal = Signal.create()
13
-
14
- -- Private ----------------------------------------------------------------
15
-
16
- -- Mirrors Signal's STATE_DISCONNECTED. Entries in this state are mid-fire disconnects.
17
- local STATE_DISCONNECTED = 0
18
-
19
- --[[
20
- Snapshot before iterating: a handler can disconnect itself or others,
21
- and a fresh chain pull would skip or double-fire entries depending on
22
- swap direction. Snapshotting locks the per-frame view.
23
- ]]
24
- local function runChain(
25
- signal: { _count: number, _entries: { any } },
26
- value: any,
27
- name: string,
28
- player: Player?
29
- ): any
30
- local count = signal._count
31
- if count == 0 then
32
- return value
33
- end
34
-
35
- local entries = signal._entries
36
- local snapshot = table.create(count)
37
- table.move(entries, 1, count, 1, snapshot)
38
-
39
- local result = value
40
- for i = 1, count do
41
- local entry = snapshot[i]
42
- if entry._state ~= STATE_DISCONNECTED then
43
- local returned = entry.fn(result, name, player)
44
- -- Hooks return non-nil to replace the value; nil keeps the prior result.
45
- if returned ~= nil then
46
- result = returned
47
- end
48
- end
49
- end
50
- return result
51
- end
52
-
53
- -- Public -----------------------------------------------------------------
54
-
55
- local Middleware = {}
56
-
57
- function Middleware.onSend(fn: (data: any, name: string, player: Player?) -> any): Types.Connection
58
- return _sendSignal:connect(fn)
59
- end
60
-
61
- function Middleware.onReceive(
62
- fn: (data: any, name: string, player: Player?) -> any
63
- ): Types.Connection
64
- return _receiveSignal:connect(fn)
65
- end
66
-
67
- function Middleware.onDrop(
68
- fn: (player: Player, reason: string, name: string, data: any?) -> ()
69
- ): Types.Connection
70
- return _dropSignal:connect(fn)
71
- end
72
-
73
- function Middleware.runSend(data: any, name: string, player: Player?): any
74
- return runChain(_sendSignal, data, name, player)
75
- end
76
-
77
- function Middleware.runReceive(data: any, name: string, player: Player?): any
78
- return runChain(_receiveSignal, data, name, player)
79
- end
80
-
81
- function Middleware.fireDrop(player: Player, reason: string, name: string, data: any?): ()
82
- _dropSignal:fireSync(player, reason, name, data)
83
- end
84
-
85
- -- Hot-path callers gate on these to skip runChain's snapshot allocation.
86
- function Middleware.hasSendHooks(): boolean
87
- return _sendSignal:hasListeners()
88
- end
89
-
90
- function Middleware.hasReceiveHooks(): boolean
91
- return _receiveSignal:hasListeners()
92
- end
93
-
94
- function Middleware.reset(): ()
95
- _sendSignal = Signal.create()
96
- _receiveSignal = Signal.create()
97
- _dropSignal = Signal.create()
98
- end
99
-
100
- return table.freeze(Middleware)
@@ -1,65 +0,0 @@
1
- --!strict
2
- --!optimize 2
3
- -- ChannelState pool. Acquire fullResets to wipe prior owner state.
4
-
5
- local Channel = require(script.Parent.Channel)
6
- local Log = require(script.Parent.Parent.util.Log)
7
- local Types = require(script.Parent.Parent.Types)
8
-
9
- -- Constants --------------------------------------------------------------
10
-
11
- local DEFAULT_SIZE = 16
12
-
13
- -- State ------------------------------------------------------------------
14
-
15
- local _stack: { Types.ChannelState } = {}
16
- local _depth = 0
17
- local _maxSize = DEFAULT_SIZE
18
-
19
- -- Public -----------------------------------------------------------------
20
-
21
- local Pool = {}
22
-
23
- -- fullReset wipes the prior owner's XOR baseline and delta caches.
24
- function Pool.acquire(): Types.ChannelState
25
- if _depth > 0 then
26
- local ch = _stack[_depth]
27
- _stack[_depth] = nil
28
- _depth -= 1
29
- Channel.fullReset(ch)
30
- return ch
31
- end
32
- return Channel.create()
33
- end
34
-
35
- -- Above the cap, drop on the floor; the GC reclaims the buffer.
36
- function Pool.release(ch: Types.ChannelState): ()
37
- if _depth >= _maxSize then
38
- return
39
- end
40
- _depth += 1
41
- _stack[_depth] = ch
42
- end
43
-
44
- function Pool.setMaxSize(size: number): ()
45
- if size < 0 then
46
- Log.error(`size must be non-negative, got {size}`)
47
- end
48
- _maxSize = size
49
- while _depth > _maxSize do
50
- _stack[_depth] = nil
51
- _depth -= 1
52
- end
53
- end
54
-
55
- function Pool.count(): number
56
- return _depth
57
- end
58
-
59
- function Pool.reset(): ()
60
- table.clear(_stack)
61
- _depth = 0
62
- _maxSize = DEFAULT_SIZE
63
- end
64
-
65
- return table.freeze(Pool)
@@ -1,119 +0,0 @@
1
- --!strict
2
- --!optimize 2
3
- -- Sequential 7-bit packet/query ID assignment.
4
-
5
- local Log = require(script.Parent.Parent.util.Log)
6
- local Signal = require(script.Parent.Parent.api.Signal)
7
- local Types = require(script.Parent.Parent.Types)
8
-
9
- -- Constants --------------------------------------------------------------
10
-
11
- local KIND_PACKET = 0
12
- local KIND_REQUEST = 1
13
- local KIND_RESPONSE = 2
14
-
15
- -- 7-bit id leaves the MSB free for the frame single/multi flag (see Constants.FRAME_MSB).
16
- local MAX_ID = 127
17
-
18
- -- State ------------------------------------------------------------------
19
-
20
- local _nextId = 0
21
- local _registrationsById: { [number]: Types.Registration } = {}
22
- local _registrationsByName: { [string]: Types.Registration } = {}
23
-
24
- -- Public -----------------------------------------------------------------
25
-
26
- local Registry = {}
27
-
28
- Registry.KIND_PACKET = KIND_PACKET
29
- Registry.KIND_REQUEST = KIND_REQUEST
30
- Registry.KIND_RESPONSE = KIND_RESPONSE
31
- Registry.MAX_ID = MAX_ID
32
-
33
- export type RegisterOptions = {
34
- name: string,
35
- kind: number,
36
- codec: Types.InternalCodec<any>,
37
- isUnreliable: boolean,
38
- partner: number?,
39
- needsGate: boolean,
40
- headerSize: number,
41
- timestampMode: number,
42
- openFn: (ch: Types.ChannelState, id: number) -> (),
43
- rateLimit: Types.RateLimitConfig?,
44
- validate: Types.ValidateFn?,
45
- maxPayloadBytes: number?,
46
- }
47
-
48
- function Registry.register(opts: RegisterOptions): Types.Registration
49
- local nextCandidate = _nextId + 1
50
- if nextCandidate > MAX_ID then
51
- Log.error(`ID limit ({MAX_ID}) exceeded; cannot register "{opts.name}"`)
52
- end
53
- --[[
54
- RESPONSE entries share their request's name with a "\0resp" suffix; only
55
- request/packet names need uniqueness in the by-name index.
56
- ]]
57
- if opts.kind ~= KIND_RESPONSE and _registrationsByName[opts.name] ~= nil then
58
- Log.error(`duplicate name "{opts.name}"`)
59
- end
60
-
61
- _nextId = nextCandidate
62
-
63
- local reg: Types.Registration = {
64
- id = nextCandidate,
65
- name = opts.name,
66
- kind = opts.kind,
67
- codec = opts.codec,
68
- isUnreliable = opts.isUnreliable,
69
- partner = opts.partner,
70
- signal = Signal.create(),
71
- rateLimit = opts.rateLimit,
72
- validate = opts.validate,
73
- needsGate = opts.needsGate,
74
- maxPayloadBytes = opts.maxPayloadBytes,
75
- timestampMode = opts.timestampMode,
76
- headerSize = opts.headerSize,
77
- _openFn = opts.openFn,
78
- bytesSent = 0,
79
- bytesReceived = 0,
80
- fires = 0,
81
- recvFires = 0,
82
- drops = 0,
83
- }
84
-
85
- _registrationsById[nextCandidate] = reg
86
- if opts.kind ~= KIND_RESPONSE then
87
- _registrationsByName[opts.name] = reg
88
- end
89
- return reg
90
- end
91
-
92
- function Registry.get(id: number): Types.Registration?
93
- return _registrationsById[id]
94
- end
95
-
96
- function Registry.getByName(name: string): Types.Registration?
97
- return _registrationsByName[name]
98
- end
99
-
100
- function Registry.count(): number
101
- return _nextId
102
- end
103
-
104
- -- IDs are sequential and never freed, so the table has no holes.
105
- function Registry.all(): { Types.Registration }
106
- local result = table.create(_nextId)
107
- for i = 1, _nextId do
108
- result[i] = _registrationsById[i]
109
- end
110
- return result
111
- end
112
-
113
- function Registry.reset(): ()
114
- table.clear(_registrationsById)
115
- table.clear(_registrationsByName)
116
- _nextId = 0
117
- end
118
-
119
- return table.freeze(Registry)
@@ -1,28 +0,0 @@
1
- --!strict
2
- --!optimize 2
3
- -- Lazy Server/Client require to break the api -> transport import cycle.
4
-
5
- -- State ------------------------------------------------------------------
6
-
7
- local _server: any = nil
8
- local _client: any = nil
9
-
10
- -- Public -----------------------------------------------------------------
11
-
12
- local Transport = {}
13
-
14
- function Transport.server(): any
15
- if not _server then
16
- _server = require(script.Parent.Parent.transport.Server)
17
- end
18
- return _server
19
- end
20
-
21
- function Transport.client(): any
22
- if not _client then
23
- _client = require(script.Parent.Parent.transport.Client)
24
- end
25
- return _client
26
- end
27
-
28
- return table.freeze(Transport)