@axpecter/lync 2.3.3 → 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 -317
  77. package/src/api/Query.luau +0 -338
  78. package/src/api/Scope.luau +0 -90
  79. package/src/api/Signal.luau +0 -193
  80. package/src/codec/Base.luau +0 -136
  81. package/src/codec/composite/Array.luau +0 -473
  82. package/src/codec/composite/Map.luau +0 -485
  83. package/src/codec/composite/Optional.luau +0 -54
  84. package/src/codec/composite/Shared.luau +0 -311
  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 -160
  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 -484
  120. package/src/internal/Middleware.luau +0 -100
  121. package/src/internal/Pool.luau +0 -66
  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 -233
  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,156 +0,0 @@
1
- --!strict
2
- --!optimize 2
3
- -- Named player sets with __iter and auto-cleanup on PlayerRemoving.
4
-
5
- local Players = game:GetService("Players")
6
-
7
- local Array = require(script.Parent.Parent.util.Array)
8
- local Log = require(script.Parent.Parent.util.Log)
9
-
10
- -- Public types -----------------------------------------------------------
11
-
12
- export type GroupHandle = {
13
- add: (self: GroupHandle, player: Player) -> boolean,
14
- remove: (self: GroupHandle, player: Player) -> boolean,
15
- has: (self: GroupHandle, player: Player) -> boolean,
16
- count: (self: GroupHandle) -> number,
17
- destroy: (self: GroupHandle) -> (),
18
- _lyncKind: "group",
19
- _members: { [Player]: boolean },
20
- }
21
-
22
- type GroupInternal = GroupHandle & { _count: number, _name: string }
23
-
24
- -- State ------------------------------------------------------------------
25
-
26
- local _groups: { [string]: GroupInternal } = {}
27
- -- Reverse index used by PlayerRemoving so we don't scan every group on disconnect.
28
- local _playerCleanup: { [Player]: { Group } } = {}
29
- local _cleanupConnected = false
30
-
31
- -- Private ----------------------------------------------------------------
32
-
33
- local swapRemove = Array.swapRemove
34
-
35
- -- Connect once on the first Group.create; subsequent creates reuse the same connection.
36
- local function ensureCleanup(): ()
37
- if _cleanupConnected then
38
- return
39
- end
40
- _cleanupConnected = true
41
-
42
- Players.PlayerRemoving:Connect(function(player: Player)
43
- local groups = _playerCleanup[player]
44
- if not groups then
45
- return
46
- end
47
- for _, group in groups do
48
- group._members[player] = nil
49
- group._count -= 1
50
- end
51
- _playerCleanup[player] = nil
52
- end)
53
- end
54
-
55
- local function untrackCleanup(player: Player, group: GroupInternal): ()
56
- local cleanup = _playerCleanup[player]
57
- if not cleanup then
58
- return
59
- end
60
- local idx = table.find(cleanup, group)
61
- if idx then
62
- swapRemove(cleanup, idx)
63
- end
64
- end
65
-
66
- -- Public -----------------------------------------------------------------
67
-
68
- local Group = {}
69
-
70
- local GroupMeta = {}
71
- GroupMeta.__index = GroupMeta
72
-
73
- -- __iter lets `for player in group do` skip the explicit :members() call.
74
- function GroupMeta.__iter(self: GroupInternal): (any, any, any)
75
- return next, self._members, nil
76
- end
77
-
78
- function GroupMeta.add(self: GroupInternal, player: Player): boolean
79
- if self._members[player] then
80
- return false
81
- end
82
-
83
- self._members[player] = true
84
- self._count += 1
85
-
86
- local cleanup = _playerCleanup[player]
87
- if not cleanup then
88
- cleanup = {}
89
- _playerCleanup[player] = cleanup
90
- end
91
- table.insert(cleanup, self)
92
- return true
93
- end
94
-
95
- function GroupMeta.remove(self: GroupInternal, player: Player): boolean
96
- if not self._members[player] then
97
- return false
98
- end
99
-
100
- self._members[player] = nil
101
- self._count -= 1
102
- untrackCleanup(player, self)
103
- return true
104
- end
105
-
106
- function GroupMeta.has(self: GroupInternal, player: Player): boolean
107
- return self._members[player] == true
108
- end
109
-
110
- function GroupMeta.count(self: GroupInternal): number
111
- return self._count
112
- end
113
-
114
- function GroupMeta.destroy(self: GroupInternal): ()
115
- if _groups[self._name] == self then
116
- _groups[self._name] = nil
117
- end
118
-
119
- for player in self._members do
120
- untrackCleanup(player, self)
121
- end
122
-
123
- table.clear(self._members)
124
- self._count = 0
125
- end
126
-
127
- table.freeze(GroupMeta)
128
-
129
- function Group.create(name: string): GroupHandle
130
- if _groups[name] then
131
- Log.error(`"{name}" already exists`)
132
- end
133
-
134
- ensureCleanup()
135
-
136
- local group = setmetatable({
137
- _lyncKind = "group" :: "group",
138
- _members = {} :: { [Player]: boolean },
139
- _count = 0,
140
- _name = name,
141
- }, GroupMeta) :: any
142
-
143
- _groups[name] = group
144
- return group
145
- end
146
-
147
- function Group.reset(): ()
148
- for _, group in _groups do
149
- table.clear(group._members)
150
- group._count = 0
151
- end
152
- table.clear(_groups)
153
- table.clear(_playerCleanup)
154
- end
155
-
156
- return table.freeze(Group)
@@ -1,317 +0,0 @@
1
- --!strict
2
- --!optimize 2
3
- -- Packet definition: send, on, once, wait, stats.
4
-
5
- local Players = game:GetService("Players")
6
- local RunService = game:GetService("RunService")
7
-
8
- local Baseline = require(script.Parent.Parent.internal.Baseline)
9
- local Channel = require(script.Parent.Parent.internal.Channel)
10
- local Log = require(script.Parent.Parent.util.Log)
11
- local Middleware = require(script.Parent.Parent.internal.Middleware)
12
- local Player = require(script.Parent.Parent.util.Player)
13
- local Registry = require(script.Parent.Parent.internal.Registry)
14
- local Shared = require(script.Parent.Parent.codec.composite.Shared)
15
- local Transport = require(script.Parent.Parent.internal.Transport)
16
- local Types = require(script.Parent.Parent.Types)
17
-
18
- -- Constants --------------------------------------------------------------
19
-
20
- local IS_SERVER = RunService:IsServer()
21
-
22
- -- mode: TS_* tag; headerSize: 1 (frame byte) + timestamp bytes (1, 2, or 8).
23
- local TS_MODES: { [string]: { mode: number, headerSize: number } } = table.freeze({
24
- frame = table.freeze({ mode = Channel.TS_FRAME, headerSize = 2 }),
25
- offset = table.freeze({ mode = Channel.TS_OFFSET, headerSize = 3 }),
26
- full = table.freeze({ mode = Channel.TS_FULL, headerSize = 9 }),
27
- })
28
-
29
- local EMPTY_OPTIONS: Types.PacketOptions = table.freeze({})
30
-
31
- -- Private ----------------------------------------------------------------
32
-
33
- local isPlayer = Player.is
34
-
35
- local function resolveTimestampMode(ts: ("frame" | "offset" | "full")?): (number, number)
36
- if ts == nil then
37
- return Channel.TS_NONE, 1
38
- end
39
- local entry = TS_MODES[ts]
40
- Channel.enableTimestamps()
41
- return entry.mode, entry.headerSize
42
- end
43
-
44
- -- Public types -----------------------------------------------------------
45
-
46
- export type PacketHandle<T> = {
47
- send: (self: PacketHandle<T>, data: T, target: any?) -> (),
48
- on: (
49
- self: PacketHandle<T>,
50
- fn: (data: T, sender: Player?, timestamp: number?) -> ()
51
- ) -> Types.Connection,
52
- once: (
53
- self: PacketHandle<T>,
54
- fn: (data: T, sender: Player?, timestamp: number?) -> ()
55
- ) -> Types.Connection,
56
- wait: (self: PacketHandle<T>) -> (T, Player?, number?),
57
- name: (self: PacketHandle<T>) -> string,
58
- stats: (self: PacketHandle<T>) -> Types.PacketStats,
59
- }
60
-
61
- -- Public -----------------------------------------------------------------
62
-
63
- local Packet = {}
64
-
65
- function Packet.define<T>(
66
- name: string,
67
- codec: Types.InternalCodec<T>,
68
- options: Types.PacketOptions?
69
- ): PacketHandle<T>
70
- local opts = options or EMPTY_OPTIONS
71
- local isUnreliable = opts.unreliable or false
72
-
73
- -- Delta + unreliable is unsafe: a dropped frame permanently desyncs the receiver baseline.
74
- if isUnreliable and codec._isDelta then
75
- Log.error(
76
- `"{name}" delta codecs need reliable transport (lost packets desync the baseline)`
77
- )
78
- end
79
-
80
- if codec._hasUnknown and not opts.validate then
81
- Log.warn(`"{name}" uses unknown codec without validate; data bypasses schema validation`)
82
- end
83
-
84
- if codec._isDelta then
85
- Baseline.markHasDelta()
86
- end
87
-
88
- local tsMode, headerSize = resolveTimestampMode(opts.timestamp)
89
- local openFn = Channel.resolveOpenFn(tsMode, name)
90
-
91
- local reg = Registry.register({
92
- name = name,
93
- kind = Registry.KIND_PACKET,
94
- codec = codec,
95
- isUnreliable = isUnreliable,
96
- partner = nil,
97
- needsGate = IS_SERVER,
98
- headerSize = headerSize,
99
- timestampMode = tsMode,
100
- openFn = openFn,
101
- rateLimit = opts.rateLimit,
102
- validate = opts.validate,
103
- maxPayloadBytes = opts.maxPayloadBytes,
104
- })
105
-
106
- local function sendToPlayer(player: Player, data: any): ()
107
- local ch = Transport.server().getChannel(player, isUnreliable)
108
- Channel.writeBatch(ch, reg, data)
109
- end
110
-
111
- local function bumpFires(): ()
112
- if Channel.statsEnabled() then
113
- reg.fires += 1
114
- end
115
- end
116
-
117
- --[[
118
- Run the send middleware chain. Returns (dropped, value). A nil value
119
- is a legitimate payload (Lync.nothing); only the explicit Lync.DROP
120
- sentinel or a hook returning DROP triggers the drop branch.
121
- ]]
122
- local function applySend(data: any, player: Player?): (boolean, any)
123
- if not Middleware.hasSendHooks() then
124
- return false, data
125
- end
126
- local sendData = Middleware.runSend(data, name, player)
127
- if typeof(sendData) == "table" and sendData._lyncKind == "drop" then
128
- return true, nil
129
- end
130
- return false, sendData
131
- end
132
-
133
- -- Non-delta codecs are stateless wire-encoders, so broadcast can encode
134
- -- once and bufCopy the payload to every player. Falls through if the
135
- -- encoded payload includes ref indices (the indices would need rewriting
136
- -- per channel, which no codec exposes).
137
- local canEncodeOnce = not codec._isDelta and not codec._hasDelta
138
-
139
- local function broadcast(players: { Player }, data: any): ()
140
- local count = #players
141
- if count == 0 then
142
- bumpFires()
143
- return
144
- end
145
-
146
- if canEncodeOnce then
147
- local scratch = Shared.acquireScratch()
148
- scratch.currentPacket = name
149
- codec.write(scratch, data)
150
- scratch.currentPacket = nil
151
- if scratch.refCount == 0 then
152
- local payload = scratch.buff
153
- local payloadLen = scratch.cursor
154
- local server = Transport.server()
155
- local getChannel = if isUnreliable
156
- then server.getUnreliableChannel
157
- else server.getReliableChannel
158
- -- Channel.writeBatchEncoded is hot-swapped by enableStats; re-read per call.
159
- local writeBatchEncoded = Channel.writeBatchEncoded
160
- for i = 1, count do
161
- writeBatchEncoded(getChannel(players[i]), reg, payload, payloadLen)
162
- end
163
- Shared.releaseScratch()
164
- bumpFires()
165
- return
166
- end
167
- Shared.releaseScratch()
168
- end
169
-
170
- for i = 1, count do
171
- sendToPlayer(players[i], data)
172
- end
173
- bumpFires()
174
- end
175
-
176
- --[[
177
- Resolve a target table into a { Player } list. Returns nil for unknown
178
- sentinel kinds; the caller errors with the original target type.
179
- ]]
180
- local function resolveAudience(target: any): { Player }?
181
- local kind = target._lyncKind
182
- if kind == "all" then
183
- return Players:GetPlayers()
184
- end
185
-
186
- if kind == "except" then
187
- local excluded = target._excluded :: { [Player]: boolean }
188
- local all = Players:GetPlayers()
189
- local list = table.create(#all)
190
- local n = 0
191
- for _, player in all do
192
- if not excluded[player] then
193
- n += 1
194
- list[n] = player
195
- end
196
- end
197
- return list
198
- end
199
-
200
- if kind == "group" then
201
- local members = target._members :: { [Player]: boolean }
202
- local list: { Player } = {}
203
- local n = 0
204
- for player in members do
205
- n += 1
206
- list[n] = player
207
- end
208
- return list
209
- end
210
-
211
- if kind == nil then
212
- -- Plain { Player } array. Validate entries on the way to a clean list.
213
- local list: { Player } = {}
214
- local n = 0
215
- for _, player in target do
216
- if isPlayer(player) then
217
- n += 1
218
- list[n] = player :: Player
219
- end
220
- end
221
- return list
222
- end
223
-
224
- return nil
225
- end
226
-
227
- local function sendToTarget(data: any, target: any): ()
228
- if isPlayer(target) then
229
- local dropped, sendData = applySend(data, target :: Player)
230
- if dropped then
231
- return
232
- end
233
- sendToPlayer(target :: Player, sendData)
234
- bumpFires()
235
- return
236
- end
237
-
238
- if typeof(target) == "table" then
239
- local dropped, sendData = applySend(data, nil)
240
- if dropped then
241
- return
242
- end
243
- local audience = resolveAudience(target)
244
- if audience then
245
- broadcast(audience, sendData)
246
- return
247
- end
248
- end
249
-
250
- Log.error(`"{name}" expected Player, table, Group, or Lync.all, got {typeof(target)}`)
251
- end
252
-
253
- local function sendFromServer(data: any, target: any): ()
254
- if target == nil then
255
- Log.error(`"{name}" server send requires a target`)
256
- end
257
- sendToTarget(data, target)
258
- end
259
-
260
- local function sendFromClient(data: any): ()
261
- local dropped, sendData = applySend(data, nil)
262
- if dropped then
263
- return
264
- end
265
- local ch = Transport.client().getChannel(isUnreliable)
266
- Channel.writeBatch(ch, reg, sendData)
267
- bumpFires()
268
- end
269
-
270
- type Self = PacketHandle<T>
271
- type Listener = (data: T, sender: Player?, timestamp: number?) -> ()
272
-
273
- local handle = {
274
- send = function(_self: Self, data: T, target: any?): ()
275
- if IS_SERVER then
276
- sendFromServer(data, target)
277
- else
278
- sendFromClient(data)
279
- end
280
- end,
281
-
282
- on = function(_self: Self, fn: Listener): Types.Connection
283
- return reg.signal:connect(fn :: any)
284
- end,
285
-
286
- once = function(_self: Self, fn: Listener): Types.Connection
287
- local conn: Types.Connection
288
- conn = reg.signal:connect(function(...: any)
289
- conn:disconnect()
290
- fn(...)
291
- end)
292
- return conn
293
- end,
294
-
295
- wait = function(_self: Self): (T, Player?, number?)
296
- return reg.signal:wait()
297
- end,
298
-
299
- name = function(_self: Self): string
300
- return reg.name
301
- end,
302
-
303
- stats = function(_self: Self): Types.PacketStats
304
- return {
305
- bytesSent = reg.bytesSent,
306
- bytesReceived = reg.bytesReceived,
307
- fires = reg.fires,
308
- recvFires = reg.recvFires,
309
- drops = reg.drops,
310
- }
311
- end,
312
- }
313
-
314
- return table.freeze(handle) :: PacketHandle<T>
315
- end
316
-
317
- return table.freeze(Packet)