@axpecter/lync 2.1.2 → 2.2.1
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/README.md +241 -349
- package/package.json +1 -1
- package/src/Types.luau +53 -13
- package/src/api/Group.luau +41 -51
- package/src/api/Packet.luau +163 -152
- package/src/api/Query.luau +224 -211
- package/src/api/Scope.luau +36 -38
- package/src/api/Signal.luau +68 -94
- package/src/codec/Base.luau +43 -23
- package/src/codec/composite/Array.luau +161 -152
- package/src/codec/composite/Map.luau +37 -53
- package/src/codec/composite/Optional.luau +15 -21
- package/src/codec/composite/Shared.luau +78 -41
- package/src/codec/composite/Struct.luau +64 -125
- package/src/codec/composite/Tagged.luau +15 -25
- package/src/codec/composite/Tuple.luau +15 -20
- package/src/codec/datatype/Buffer.luau +44 -51
- package/src/codec/datatype/CFrame.luau +72 -104
- package/src/codec/datatype/Color.luau +14 -10
- package/src/codec/datatype/Instance.luau +32 -42
- package/src/codec/datatype/IntVector.luau +24 -22
- package/src/codec/datatype/NumberRange.luau +21 -12
- package/src/codec/datatype/Ray.luau +13 -7
- package/src/codec/datatype/Rect.luau +13 -7
- package/src/codec/datatype/Region.luau +25 -22
- package/src/codec/datatype/Sequence.luau +144 -118
- package/src/codec/datatype/String.luau +29 -59
- package/src/codec/datatype/UDim.luau +29 -30
- package/src/codec/datatype/Vector.luau +89 -105
- package/src/codec/meta/Auto.luau +194 -246
- package/src/codec/meta/Bitfield.luau +37 -36
- package/src/codec/meta/Custom.luau +10 -10
- package/src/codec/meta/Enum.luau +8 -11
- package/src/codec/meta/Float.luau +16 -20
- package/src/codec/meta/Nothing.luau +2 -2
- package/src/codec/meta/Unknown.luau +22 -32
- package/src/codec/primitive/Bool.luau +9 -5
- package/src/codec/primitive/Float16.luau +13 -23
- package/src/codec/primitive/Int.luau +20 -28
- package/src/codec/primitive/Number.luau +6 -10
- package/src/codec/primitive/Signed.luau +32 -0
- package/src/codec/primitive/Varint.luau +59 -28
- package/src/index.d.ts +8 -2
- package/src/init.luau +133 -143
- package/src/internal/Baseline.luau +17 -18
- package/src/internal/Channel.luau +143 -212
- package/src/internal/Middleware.luau +37 -47
- package/src/internal/Pool.luau +10 -10
- package/src/internal/Registry.luau +38 -34
- package/src/internal/Transport.luau +28 -0
- package/src/internal/Util.luau +26 -0
- package/src/transport/Bridge.luau +32 -24
- package/src/transport/Client.luau +51 -53
- package/src/transport/Gate.luau +183 -113
- package/src/transport/Reader.luau +95 -66
- package/src/transport/Server.luau +130 -125
package/src/api/Packet.luau
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
--!strict
|
|
2
2
|
--!optimize 2
|
|
3
|
-
-- Packet definition
|
|
3
|
+
-- Packet definition: send, on, once, wait, stats.
|
|
4
4
|
|
|
5
5
|
local Players = game:GetService("Players")
|
|
6
6
|
local RunService = game:GetService("RunService")
|
|
@@ -9,226 +9,237 @@ local Baseline = require(script.Parent.Parent.internal.Baseline)
|
|
|
9
9
|
local Channel = require(script.Parent.Parent.internal.Channel)
|
|
10
10
|
local Middleware = require(script.Parent.Parent.internal.Middleware)
|
|
11
11
|
local Registry = require(script.Parent.Parent.internal.Registry)
|
|
12
|
+
local Transport = require(script.Parent.Parent.internal.Transport)
|
|
12
13
|
local Types = require(script.Parent.Parent.Types)
|
|
14
|
+
local Util = require(script.Parent.Parent.internal.Util)
|
|
13
15
|
|
|
14
|
-
-- Constants
|
|
16
|
+
-- Constants --------------------------------------------------------------
|
|
15
17
|
|
|
16
18
|
local IS_SERVER = RunService:IsServer()
|
|
17
19
|
|
|
18
|
-
-- Private
|
|
20
|
+
-- Private ----------------------------------------------------------------
|
|
19
21
|
|
|
20
|
-
local
|
|
22
|
+
local isPlayer = Util.isPlayer
|
|
23
|
+
|
|
24
|
+
local function resolveTimestampMode(ts: ("frame" | "offset" | "full")?): (number, number)
|
|
21
25
|
if ts == "frame" then
|
|
22
26
|
Channel.enableTimestamps()
|
|
23
27
|
return Channel.TS_FRAME, 2
|
|
24
|
-
|
|
28
|
+
end
|
|
29
|
+
if ts == "offset" then
|
|
25
30
|
Channel.enableTimestamps()
|
|
26
31
|
return Channel.TS_OFFSET, 3
|
|
27
|
-
|
|
32
|
+
end
|
|
33
|
+
if ts == "full" then
|
|
28
34
|
Channel.enableTimestamps()
|
|
29
35
|
return Channel.TS_FULL, 9
|
|
30
36
|
end
|
|
31
37
|
return Channel.TS_NONE, 1
|
|
32
38
|
end
|
|
33
39
|
|
|
34
|
-
-- Public
|
|
40
|
+
-- Public types -----------------------------------------------------------
|
|
41
|
+
|
|
42
|
+
export type PacketHandle<T> = {
|
|
43
|
+
send: (self: PacketHandle<T>, data: T, target: any?) -> (),
|
|
44
|
+
on: (
|
|
45
|
+
self: PacketHandle<T>,
|
|
46
|
+
fn: (data: T, sender: Player?, timestamp: number?) -> ()
|
|
47
|
+
) -> Types.Connection,
|
|
48
|
+
once: (
|
|
49
|
+
self: PacketHandle<T>,
|
|
50
|
+
fn: (data: T, sender: Player?, timestamp: number?) -> ()
|
|
51
|
+
) -> Types.Connection,
|
|
52
|
+
wait: (self: PacketHandle<T>) -> (T, Player?, number?),
|
|
53
|
+
name: (self: PacketHandle<T>) -> string,
|
|
54
|
+
stats: (self: PacketHandle<T>) -> Types.PacketStats,
|
|
55
|
+
}
|
|
35
56
|
|
|
36
|
-
|
|
57
|
+
-- Public -----------------------------------------------------------------
|
|
37
58
|
|
|
38
|
-
|
|
39
|
-
send: (self: PacketHandle, data: any, target: any?) -> (),
|
|
40
|
-
on: (self: PacketHandle, fn: (...any) -> ()) -> Types.Connection,
|
|
41
|
-
once: (self: PacketHandle, fn: (...any) -> ()) -> Types.Connection,
|
|
42
|
-
wait: (self: PacketHandle) -> ...any,
|
|
43
|
-
name: (self: PacketHandle) -> string,
|
|
44
|
-
stats: (self: PacketHandle) -> Types.PacketStats,
|
|
45
|
-
}
|
|
59
|
+
local Packet = {}
|
|
46
60
|
|
|
47
|
-
function Packet.define(
|
|
61
|
+
function Packet.define<T>(
|
|
48
62
|
name: string,
|
|
49
|
-
codec: Types.InternalCodec<
|
|
63
|
+
codec: Types.InternalCodec<T>,
|
|
50
64
|
options: Types.PacketOptions?
|
|
51
|
-
): PacketHandle
|
|
52
|
-
local opts = options or {} :: Types.PacketOptions
|
|
65
|
+
): PacketHandle<T>
|
|
66
|
+
local opts = options or ({} :: Types.PacketOptions)
|
|
53
67
|
local isUnreliable = opts.unreliable or false
|
|
54
68
|
|
|
55
|
-
if isUnreliable and
|
|
69
|
+
if isUnreliable and codec._isDelta then
|
|
56
70
|
error(`[Lync] Lync.packet: "{name}" cannot use delta codecs with unreliable transport`)
|
|
57
71
|
end
|
|
58
72
|
|
|
59
|
-
if
|
|
73
|
+
if codec._hasUnknown and not opts.validate then
|
|
60
74
|
warn(
|
|
61
|
-
`[Lync] Lync.packet: "{name}" uses unknown codec without validate
|
|
75
|
+
`[Lync] Lync.packet: "{name}" uses unknown codec without validate; data bypasses schema validation`
|
|
62
76
|
)
|
|
63
77
|
end
|
|
64
78
|
|
|
65
|
-
if
|
|
79
|
+
if codec._isDelta then
|
|
66
80
|
Baseline.markHasDelta()
|
|
67
81
|
end
|
|
68
82
|
|
|
69
83
|
local tsMode, headerSize = resolveTimestampMode(opts.timestamp)
|
|
70
|
-
local needsGate = IS_SERVER
|
|
71
|
-
|
|
72
84
|
local openFn = Channel.resolveOpenFn(tsMode, name)
|
|
73
85
|
|
|
74
|
-
local reg = Registry.register(
|
|
75
|
-
name,
|
|
76
|
-
Registry.KIND_PACKET,
|
|
77
|
-
codec,
|
|
78
|
-
isUnreliable,
|
|
79
|
-
nil,
|
|
80
|
-
needsGate,
|
|
81
|
-
headerSize,
|
|
82
|
-
tsMode,
|
|
83
|
-
openFn,
|
|
84
|
-
opts.rateLimit,
|
|
85
|
-
opts.validate,
|
|
86
|
-
opts.maxPayloadBytes
|
|
87
|
-
)
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
86
|
+
local reg = Registry.register({
|
|
87
|
+
name = name,
|
|
88
|
+
kind = Registry.KIND_PACKET,
|
|
89
|
+
codec = codec,
|
|
90
|
+
isUnreliable = isUnreliable,
|
|
91
|
+
partner = nil,
|
|
92
|
+
needsGate = IS_SERVER,
|
|
93
|
+
headerSize = headerSize,
|
|
94
|
+
timestampMode = tsMode,
|
|
95
|
+
openFn = openFn,
|
|
96
|
+
rateLimit = opts.rateLimit,
|
|
97
|
+
validate = opts.validate,
|
|
98
|
+
maxPayloadBytes = opts.maxPayloadBytes,
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
local function sendToPlayer(player: Player, data: any): ()
|
|
102
|
+
local ch = Transport.server().getChannel(player, isUnreliable)
|
|
103
|
+
Channel.writeBatch(ch, reg, data)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
local function bumpFires(): ()
|
|
107
|
+
if Channel.statsEnabled() then
|
|
108
|
+
reg.fires += 1
|
|
96
109
|
end
|
|
97
|
-
return _server
|
|
98
110
|
end
|
|
99
111
|
|
|
100
|
-
local function
|
|
101
|
-
if not
|
|
102
|
-
|
|
112
|
+
local function applySend(data: any, player: Player?): any?
|
|
113
|
+
if not Middleware.hasSendHooks() then
|
|
114
|
+
return data
|
|
103
115
|
end
|
|
104
|
-
|
|
116
|
+
|
|
117
|
+
local sendData = Middleware.runSend(data, name, player)
|
|
118
|
+
if typeof(sendData) == "table" and sendData._lyncDrop then
|
|
119
|
+
return nil
|
|
120
|
+
end
|
|
121
|
+
return sendData
|
|
105
122
|
end
|
|
106
123
|
|
|
107
|
-
local
|
|
124
|
+
local function sendFromServer(data: any, target: any): ()
|
|
125
|
+
if target == nil then
|
|
126
|
+
error(`[Lync] Packet.send: "{name}" server send requires a target`)
|
|
127
|
+
end
|
|
108
128
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
if typeof(data) == "table" and (data :: any)._lyncDrop then
|
|
129
|
+
if isPlayer(target) then
|
|
130
|
+
local sendData = applySend(data, target :: Player)
|
|
131
|
+
if sendData == nil then
|
|
113
132
|
return
|
|
114
133
|
end
|
|
134
|
+
sendToPlayer(target :: Player, sendData)
|
|
135
|
+
bumpFires()
|
|
136
|
+
return
|
|
115
137
|
end
|
|
116
138
|
|
|
117
|
-
if
|
|
118
|
-
|
|
119
|
-
|
|
139
|
+
if typeof(target) == "table" then
|
|
140
|
+
local sendData = applySend(data, nil)
|
|
141
|
+
if sendData == nil then
|
|
142
|
+
return
|
|
120
143
|
end
|
|
121
144
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
local ch = Server.getChannel(target :: Player, isUnreliable)
|
|
126
|
-
Channel.writeBatch(ch, reg, data)
|
|
127
|
-
if Channel.statsEnabled() then
|
|
128
|
-
reg.fires += 1
|
|
145
|
+
if target._lyncAll then
|
|
146
|
+
for _, player in Players:GetPlayers() do
|
|
147
|
+
sendToPlayer(player, sendData)
|
|
129
148
|
end
|
|
149
|
+
bumpFires()
|
|
130
150
|
return
|
|
131
151
|
end
|
|
132
152
|
|
|
133
|
-
if
|
|
134
|
-
local
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
local ch = Server.getChannel(player, isUnreliable)
|
|
139
|
-
Channel.writeBatch(ch, reg, data)
|
|
140
|
-
end
|
|
141
|
-
if Channel.statsEnabled() then
|
|
142
|
-
reg.fires += 1
|
|
153
|
+
if target._lyncExcept then
|
|
154
|
+
local excluded = target._excluded :: { [Player]: boolean }
|
|
155
|
+
for _, player in Players:GetPlayers() do
|
|
156
|
+
if not excluded[player] then
|
|
157
|
+
sendToPlayer(player, sendData)
|
|
143
158
|
end
|
|
144
|
-
return
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
if tbl._lyncExcept then
|
|
148
|
-
local excluded = tbl._excluded :: { [Player]: boolean }
|
|
149
|
-
for _, player in Players:GetPlayers() do
|
|
150
|
-
if not excluded[player] then
|
|
151
|
-
local ch = Server.getChannel(player, isUnreliable)
|
|
152
|
-
Channel.writeBatch(ch, reg, data)
|
|
153
|
-
end
|
|
154
|
-
end
|
|
155
|
-
if Channel.statsEnabled() then
|
|
156
|
-
reg.fires += 1
|
|
157
|
-
end
|
|
158
|
-
return
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
if tbl._lyncGroup then
|
|
162
|
-
local members = tbl._members :: { [Player]: boolean }
|
|
163
|
-
for player in members do
|
|
164
|
-
local ch = Server.getChannel(player, isUnreliable)
|
|
165
|
-
Channel.writeBatch(ch, reg, data)
|
|
166
|
-
end
|
|
167
|
-
if Channel.statsEnabled() then
|
|
168
|
-
reg.fires += 1
|
|
169
|
-
end
|
|
170
|
-
return
|
|
171
159
|
end
|
|
160
|
+
bumpFires()
|
|
161
|
+
return
|
|
162
|
+
end
|
|
172
163
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
Channel.writeBatch(ch, reg, data)
|
|
177
|
-
end
|
|
178
|
-
end
|
|
179
|
-
if Channel.statsEnabled() then
|
|
180
|
-
reg.fires += 1
|
|
164
|
+
if target._lyncGroup then
|
|
165
|
+
for player in target._members :: { [Player]: boolean } do
|
|
166
|
+
sendToPlayer(player, sendData)
|
|
181
167
|
end
|
|
168
|
+
bumpFires()
|
|
182
169
|
return
|
|
183
170
|
end
|
|
184
171
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
)
|
|
190
|
-
else
|
|
191
|
-
local Client = getClient()
|
|
192
|
-
local ch = Client.getChannel(isUnreliable)
|
|
193
|
-
Channel.writeBatch(ch, reg, data)
|
|
194
|
-
if Channel.statsEnabled() then
|
|
195
|
-
reg.fires += 1
|
|
172
|
+
for _, player in target do
|
|
173
|
+
if isPlayer(player) then
|
|
174
|
+
sendToPlayer(player :: Player, sendData)
|
|
175
|
+
end
|
|
196
176
|
end
|
|
177
|
+
bumpFires()
|
|
178
|
+
return
|
|
197
179
|
end
|
|
198
|
-
end
|
|
199
|
-
|
|
200
|
-
function handle.on(_self: PacketHandle, fn: (...any) -> ()): Types.Connection
|
|
201
|
-
return reg.signal:connect(fn)
|
|
202
|
-
end
|
|
203
|
-
|
|
204
|
-
function handle.once(_self: PacketHandle, fn: (...any) -> ()): Types.Connection
|
|
205
|
-
local conn: Types.Connection
|
|
206
|
-
conn = reg.signal:connect(function(...: any)
|
|
207
|
-
conn:disconnect()
|
|
208
|
-
fn(...)
|
|
209
|
-
end)
|
|
210
|
-
return conn
|
|
211
|
-
end
|
|
212
180
|
|
|
213
|
-
|
|
214
|
-
|
|
181
|
+
error(
|
|
182
|
+
`[Lync] Packet.send: "{name}" expected Player, table, Group, or Lync.all as target, got {typeof(
|
|
183
|
+
target
|
|
184
|
+
)}`
|
|
185
|
+
)
|
|
215
186
|
end
|
|
216
187
|
|
|
217
|
-
function
|
|
218
|
-
|
|
188
|
+
local function sendFromClient(data: any): ()
|
|
189
|
+
local sendData = applySend(data, nil)
|
|
190
|
+
if sendData == nil then
|
|
191
|
+
return
|
|
192
|
+
end
|
|
193
|
+
local ch = Transport.client().getChannel(isUnreliable)
|
|
194
|
+
Channel.writeBatch(ch, reg, sendData)
|
|
195
|
+
bumpFires()
|
|
219
196
|
end
|
|
220
197
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
bytesSent = reg.bytesSent,
|
|
224
|
-
bytesReceived = reg.bytesReceived,
|
|
225
|
-
fires = reg.fires,
|
|
226
|
-
recvFires = reg.recvFires,
|
|
227
|
-
drops = reg.drops,
|
|
228
|
-
}
|
|
229
|
-
end
|
|
198
|
+
type Self = PacketHandle<T>
|
|
199
|
+
type Listener = (data: T, sender: Player?, timestamp: number?) -> ()
|
|
230
200
|
|
|
231
|
-
|
|
201
|
+
local handle = {
|
|
202
|
+
send = function(_self: Self, data: T, target: any?): ()
|
|
203
|
+
if IS_SERVER then
|
|
204
|
+
sendFromServer(data, target)
|
|
205
|
+
else
|
|
206
|
+
sendFromClient(data)
|
|
207
|
+
end
|
|
208
|
+
end,
|
|
209
|
+
|
|
210
|
+
on = function(_self: Self, fn: Listener): Types.Connection
|
|
211
|
+
return reg.signal:connect(fn :: any)
|
|
212
|
+
end,
|
|
213
|
+
|
|
214
|
+
once = function(_self: Self, fn: Listener): Types.Connection
|
|
215
|
+
local conn: Types.Connection
|
|
216
|
+
conn = reg.signal:connect(function(...: any)
|
|
217
|
+
conn:disconnect()
|
|
218
|
+
fn(...)
|
|
219
|
+
end)
|
|
220
|
+
return conn
|
|
221
|
+
end,
|
|
222
|
+
|
|
223
|
+
wait = function(_self: Self): (T, Player?, number?)
|
|
224
|
+
return reg.signal:wait()
|
|
225
|
+
end,
|
|
226
|
+
|
|
227
|
+
name = function(_self: Self): string
|
|
228
|
+
return reg.name
|
|
229
|
+
end,
|
|
230
|
+
|
|
231
|
+
stats = function(_self: Self): Types.PacketStats
|
|
232
|
+
return {
|
|
233
|
+
bytesSent = reg.bytesSent,
|
|
234
|
+
bytesReceived = reg.bytesReceived,
|
|
235
|
+
fires = reg.fires,
|
|
236
|
+
recvFires = reg.recvFires,
|
|
237
|
+
drops = reg.drops,
|
|
238
|
+
}
|
|
239
|
+
end,
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return table.freeze(handle) :: PacketHandle<T>
|
|
232
243
|
end
|
|
233
244
|
|
|
234
245
|
return table.freeze(Packet)
|