@axpecter/lync 1.5.2 → 2.1.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 +499 -357
- package/package.json +2 -2
- package/src/Types.luau +69 -27
- package/src/api/Group.luau +101 -106
- package/src/api/Packet.luau +191 -157
- package/src/api/Query.luau +223 -282
- package/src/api/Scope.luau +46 -57
- package/src/api/Signal.luau +104 -137
- package/src/codec/Base.luau +69 -20
- package/src/codec/composite/Array.luau +189 -201
- package/src/codec/composite/Map.luau +97 -341
- package/src/codec/composite/Optional.luau +27 -23
- package/src/codec/composite/Shared.luau +96 -65
- package/src/codec/composite/Struct.luau +201 -339
- package/src/codec/composite/Tagged.luau +64 -178
- package/src/codec/composite/Tuple.luau +81 -95
- package/src/codec/datatype/Buffer.luau +49 -21
- package/src/codec/datatype/CFrame.luau +207 -30
- package/src/codec/datatype/Color.luau +21 -11
- package/src/codec/datatype/Instance.luau +29 -19
- package/src/codec/datatype/IntVector.luau +33 -21
- package/src/codec/datatype/NumberRange.luau +19 -10
- package/src/codec/datatype/Ray.luau +26 -22
- package/src/codec/datatype/Rect.luau +20 -16
- package/src/codec/datatype/Region.luau +51 -45
- package/src/codec/datatype/Sequence.luau +64 -56
- package/src/codec/datatype/String.luau +89 -56
- package/src/codec/datatype/UDim.luau +40 -22
- package/src/codec/datatype/Vector.luau +181 -17
- package/src/codec/meta/Auto.luau +295 -253
- package/src/codec/meta/Bitfield.luau +104 -148
- package/src/codec/meta/Custom.luau +8 -4
- package/src/codec/meta/Enum.luau +29 -57
- package/src/codec/meta/Float.luau +64 -0
- package/src/codec/meta/Nothing.luau +9 -5
- package/src/codec/meta/Unknown.luau +44 -35
- package/src/codec/primitive/Bool.luau +16 -26
- package/src/codec/primitive/Float16.luau +58 -64
- package/src/codec/primitive/Int.luau +68 -0
- package/src/codec/primitive/Number.luau +21 -43
- package/src/codec/primitive/Varint.luau +67 -46
- package/src/index.d.ts +249 -306
- package/src/init.luau +332 -173
- package/src/internal/Baseline.luau +29 -24
- package/src/internal/Channel.luau +346 -161
- package/src/internal/Middleware.luau +60 -85
- package/src/internal/Pool.luau +19 -30
- package/src/internal/Registry.luau +61 -101
- package/src/transport/Bridge.luau +64 -43
- package/src/transport/Client.luau +60 -117
- package/src/transport/Gate.luau +282 -133
- package/src/transport/Reader.luau +159 -100
- package/src/transport/Server.luau +147 -292
- package/src/api/Namespace.luau +0 -251
- package/src/codec/meta/Quantized.luau +0 -174
package/src/api/Query.luau
CHANGED
|
@@ -1,346 +1,287 @@
|
|
|
1
1
|
--!strict
|
|
2
2
|
--!optimize 2
|
|
3
|
-
--
|
|
3
|
+
-- Query definition: handle, request with correlation IDs and timeout.
|
|
4
4
|
|
|
5
5
|
local Players = game:GetService("Players")
|
|
6
6
|
local RunService = game:GetService("RunService")
|
|
7
7
|
|
|
8
|
-
local
|
|
8
|
+
local Baseline = require(script.Parent.Parent.internal.Baseline)
|
|
9
|
+
local Channel = require(script.Parent.Parent.internal.Channel)
|
|
9
10
|
local Registry = require(script.Parent.Parent.internal.Registry)
|
|
10
|
-
local Server = require(script.Parent.Parent.transport.Server)
|
|
11
|
-
local Signal = require(script.Parent.Signal)
|
|
12
11
|
local Types = require(script.Parent.Parent.Types)
|
|
13
12
|
|
|
14
|
-
type Connection = Types.Connection
|
|
15
|
-
type QueryConfig<R, S> = Types.QueryConfig<R, S>
|
|
16
|
-
type Registration = Types.Registration
|
|
17
|
-
|
|
18
13
|
-- Constants -----------------------------------------------------------
|
|
19
14
|
|
|
20
15
|
local IS_SERVER = RunService:IsServer()
|
|
21
|
-
|
|
22
|
-
-- Wire ceiling: correlationId is u16 in Channel.writeQuery / Reader.process.
|
|
23
|
-
local POOL_SIZE = 65536
|
|
16
|
+
local DEFAULT_TIMEOUT = 5
|
|
24
17
|
|
|
25
18
|
-- State ---------------------------------------------------------------
|
|
26
19
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
callback: ((data: any) -> ())?,
|
|
30
|
-
timeout: thread?,
|
|
31
|
-
source: Player?,
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
local _pending = {} :: { [number]: PendingQuery }
|
|
35
|
-
local _nextId = 0
|
|
36
|
-
local _activeCount = 0
|
|
37
|
-
|
|
38
|
-
-- Private -------------------------------------------------------------
|
|
20
|
+
local _nextCorrId = 0
|
|
21
|
+
local _pending: { [number]: thread } = {}
|
|
39
22
|
|
|
40
|
-
|
|
41
|
-
if _activeCount >= POOL_SIZE then
|
|
42
|
-
error("[Lync] All 65536 query correlation slots exhausted")
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
local id = _nextId
|
|
23
|
+
-- Public --------------------------------------------------------------
|
|
46
24
|
|
|
47
|
-
|
|
48
|
-
-- concurrency, this loop body almost never executes.
|
|
49
|
-
while _pending[id] do
|
|
50
|
-
id = (id + 1) % POOL_SIZE
|
|
51
|
-
end
|
|
25
|
+
local Query = {}
|
|
52
26
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
27
|
+
export type QueryHandle = {
|
|
28
|
+
handle: (self: QueryHandle, fn: (request: any, player: Player?) -> any) -> Types.Connection,
|
|
29
|
+
request: (self: QueryHandle, data: any, target: any?) -> any,
|
|
30
|
+
name: (self: QueryHandle) -> string,
|
|
31
|
+
stats: (self: QueryHandle) -> Types.PacketStats,
|
|
32
|
+
}
|
|
57
33
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
34
|
+
function Query.define(
|
|
35
|
+
name: string,
|
|
36
|
+
requestCodec: Types.InternalCodec<any>,
|
|
37
|
+
responseCodec: Types.InternalCodec<any>,
|
|
38
|
+
options: Types.QueryOptions?
|
|
39
|
+
): QueryHandle
|
|
40
|
+
local opts = options or {} :: Types.QueryOptions
|
|
41
|
+
local timeout = opts.timeout or DEFAULT_TIMEOUT
|
|
42
|
+
|
|
43
|
+
-- Register request channel
|
|
44
|
+
local reqOpenFn = Channel.resolveOpenFn(Channel.TS_NONE, name)
|
|
45
|
+
local reqReg = Registry.register(
|
|
46
|
+
name,
|
|
47
|
+
Registry.KIND_REQUEST,
|
|
48
|
+
requestCodec,
|
|
49
|
+
false,
|
|
50
|
+
nil,
|
|
51
|
+
IS_SERVER,
|
|
52
|
+
1,
|
|
53
|
+
Channel.TS_NONE,
|
|
54
|
+
reqOpenFn,
|
|
55
|
+
opts.rateLimit or { maxPerSecond = 30 },
|
|
56
|
+
opts.validate,
|
|
57
|
+
nil
|
|
58
|
+
)
|
|
63
59
|
|
|
64
|
-
|
|
65
|
-
local
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
60
|
+
-- Register response channel (paired)
|
|
61
|
+
local respOpenFn = Channel.resolveOpenFn(Channel.TS_NONE, `{name}_resp`)
|
|
62
|
+
local respReg = Registry.register(
|
|
63
|
+
`{name}_resp`,
|
|
64
|
+
Registry.KIND_RESPONSE,
|
|
65
|
+
responseCodec,
|
|
66
|
+
false,
|
|
67
|
+
reqReg.id,
|
|
68
|
+
false,
|
|
69
|
+
1,
|
|
70
|
+
Channel.TS_NONE,
|
|
71
|
+
respOpenFn,
|
|
72
|
+
nil,
|
|
73
|
+
nil,
|
|
74
|
+
nil
|
|
75
|
+
)
|
|
69
76
|
|
|
70
|
-
|
|
71
|
-
if source ~= nil and entry.source ~= nil and source ~= entry.source then
|
|
72
|
-
return
|
|
73
|
-
end
|
|
77
|
+
reqReg.partner = respReg.id
|
|
74
78
|
|
|
75
|
-
|
|
76
|
-
|
|
79
|
+
-- Lazy-require to avoid circular deps
|
|
80
|
+
local _server: any = nil
|
|
81
|
+
local _client: any = nil
|
|
77
82
|
|
|
78
|
-
|
|
79
|
-
|
|
83
|
+
local function getServer(): any
|
|
84
|
+
if not _server then
|
|
85
|
+
_server = require(script.Parent.Parent.transport.Server)
|
|
86
|
+
end
|
|
87
|
+
return _server
|
|
80
88
|
end
|
|
81
89
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
90
|
+
local function getClient(): any
|
|
91
|
+
if not _client then
|
|
92
|
+
_client = require(script.Parent.Parent.transport.Client)
|
|
93
|
+
end
|
|
94
|
+
return _client
|
|
86
95
|
end
|
|
87
|
-
end
|
|
88
96
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
97
|
+
-- Listen for incoming responses and resolve pending requests
|
|
98
|
+
respReg.signal:connect(function(value: any, sender: Player?, corrId: number)
|
|
99
|
+
local waiting = _pending[corrId]
|
|
100
|
+
if waiting then
|
|
101
|
+
_pending[corrId] = nil
|
|
102
|
+
task.spawn(waiting, value)
|
|
103
|
+
end
|
|
104
|
+
end)
|
|
92
105
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
_reqReg: Registration,
|
|
96
|
-
_respReg: Registration,
|
|
97
|
-
_timeout: number,
|
|
98
|
-
}
|
|
106
|
+
-- Listen for incoming requests and auto-respond
|
|
107
|
+
local _handler: ((any, Player?) -> any)? = nil
|
|
99
108
|
|
|
100
|
-
|
|
101
|
-
|
|
109
|
+
reqReg.signal:connect(function(value: any, sender: Player?, corrId: number)
|
|
110
|
+
if not _handler then
|
|
111
|
+
return
|
|
112
|
+
end
|
|
102
113
|
|
|
103
|
-
|
|
114
|
+
-- Run handler, get response
|
|
115
|
+
local ok, response = pcall(_handler :: any, value, sender)
|
|
104
116
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
117
|
+
if IS_SERVER then
|
|
118
|
+
if sender then
|
|
119
|
+
local Server = getServer()
|
|
120
|
+
local ch = Server.getChannel(sender, false)
|
|
121
|
+
if ok then
|
|
122
|
+
Channel.writeQuery(ch, respReg.id, corrId, responseCodec, response)
|
|
123
|
+
else
|
|
124
|
+
Channel.writeQuery(ch, respReg.id, corrId, nil, nil)
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
else
|
|
128
|
+
local Client = getClient()
|
|
129
|
+
local ch = Client.getChannel(false)
|
|
130
|
+
if ok then
|
|
131
|
+
Channel.writeQuery(ch, respReg.id, corrId, responseCodec, response)
|
|
132
|
+
else
|
|
133
|
+
Channel.writeQuery(ch, respReg.id, corrId, nil, nil)
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end)
|
|
110
137
|
|
|
111
|
-
local
|
|
112
|
-
if count == 0 then
|
|
113
|
-
return {}
|
|
114
|
-
end
|
|
138
|
+
local handle: any = {}
|
|
115
139
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
Server.writeQuery(
|
|
123
|
-
players[1],
|
|
124
|
-
self._reqReg.id,
|
|
125
|
-
self._name,
|
|
126
|
-
correlation,
|
|
127
|
-
self._reqReg.codec,
|
|
128
|
-
data
|
|
129
|
-
)
|
|
130
|
-
|
|
131
|
-
entry.timeout = task.delay(self._timeout, onTimeout, correlation)
|
|
132
|
-
local result = coroutine.yield()
|
|
133
|
-
return { [players[1]] = result }
|
|
134
|
-
end
|
|
140
|
+
function handle.handle(
|
|
141
|
+
_self: QueryHandle,
|
|
142
|
+
fn: (request: any, player: Player?) -> any
|
|
143
|
+
): Types.Connection
|
|
144
|
+
_handler = fn
|
|
135
145
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
local reqId = self._reqReg.id
|
|
143
|
-
local reqName = self._name
|
|
144
|
-
local reqCodec = self._reqReg.codec
|
|
145
|
-
local timeout = self._timeout
|
|
146
|
-
|
|
147
|
-
for i = 1, count do
|
|
148
|
-
local player = players[i]
|
|
149
|
-
local correlation = allocCorrelation()
|
|
150
|
-
correlations[i] = correlation
|
|
151
|
-
|
|
152
|
-
local entry: PendingQuery = {
|
|
153
|
-
thread = nil,
|
|
154
|
-
callback = function(resp: any): ()
|
|
155
|
-
results[player] = resp
|
|
156
|
-
remaining -= 1
|
|
157
|
-
if remaining == 0 and not finished then
|
|
158
|
-
finished = true
|
|
159
|
-
task.spawn(thread, results)
|
|
146
|
+
-- Return a connection that clears the handler on disconnect
|
|
147
|
+
return table.freeze({
|
|
148
|
+
connected = true,
|
|
149
|
+
disconnect = function(self: Types.Connection): ()
|
|
150
|
+
if not (self :: any).connected then
|
|
151
|
+
return
|
|
160
152
|
end
|
|
153
|
+
(self :: any).connected = false
|
|
154
|
+
_handler = nil
|
|
161
155
|
end,
|
|
162
|
-
|
|
163
|
-
source = player,
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
_pending[correlation] = entry
|
|
167
|
-
Server.writeQuery(player, reqId, reqName, correlation, reqCodec, data)
|
|
156
|
+
} :: any)
|
|
168
157
|
end
|
|
169
158
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
end
|
|
174
|
-
finished = true
|
|
159
|
+
function handle.request(_self: QueryHandle, data: any, target: any?): any
|
|
160
|
+
_nextCorrId += 1
|
|
161
|
+
local corrId = _nextCorrId
|
|
175
162
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
_pending[cid] = nil
|
|
180
|
-
releaseCorrelation()
|
|
163
|
+
if IS_SERVER then
|
|
164
|
+
if target == nil then
|
|
165
|
+
error(`[Lync] Query "{name}": server request requires a target`)
|
|
181
166
|
end
|
|
182
|
-
end
|
|
183
167
|
|
|
184
|
-
|
|
185
|
-
end)
|
|
168
|
+
local Server = getServer()
|
|
186
169
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
entry.timeout = timeoutThread
|
|
192
|
-
end
|
|
193
|
-
end
|
|
194
|
-
|
|
195
|
-
return coroutine.yield()
|
|
196
|
-
end
|
|
170
|
+
-- Single player
|
|
171
|
+
if typeof(target) == "Instance" and target:IsA("Player") then
|
|
172
|
+
local ch = Server.getChannel(target :: Player, false)
|
|
173
|
+
Channel.writeQuery(ch, reqReg.id, corrId, requestCodec, data)
|
|
197
174
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
local respCodec = self._respReg.codec
|
|
202
|
-
|
|
203
|
-
if IS_SERVER then
|
|
204
|
-
return self._reqReg.signal:connect(
|
|
205
|
-
function(request: any, player: Player, correlation: number): ()
|
|
206
|
-
local results = table.pack(pcall(callback, request, player))
|
|
207
|
-
if not results[1] then
|
|
208
|
-
warn(`[Lync] Query handler error on "{respName}": {results[2]}`)
|
|
209
|
-
Server.writeQueryNil(player, respId, respName, correlation)
|
|
210
|
-
return
|
|
211
|
-
end
|
|
175
|
+
-- Wait for response
|
|
176
|
+
local running = coroutine.running()
|
|
177
|
+
_pending[corrId] = running
|
|
212
178
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
179
|
+
task.delay(timeout, function()
|
|
180
|
+
if _pending[corrId] == running then
|
|
181
|
+
_pending[corrId] = nil
|
|
182
|
+
task.spawn(running, nil)
|
|
183
|
+
end
|
|
184
|
+
end)
|
|
216
185
|
|
|
217
|
-
|
|
218
|
-
Server.writeQuery(player, respId, respName, correlation, respCodec, response)
|
|
219
|
-
else
|
|
220
|
-
Server.writeQueryNil(player, respId, respName, correlation)
|
|
221
|
-
end
|
|
186
|
+
return coroutine.yield()
|
|
222
187
|
end
|
|
223
|
-
)
|
|
224
|
-
else
|
|
225
|
-
return self._reqReg.signal:connect(
|
|
226
|
-
function(request: any, _player: Player?, correlation: number): ()
|
|
227
|
-
local results = table.pack(pcall(callback, request))
|
|
228
|
-
if not results[1] then
|
|
229
|
-
warn(`[Lync] Query handler error on "{respName}": {results[2]}`)
|
|
230
|
-
Client.writeQueryNil(respId, respName, correlation)
|
|
231
|
-
return
|
|
232
|
-
end
|
|
233
188
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
189
|
+
-- Multi-target: collect responses into { [Player]: response? }
|
|
190
|
+
local targets: { Player } = {}
|
|
191
|
+
|
|
192
|
+
if typeof(target) == "table" then
|
|
193
|
+
local tbl = target :: any
|
|
194
|
+
if tbl._lyncAll then
|
|
195
|
+
targets = Players:GetPlayers()
|
|
196
|
+
elseif tbl._lyncGroup then
|
|
197
|
+
for player in tbl._members do
|
|
198
|
+
table.insert(targets, player)
|
|
199
|
+
end
|
|
240
200
|
else
|
|
241
|
-
|
|
201
|
+
for _, p in tbl do
|
|
202
|
+
if typeof(p) == "Instance" and (p :: Instance):IsA("Player") then
|
|
203
|
+
table.insert(targets, p :: Player)
|
|
204
|
+
end
|
|
205
|
+
end
|
|
242
206
|
end
|
|
243
207
|
end
|
|
244
|
-
)
|
|
245
|
-
end
|
|
246
|
-
end
|
|
247
|
-
|
|
248
|
-
-- Client: send request to server, yield until response.
|
|
249
|
-
function QueryImpl.request(self: Query, data: any): any
|
|
250
|
-
if IS_SERVER then
|
|
251
|
-
error("[Lync] query:request is client-only. Use query:requestFrom on server")
|
|
252
|
-
end
|
|
253
208
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
_pending[correlation] = entry
|
|
209
|
+
if #targets == 0 then
|
|
210
|
+
return {}
|
|
211
|
+
end
|
|
258
212
|
|
|
259
|
-
|
|
213
|
+
local results: { [Player]: any } = {}
|
|
214
|
+
local remaining = #targets
|
|
215
|
+
local running = coroutine.running()
|
|
216
|
+
|
|
217
|
+
for _, player in targets do
|
|
218
|
+
_nextCorrId += 1
|
|
219
|
+
local playerCorrId = _nextCorrId
|
|
220
|
+
local ch = Server.getChannel(player, false)
|
|
221
|
+
Channel.writeQuery(ch, reqReg.id, playerCorrId, requestCodec, data)
|
|
222
|
+
|
|
223
|
+
local playerRef = player
|
|
224
|
+
_pending[playerCorrId] = coroutine.create(function(response: any)
|
|
225
|
+
results[playerRef] = response
|
|
226
|
+
remaining -= 1
|
|
227
|
+
if remaining == 0 then
|
|
228
|
+
task.spawn(running, results)
|
|
229
|
+
end
|
|
230
|
+
end)
|
|
231
|
+
end
|
|
260
232
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
233
|
+
-- Timeout
|
|
234
|
+
task.delay(timeout, function()
|
|
235
|
+
if remaining > 0 then
|
|
236
|
+
remaining = 0
|
|
237
|
+
task.spawn(running, results)
|
|
238
|
+
end
|
|
239
|
+
end)
|
|
240
|
+
|
|
241
|
+
return coroutine.yield()
|
|
242
|
+
else
|
|
243
|
+
-- Client → server
|
|
244
|
+
local Client = getClient()
|
|
245
|
+
local ch = Client.getChannel(false)
|
|
246
|
+
Channel.writeQuery(ch, reqReg.id, corrId, requestCodec, data)
|
|
247
|
+
|
|
248
|
+
local running = coroutine.running()
|
|
249
|
+
_pending[corrId] = running
|
|
250
|
+
|
|
251
|
+
task.delay(timeout, function()
|
|
252
|
+
if _pending[corrId] == running then
|
|
253
|
+
_pending[corrId] = nil
|
|
254
|
+
task.spawn(running, nil)
|
|
255
|
+
end
|
|
256
|
+
end)
|
|
264
257
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
if not IS_SERVER then
|
|
268
|
-
error("[Lync] query:requestFrom is server-only. Use query:request on client")
|
|
258
|
+
return coroutine.yield()
|
|
259
|
+
end
|
|
269
260
|
end
|
|
270
261
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
local entry: PendingQuery = { thread = thread, timeout = nil, source = player }
|
|
274
|
-
_pending[correlation] = entry
|
|
275
|
-
|
|
276
|
-
Server.writeQuery(player, self._reqReg.id, self._name, correlation, self._reqReg.codec, data)
|
|
277
|
-
|
|
278
|
-
entry.timeout = task.delay(self._timeout, onTimeout, correlation)
|
|
279
|
-
return coroutine.yield()
|
|
280
|
-
end
|
|
281
|
-
|
|
282
|
-
-- Server: send request to all players, yield until all respond or timeout.
|
|
283
|
-
function QueryImpl.requestAll(self: Query, data: any): { [Player]: any? }
|
|
284
|
-
return requestMulti(self, Players:GetPlayers(), data)
|
|
285
|
-
end
|
|
286
|
-
|
|
287
|
-
-- Server: send request to a list of players.
|
|
288
|
-
function QueryImpl.requestList(self: Query, players: { Player }, data: any): { [Player]: any? }
|
|
289
|
-
return requestMulti(self, players, data)
|
|
290
|
-
end
|
|
291
|
-
|
|
292
|
-
-- Server: send request to all players in a group.
|
|
293
|
-
function QueryImpl.requestGroup(self: Query, group: any, data: any): { [Player]: any? }
|
|
294
|
-
local set = group:getSet()
|
|
295
|
-
local players = {} :: { Player }
|
|
296
|
-
for player in set do
|
|
297
|
-
table.insert(players, player)
|
|
262
|
+
function handle.name(_self: QueryHandle): string
|
|
263
|
+
return name
|
|
298
264
|
end
|
|
299
|
-
return requestMulti(self, players, data)
|
|
300
|
-
end
|
|
301
|
-
|
|
302
|
-
table.freeze(QueryImpl)
|
|
303
|
-
|
|
304
|
-
-- Public --------------------------------------------------------------
|
|
305
265
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
266
|
+
function handle.stats(_self: QueryHandle): Types.PacketStats
|
|
267
|
+
return {
|
|
268
|
+
bytesSent = reqReg.bytesSent + respReg.bytesSent,
|
|
269
|
+
bytesReceived = reqReg.bytesReceived + respReg.bytesReceived,
|
|
270
|
+
fires = reqReg.fires + respReg.fires,
|
|
271
|
+
recvFires = reqReg.recvFires + respReg.recvFires,
|
|
272
|
+
drops = reqReg.drops + respReg.drops,
|
|
273
|
+
}
|
|
314
274
|
end
|
|
315
275
|
|
|
316
|
-
|
|
317
|
-
local respSignal = Signal.create()
|
|
318
|
-
|
|
319
|
-
local reqReg, respReg = Registry.registerQueryPair(
|
|
320
|
-
name,
|
|
321
|
-
config.request,
|
|
322
|
-
config.response,
|
|
323
|
-
reqSignal,
|
|
324
|
-
respSignal,
|
|
325
|
-
config.rateLimit,
|
|
326
|
-
config.validate
|
|
327
|
-
)
|
|
328
|
-
|
|
329
|
-
respSignal:connect(function(resp: any, source: Player?, correlation: number): ()
|
|
330
|
-
completeQuery(correlation, resp, source)
|
|
331
|
-
end)
|
|
332
|
-
|
|
333
|
-
return setmetatable({
|
|
334
|
-
_name = name,
|
|
335
|
-
_reqReg = reqReg,
|
|
336
|
-
_respReg = respReg,
|
|
337
|
-
_timeout = config.timeout or 5,
|
|
338
|
-
}, QueryImpl)
|
|
276
|
+
return table.freeze(handle)
|
|
339
277
|
end
|
|
340
278
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
279
|
+
function Query.pendingCount(): number
|
|
280
|
+
local count = 0
|
|
281
|
+
for _ in _pending do
|
|
282
|
+
count += 1
|
|
283
|
+
end
|
|
284
|
+
return count
|
|
344
285
|
end
|
|
345
286
|
|
|
346
|
-
return table.freeze(
|
|
287
|
+
return table.freeze(Query)
|