@axpecter/lync 1.5.1 → 2.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.
- package/README.md +105 -12
- package/package.json +2 -2
- package/src/Types.luau +10 -0
- package/src/api/Namespace.luau +8 -3
- package/src/api/Packet.luau +76 -43
- package/src/api/Query.luau +35 -14
- package/src/api/Signal.luau +4 -0
- package/src/codec/composite/Array.luau +85 -6
- package/src/codec/composite/Map.luau +7 -1
- package/src/codec/composite/Optional.luau +1 -0
- package/src/codec/composite/Struct.luau +23 -1
- package/src/codec/composite/Tagged.luau +11 -0
- package/src/codec/composite/Tuple.luau +10 -0
- package/src/codec/datatype/Instance.luau +3 -0
- package/src/codec/meta/Unknown.luau +1 -0
- package/src/index.d.ts +36 -7
- package/src/init.luau +49 -2
- package/src/internal/Channel.luau +172 -42
- package/src/internal/Registry.luau +20 -3
- package/src/transport/Client.luau +65 -11
- package/src/transport/Gate.luau +9 -0
- package/src/transport/Reader.luau +75 -24
- package/src/transport/Server.luau +273 -68
|
@@ -38,6 +38,7 @@ function Array.deltaArray(element: Codec<any>, maxCount: number?): Codec<{ any }
|
|
|
38
38
|
|
|
39
39
|
return table.freeze({
|
|
40
40
|
_isDelta = true,
|
|
41
|
+
_hasUnknown = (element :: any)._hasUnknown or nil,
|
|
41
42
|
|
|
42
43
|
write = function(ch: ChannelState, value: { any }): ()
|
|
43
44
|
local len = #value
|
|
@@ -110,12 +111,14 @@ function Array.deltaArray(element: Codec<any>, maxCount: number?): Codec<{ any }
|
|
|
110
111
|
ch.cursor += 1
|
|
111
112
|
Varint.write(ch, dirtyN)
|
|
112
113
|
|
|
114
|
+
local prevIdx = 0
|
|
113
115
|
for j = 1, dirtyN do
|
|
114
116
|
local i = dirty[j]
|
|
115
117
|
local newOff = bounds[i]
|
|
116
118
|
local newLen = bounds[i + 1] - newOff
|
|
117
119
|
|
|
118
|
-
Varint.write(ch, i - 1)
|
|
120
|
+
Varint.write(ch, (i - 1) - prevIdx)
|
|
121
|
+
prevIdx = i - 1
|
|
119
122
|
alloc(ch, newLen)
|
|
120
123
|
buffer.copy(ch.buff, ch.cursor, scratch.buff, newOff, newLen)
|
|
121
124
|
ch.cursor += newLen
|
|
@@ -167,21 +170,26 @@ function Array.deltaArray(element: Codec<any>, maxCount: number?): Codec<{ any }
|
|
|
167
170
|
end
|
|
168
171
|
|
|
169
172
|
local cache = Baseline.getCache(deltaId) :: { any }?
|
|
170
|
-
|
|
173
|
+
if not cache then
|
|
174
|
+
error("[Lync] Delta frame without baseline")
|
|
175
|
+
end
|
|
176
|
+
local result = table.clone(cache)
|
|
171
177
|
|
|
172
178
|
local dirtyN, dnBytes = Varint.read(src, absPos)
|
|
173
179
|
absPos += dnBytes
|
|
174
180
|
|
|
181
|
+
local runningIdx = 0
|
|
175
182
|
for _ = 1, dirtyN do
|
|
176
|
-
local
|
|
177
|
-
absPos +=
|
|
183
|
+
local delta, deltaBytes = Varint.read(src, absPos)
|
|
184
|
+
absPos += deltaBytes
|
|
185
|
+
runningIdx += delta
|
|
178
186
|
|
|
179
187
|
if elemRead and elemSize then
|
|
180
|
-
result[
|
|
188
|
+
result[runningIdx + 1] = elemRead(src, absPos)
|
|
181
189
|
absPos += elemSize
|
|
182
190
|
else
|
|
183
191
|
local val, n = readElement(src, absPos, refs)
|
|
184
|
-
result[
|
|
192
|
+
result[runningIdx + 1] = val
|
|
185
193
|
absPos += n
|
|
186
194
|
end
|
|
187
195
|
end
|
|
@@ -198,8 +206,78 @@ function Array.array(element: Codec<any>, maxCount: number?): Codec<{ any }>
|
|
|
198
206
|
local directWrite = internal._directWrite
|
|
199
207
|
local directRead = internal._directRead
|
|
200
208
|
|
|
209
|
+
local band = bit32.band
|
|
210
|
+
local bor = bit32.bor
|
|
211
|
+
local lshift = bit32.lshift
|
|
212
|
+
local rshift = bit32.rshift
|
|
213
|
+
local ceil = math.ceil
|
|
214
|
+
|
|
215
|
+
-- Bitpacked bool array: 8 bools per byte
|
|
216
|
+
if internal._isBool then
|
|
217
|
+
return table.freeze({
|
|
218
|
+
_hasUnknown = nil,
|
|
219
|
+
write = function(ch: ChannelState, value: { any }): ()
|
|
220
|
+
local len = #value
|
|
221
|
+
Varint.write(ch, len)
|
|
222
|
+
if len == 0 then
|
|
223
|
+
return
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
local byteCount = ceil(len / 8)
|
|
227
|
+
local c = ch.cursor
|
|
228
|
+
if c + byteCount > ch.size then
|
|
229
|
+
alloc(ch, byteCount)
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
local b = ch.buff
|
|
233
|
+
local byteIdx = 0
|
|
234
|
+
local acc = 0
|
|
235
|
+
for i = 1, len do
|
|
236
|
+
local bit = (i - 1) % 8
|
|
237
|
+
if value[i] then
|
|
238
|
+
acc = bor(acc, lshift(1, bit))
|
|
239
|
+
end
|
|
240
|
+
if bit == 7 then
|
|
241
|
+
buffer.writeu8(b, c + byteIdx, acc)
|
|
242
|
+
byteIdx += 1
|
|
243
|
+
acc = 0
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
-- Flush remaining bits
|
|
247
|
+
if len % 8 ~= 0 then
|
|
248
|
+
buffer.writeu8(b, c + byteIdx, acc)
|
|
249
|
+
end
|
|
250
|
+
ch.cursor = c + byteCount
|
|
251
|
+
end,
|
|
252
|
+
read = function(src: buffer, pos: number, _refs: { Instance }?): ({ boolean }, number)
|
|
253
|
+
local len, lenBytes = Varint.read(src, pos)
|
|
254
|
+
|
|
255
|
+
if maxCount and len > maxCount then
|
|
256
|
+
error(`[Lync] Array count {len} exceeds max {maxCount}`)
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
local result = table.create(len)
|
|
260
|
+
if len == 0 then
|
|
261
|
+
return result, lenBytes
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
local byteCount = ceil(len / 8)
|
|
265
|
+
local c = pos + lenBytes
|
|
266
|
+
for i = 1, len do
|
|
267
|
+
local byteIdx = rshift(i - 1, 3)
|
|
268
|
+
local bit = (i - 1) % 8
|
|
269
|
+
local byte = buffer.readu8(src, c + byteIdx)
|
|
270
|
+
result[i] = band(byte, lshift(1, bit)) ~= 0
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
return result, lenBytes + byteCount
|
|
274
|
+
end,
|
|
275
|
+
})
|
|
276
|
+
end
|
|
277
|
+
|
|
201
278
|
if elementSize and directWrite and directRead then
|
|
202
279
|
return table.freeze({
|
|
280
|
+
_hasUnknown = (element :: any)._hasUnknown or nil,
|
|
203
281
|
write = function(ch: ChannelState, value: { any }): ()
|
|
204
282
|
local len = #value
|
|
205
283
|
Varint.write(ch, len)
|
|
@@ -244,6 +322,7 @@ function Array.array(element: Codec<any>, maxCount: number?): Codec<{ any }>
|
|
|
244
322
|
local readElement = element.read
|
|
245
323
|
|
|
246
324
|
return table.freeze({
|
|
325
|
+
_hasUnknown = (element :: any)._hasUnknown or nil,
|
|
247
326
|
write = function(ch: ChannelState, value: { any }): ()
|
|
248
327
|
local len = #value
|
|
249
328
|
Varint.write(ch, len)
|
|
@@ -44,6 +44,7 @@ function Map.map(
|
|
|
44
44
|
local entrySize = keySize + valSize
|
|
45
45
|
|
|
46
46
|
return table.freeze({
|
|
47
|
+
_hasUnknown = (keyCodec :: any)._hasUnknown or (valueCodec :: any)._hasUnknown or nil,
|
|
47
48
|
write = function(ch: ChannelState, value: { [any]: any }): ()
|
|
48
49
|
local count = 0
|
|
49
50
|
for _ in value do
|
|
@@ -100,6 +101,7 @@ function Map.map(
|
|
|
100
101
|
local readVal = valueCodec.read
|
|
101
102
|
|
|
102
103
|
return table.freeze({
|
|
104
|
+
_hasUnknown = (keyCodec :: any)._hasUnknown or (valueCodec :: any)._hasUnknown or nil,
|
|
103
105
|
write = function(ch: ChannelState, value: { [any]: any }): ()
|
|
104
106
|
local count = 0
|
|
105
107
|
for _ in value do
|
|
@@ -185,6 +187,7 @@ function Map.deltaMap(
|
|
|
185
187
|
|
|
186
188
|
return table.freeze({
|
|
187
189
|
_isDelta = true,
|
|
190
|
+
_hasUnknown = (keyCodec :: any)._hasUnknown or (valueCodec :: any)._hasUnknown or nil,
|
|
188
191
|
|
|
189
192
|
write = function(ch: ChannelState, value: { [any]: any }): ()
|
|
190
193
|
local scratch = acquireScratch()
|
|
@@ -378,7 +381,10 @@ function Map.deltaMap(
|
|
|
378
381
|
end
|
|
379
382
|
|
|
380
383
|
local cache = Baseline.getCache(deltaId) :: { [any]: any }?
|
|
381
|
-
|
|
384
|
+
if not cache then
|
|
385
|
+
error("[Lync] Delta frame without baseline")
|
|
386
|
+
end
|
|
387
|
+
local result = table.clone(cache)
|
|
382
388
|
|
|
383
389
|
local upsertN, unBytes = Varint.read(src, absPos)
|
|
384
390
|
absPos += unBytes
|
|
@@ -19,6 +19,7 @@ function Optional.optional(inner: Codec<any>): Codec<any>
|
|
|
19
19
|
local innerRead = inner.read
|
|
20
20
|
|
|
21
21
|
return table.freeze({
|
|
22
|
+
_hasUnknown = (inner :: any)._hasUnknown or nil,
|
|
22
23
|
write = function(ch: ChannelState, value: any): ()
|
|
23
24
|
local c = ch.cursor
|
|
24
25
|
if c + 1 > ch.size then
|
|
@@ -47,6 +47,14 @@ function Struct.struct(schema: { [string]: Codec<any> }): Codec<any>
|
|
|
47
47
|
local boolByteCount = ceil(boolCount / 8)
|
|
48
48
|
local hasBools = boolCount > 0
|
|
49
49
|
|
|
50
|
+
local hasUnknown = false
|
|
51
|
+
for _, fieldCodec in schema do
|
|
52
|
+
if (fieldCodec :: any)._hasUnknown then
|
|
53
|
+
hasUnknown = true
|
|
54
|
+
break
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
50
58
|
local canDirect = true
|
|
51
59
|
local fixedSize = boolByteCount
|
|
52
60
|
local isAllFixed = true
|
|
@@ -126,6 +134,7 @@ function Struct.struct(schema: { [string]: Codec<any> }): Codec<any>
|
|
|
126
134
|
_size = fixedSize,
|
|
127
135
|
_directWrite = directWriteBody,
|
|
128
136
|
_directRead = directReadBody,
|
|
137
|
+
_hasUnknown = hasUnknown or nil,
|
|
129
138
|
|
|
130
139
|
write = function(ch: ChannelState, value: any): ()
|
|
131
140
|
local c = ch.cursor
|
|
@@ -152,6 +161,7 @@ function Struct.struct(schema: { [string]: Codec<any> }): Codec<any>
|
|
|
152
161
|
|
|
153
162
|
return table.freeze({
|
|
154
163
|
_size = if isAllFixed then fixedSize else nil,
|
|
164
|
+
_hasUnknown = hasUnknown or nil,
|
|
155
165
|
|
|
156
166
|
write = function(ch: ChannelState, value: any): ()
|
|
157
167
|
if isAllFixed then
|
|
@@ -195,6 +205,14 @@ function Struct.deltaStruct(schema: { [string]: Codec<any> }): Codec<any>
|
|
|
195
205
|
local bitmaskBytes = ceil(segCount / 8)
|
|
196
206
|
local deltaId = Shared.allocDeltaId()
|
|
197
207
|
|
|
208
|
+
local hasUnknown = false
|
|
209
|
+
for _, fieldCodec in schema do
|
|
210
|
+
if (fieldCodec :: any)._hasUnknown then
|
|
211
|
+
hasUnknown = true
|
|
212
|
+
break
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
|
|
198
216
|
-- Scratch bounds reused every frame(only cloned into cache)
|
|
199
217
|
local _scratchBounds = table.create(segCount + 1) :: { number }
|
|
200
218
|
_scratchBounds[1] = 0
|
|
@@ -237,6 +255,7 @@ function Struct.deltaStruct(schema: { [string]: Codec<any> }): Codec<any>
|
|
|
237
255
|
|
|
238
256
|
return table.freeze({
|
|
239
257
|
_isDelta = true,
|
|
258
|
+
_hasUnknown = hasUnknown or nil,
|
|
240
259
|
|
|
241
260
|
write = function(ch: ChannelState, value: any): ()
|
|
242
261
|
local cache = ch.deltas[deltaId] :: DeltaCache?
|
|
@@ -413,7 +432,10 @@ function Struct.deltaStruct(schema: { [string]: Codec<any> }): Codec<any>
|
|
|
413
432
|
end
|
|
414
433
|
|
|
415
434
|
local cache = Baseline.getCache(deltaId) :: any
|
|
416
|
-
|
|
435
|
+
if not cache then
|
|
436
|
+
error("[Lync] Delta frame without baseline")
|
|
437
|
+
end
|
|
438
|
+
local result = table.clone(cache)
|
|
417
439
|
|
|
418
440
|
local maskStart = absPos
|
|
419
441
|
absPos += bitmaskBytes
|
|
@@ -71,6 +71,14 @@ function Tagged.define(tagField: string, variants: { [string]: Codec<any> }): Co
|
|
|
71
71
|
end
|
|
72
72
|
end
|
|
73
73
|
|
|
74
|
+
local hasUnknown = false
|
|
75
|
+
for i = 1, count do
|
|
76
|
+
if (tagCodecs[i] :: any)._hasUnknown then
|
|
77
|
+
hasUnknown = true
|
|
78
|
+
break
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
74
82
|
table.freeze(nameToTag)
|
|
75
83
|
table.freeze(tagCodecs)
|
|
76
84
|
table.freeze(tagNames)
|
|
@@ -86,6 +94,7 @@ function Tagged.define(tagField: string, variants: { [string]: Codec<any> }): Co
|
|
|
86
94
|
if fixedSize then
|
|
87
95
|
return table.freeze({
|
|
88
96
|
_size = fixedSize,
|
|
97
|
+
_hasUnknown = hasUnknown or nil,
|
|
89
98
|
_directWrite = function(b: buffer, offset: number, value: any): ()
|
|
90
99
|
local tag = nameToTag[value[tagField]]
|
|
91
100
|
if not tag then
|
|
@@ -141,6 +150,7 @@ function Tagged.define(tagField: string, variants: { [string]: Codec<any> }): Co
|
|
|
141
150
|
|
|
142
151
|
return table.freeze({
|
|
143
152
|
_size = nil,
|
|
153
|
+
_hasUnknown = hasUnknown or nil,
|
|
144
154
|
write = function(ch: ChannelState, value: any): ()
|
|
145
155
|
local tag = nameToTag[value[tagField]]
|
|
146
156
|
if not tag then
|
|
@@ -183,6 +193,7 @@ function Tagged.define(tagField: string, variants: { [string]: Codec<any> }): Co
|
|
|
183
193
|
|
|
184
194
|
return table.freeze({
|
|
185
195
|
_size = fixedSize,
|
|
196
|
+
_hasUnknown = hasUnknown or nil,
|
|
186
197
|
write = function(ch: ChannelState, value: any): ()
|
|
187
198
|
local tag = nameToTag[value[tagField]]
|
|
188
199
|
if not tag then
|
|
@@ -24,6 +24,14 @@ function Tuple.define(...: Codec<any>): Codec<{ any }>
|
|
|
24
24
|
|
|
25
25
|
table.freeze(codecs)
|
|
26
26
|
|
|
27
|
+
local hasUnknown = false
|
|
28
|
+
for i = 1, count do
|
|
29
|
+
if (codecs[i] :: any)._hasUnknown then
|
|
30
|
+
hasUnknown = true
|
|
31
|
+
break
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
27
35
|
local canDirect = true
|
|
28
36
|
local totalSize: number = 0
|
|
29
37
|
local directWrites = table.create(count) :: { any }
|
|
@@ -92,6 +100,7 @@ function Tuple.define(...: Codec<any>): Codec<{ any }>
|
|
|
92
100
|
_size = totalSize,
|
|
93
101
|
_directWrite = directWriteBody,
|
|
94
102
|
_directRead = directReadBody,
|
|
103
|
+
_hasUnknown = hasUnknown or nil,
|
|
95
104
|
write = function(ch: ChannelState, value: { any }): ()
|
|
96
105
|
local c = ch.cursor
|
|
97
106
|
if c + totalSize > ch.size then
|
|
@@ -119,6 +128,7 @@ function Tuple.define(...: Codec<any>): Codec<{ any }>
|
|
|
119
128
|
|
|
120
129
|
return table.freeze({
|
|
121
130
|
_size = totalSize,
|
|
131
|
+
_hasUnknown = hasUnknown or nil,
|
|
122
132
|
write = function(ch: ChannelState, value: { any }): ()
|
|
123
133
|
if hasFixedTotal then
|
|
124
134
|
alloc(ch, totalSize :: number)
|
package/src/index.d.ts
CHANGED
|
@@ -100,9 +100,9 @@ export type Target = Player | AllTarget | ExceptTarget | GroupObject | Player[];
|
|
|
100
100
|
|
|
101
101
|
export interface Scope {
|
|
102
102
|
add(this: Scope, conn: Connection | RBXScriptConnection): void;
|
|
103
|
-
listen<T>(this: Scope, source: Packet<T>, callback: (data: T, sender: Player | undefined) => void): void;
|
|
104
|
-
once<T>(this: Scope, source: Packet<T>, callback: (data: T, sender: Player | undefined) => void): void;
|
|
105
|
-
listenAll(this: Scope, namespace: Namespace, callback: (name: string, data: unknown, sender: Player | undefined) => void): void;
|
|
103
|
+
listen<T>(this: Scope, source: Packet<T>, callback: (data: T, sender: Player | undefined, timestamp: number | undefined) => void): void;
|
|
104
|
+
once<T>(this: Scope, source: Packet<T>, callback: (data: T, sender: Player | undefined, timestamp: number | undefined) => void): void;
|
|
105
|
+
listenAll(this: Scope, namespace: Namespace, callback: (name: string, data: unknown, sender: Player | undefined, timestamp: number | undefined) => void): void;
|
|
106
106
|
destroy(this: Scope): void;
|
|
107
107
|
}
|
|
108
108
|
|
|
@@ -120,14 +120,26 @@ export interface PacketConfig<T> {
|
|
|
120
120
|
rateLimit?: RateLimitConfig;
|
|
121
121
|
validate?: (data: T, player: Player) => LuaTuple<[boolean, string?]>;
|
|
122
122
|
maxPayloadBytes?: number;
|
|
123
|
+
timestamp?: "frame" | "offset" | "full";
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export interface PlayerStats {
|
|
127
|
+
bytesSent: number;
|
|
128
|
+
bytesReceived: number;
|
|
123
129
|
}
|
|
124
130
|
|
|
125
131
|
export interface Packet<T> {
|
|
126
132
|
send(this: Packet<T>, data: T, target?: Target): void;
|
|
127
|
-
listen(this: Packet<T>, callback: (data: T, sender: Player | undefined) => void): Connection;
|
|
128
|
-
once(this: Packet<T>, callback: (data: T, sender: Player | undefined) => void): Connection;
|
|
133
|
+
listen(this: Packet<T>, callback: (data: T, sender: Player | undefined, timestamp: number | undefined) => void): Connection;
|
|
134
|
+
once(this: Packet<T>, callback: (data: T, sender: Player | undefined, timestamp: number | undefined) => void): Connection;
|
|
129
135
|
wait(this: Packet<T>): LuaTuple<[T, Player | undefined]>;
|
|
130
136
|
disconnectAll(this: Packet<T>): void;
|
|
137
|
+
|
|
138
|
+
getBytesSent(this: Packet<T>): number;
|
|
139
|
+
getBytesReceived(this: Packet<T>): number;
|
|
140
|
+
getFires(this: Packet<T>): number;
|
|
141
|
+
getRecvFires(this: Packet<T>): number;
|
|
142
|
+
getDrops(this: Packet<T>): number;
|
|
131
143
|
}
|
|
132
144
|
|
|
133
145
|
// -- Query -------------------------------------------------------------
|
|
@@ -182,7 +194,7 @@ export interface Namespace {
|
|
|
182
194
|
readonly queries: Record<string, Query<unknown, unknown>>;
|
|
183
195
|
listenAll(
|
|
184
196
|
this: Namespace,
|
|
185
|
-
callback: (name: string, data: unknown, sender: Player | undefined) => void,
|
|
197
|
+
callback: (name: string, data: unknown, sender: Player | undefined, timestamp: number | undefined) => void,
|
|
186
198
|
): Connection;
|
|
187
199
|
onSend(
|
|
188
200
|
this: Namespace,
|
|
@@ -306,13 +318,30 @@ declare namespace Lync {
|
|
|
306
318
|
// Scope
|
|
307
319
|
export function scope(): Scope;
|
|
308
320
|
|
|
309
|
-
// Configuration
|
|
321
|
+
// Configuration (call before start)
|
|
310
322
|
export function setChannelMaxSize(bytes: number): void;
|
|
311
323
|
export function setValidationDepth(depth: number): void;
|
|
312
324
|
export function setPoolSize(count: number): void;
|
|
313
325
|
|
|
326
|
+
// Runtime configuration
|
|
327
|
+
export function flush(): void;
|
|
328
|
+
export function setFlushRate(hz: number): void;
|
|
329
|
+
|
|
330
|
+
// Stats (default off; call enableStats() to activate)
|
|
331
|
+
export function enableStats(): void;
|
|
332
|
+
export function getPlayerStats(player: Player): PlayerStats | undefined;
|
|
333
|
+
export function resetStats(): void;
|
|
334
|
+
|
|
335
|
+
// Security (server-only)
|
|
336
|
+
export function setBandwidthLimit(softLimit: number, maxStrikes: number): void;
|
|
337
|
+
|
|
314
338
|
// Introspection
|
|
315
339
|
export function queryPendingCount(): number;
|
|
340
|
+
|
|
341
|
+
// Packet capture (server-only, debug)
|
|
342
|
+
export function startCapture(label?: string): void;
|
|
343
|
+
export function stopCapture(): void;
|
|
344
|
+
export function dumpCaptures(): void;
|
|
316
345
|
}
|
|
317
346
|
|
|
318
347
|
export default Lync;
|
package/src/init.luau
CHANGED
|
@@ -103,8 +103,38 @@ end
|
|
|
103
103
|
|
|
104
104
|
-- Public --------------------------------------------------------------
|
|
105
105
|
|
|
106
|
+
local IS_SERVER = RunService:IsServer()
|
|
107
|
+
|
|
108
|
+
local function flush(): ()
|
|
109
|
+
if IS_SERVER then
|
|
110
|
+
Server.flush()
|
|
111
|
+
else
|
|
112
|
+
Client.flush()
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
local function setFlushRate(hz: number): ()
|
|
117
|
+
if IS_SERVER then
|
|
118
|
+
Server.setFlushRate(hz)
|
|
119
|
+
else
|
|
120
|
+
Client.setFlushRate(hz)
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
local function getPlayerStats(player: Player): any?
|
|
125
|
+
return Server.getPlayerStats(player)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
local function resetStats(): ()
|
|
129
|
+
Server.resetStats()
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
local function setBandwidthLimit(softLimit: number, maxStrikes: number): ()
|
|
133
|
+
Server.setBandwidthLimit(softLimit, maxStrikes)
|
|
134
|
+
end
|
|
135
|
+
|
|
106
136
|
local Lync = {
|
|
107
|
-
VERSION = "
|
|
137
|
+
VERSION = "2.0.0",
|
|
108
138
|
|
|
109
139
|
-- Lifecycle
|
|
110
140
|
start = start,
|
|
@@ -187,13 +217,30 @@ local Lync = {
|
|
|
187
217
|
-- Scope
|
|
188
218
|
scope = ScopeModule.create,
|
|
189
219
|
|
|
190
|
-
-- Configuration(call before start)
|
|
220
|
+
-- Configuration (call before start)
|
|
191
221
|
setChannelMaxSize = Channel.setMaxSize,
|
|
192
222
|
setValidationDepth = Gate.setMaxDepth,
|
|
193
223
|
setPoolSize = Pool.setMaxSize,
|
|
194
224
|
|
|
225
|
+
-- Runtime configuration
|
|
226
|
+
flush = flush,
|
|
227
|
+
setFlushRate = setFlushRate,
|
|
228
|
+
|
|
229
|
+
-- Stats (default off; call enableStats() to activate)
|
|
230
|
+
enableStats = Channel.enableStats,
|
|
231
|
+
getPlayerStats = getPlayerStats,
|
|
232
|
+
resetStats = resetStats,
|
|
233
|
+
|
|
234
|
+
-- Security (server-only)
|
|
235
|
+
setBandwidthLimit = setBandwidthLimit,
|
|
236
|
+
|
|
195
237
|
-- Introspection
|
|
196
238
|
queryPendingCount = QueryModule.pendingCount,
|
|
239
|
+
|
|
240
|
+
-- Packet capture (server-only, debug)
|
|
241
|
+
startCapture = if IS_SERVER then Server.startCapture else nil,
|
|
242
|
+
stopCapture = if IS_SERVER then Server.stopCapture else nil,
|
|
243
|
+
dumpCaptures = if IS_SERVER then Server.dumpCaptures else nil,
|
|
197
244
|
}
|
|
198
245
|
|
|
199
246
|
Lync.default = Lync
|