@axpecter/lync 1.4.3 → 1.5.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 +41 -2
- package/package.json +1 -1
- package/src/Types.luau +13 -1
- package/src/api/Group.luau +35 -28
- package/src/api/Namespace.luau +107 -89
- package/src/api/Packet.luau +69 -51
- package/src/api/Query.luau +101 -95
- package/src/api/Scope.luau +32 -18
- package/src/api/Signal.luau +78 -56
- package/src/codec/Base.luau +17 -17
- package/src/codec/composite/Array.luau +74 -74
- package/src/codec/composite/Map.luau +80 -80
- package/src/codec/composite/Optional.luau +14 -14
- package/src/codec/composite/Shared.luau +35 -35
- package/src/codec/composite/Struct.luau +108 -108
- package/src/codec/composite/Tagged.luau +71 -71
- package/src/codec/composite/Tuple.luau +35 -35
- package/src/codec/datatype/Buffer.luau +18 -18
- package/src/codec/datatype/CFrame.luau +24 -24
- package/src/codec/datatype/Color.luau +8 -12
- package/src/codec/datatype/Instance.luau +13 -13
- package/src/codec/datatype/IntVector.luau +17 -17
- package/src/codec/datatype/NumberRange.luau +7 -7
- package/src/codec/datatype/Ray.luau +16 -16
- package/src/codec/datatype/Rect.luau +13 -13
- package/src/codec/datatype/Region.luau +32 -36
- package/src/codec/datatype/Sequence.luau +41 -41
- package/src/codec/datatype/String.luau +28 -28
- package/src/codec/datatype/UDim.luau +17 -17
- package/src/codec/datatype/Vector.luau +14 -18
- package/src/codec/meta/Auto.luau +75 -73
- package/src/codec/meta/Bitfield.luau +46 -46
- package/src/codec/meta/Custom.luau +7 -7
- package/src/codec/meta/Enum.luau +25 -25
- package/src/codec/meta/Nothing.luau +3 -3
- package/src/codec/meta/Quantized.luau +63 -60
- package/src/codec/meta/Unknown.luau +11 -11
- package/src/codec/primitive/Bool.luau +12 -12
- package/src/codec/primitive/Float16.luau +28 -28
- package/src/codec/primitive/Number.luau +41 -41
- package/src/codec/primitive/Varint.luau +19 -19
- package/src/init.luau +81 -61
- package/src/internal/Baseline.luau +7 -7
- package/src/internal/Channel.luau +56 -56
- package/src/internal/Middleware.luau +29 -29
- package/src/internal/Pool.luau +15 -15
- package/src/internal/Registry.luau +19 -19
- package/src/transport/Bridge.luau +17 -17
- package/src/transport/Client.luau +46 -46
- package/src/transport/Gate.luau +56 -64
- package/src/transport/Reader.luau +34 -34
- package/src/transport/Server.luau +89 -89
package/src/api/Packet.luau
CHANGED
|
@@ -2,21 +2,22 @@
|
|
|
2
2
|
--!optimize 2
|
|
3
3
|
-- Packet definition and send/listen API.
|
|
4
4
|
|
|
5
|
-
local RunService = game:GetService
|
|
5
|
+
local RunService = game:GetService("RunService")
|
|
6
6
|
|
|
7
|
-
local Client = require
|
|
8
|
-
local Registry = require
|
|
9
|
-
local Server = require
|
|
10
|
-
local Signal = require
|
|
11
|
-
local Types = require
|
|
7
|
+
local Client = require(script.Parent.Parent.transport.Client)
|
|
8
|
+
local Registry = require(script.Parent.Parent.internal.Registry)
|
|
9
|
+
local Server = require(script.Parent.Parent.transport.Server)
|
|
10
|
+
local Signal = require(script.Parent.Signal)
|
|
11
|
+
local Types = require(script.Parent.Parent.Types)
|
|
12
12
|
|
|
13
13
|
type Connection = Types.Connection
|
|
14
|
+
type Codec<T> = Types.Codec<T>
|
|
14
15
|
type InternalCodec<T> = Types.InternalCodec<T>
|
|
15
16
|
type PacketConfig<T> = Types.PacketConfig<T>
|
|
16
17
|
|
|
17
|
-
-- Constants
|
|
18
|
+
-- Constants -----------------------------------------------------------
|
|
18
19
|
|
|
19
|
-
local IS_SERVER = RunService:IsServer
|
|
20
|
+
local IS_SERVER = RunService:IsServer()
|
|
20
21
|
|
|
21
22
|
local serverWriteTo = Server.writeTo
|
|
22
23
|
local serverWriteToAll = Server.writeToAll
|
|
@@ -28,32 +29,44 @@ local clientWrite = Client.write
|
|
|
28
29
|
local DELTA_TARGETED = 1
|
|
29
30
|
local DELTA_BROADCAST = 2
|
|
30
31
|
|
|
31
|
-
-- Private
|
|
32
|
+
-- Private -------------------------------------------------------------
|
|
32
33
|
|
|
33
|
-
|
|
34
|
+
type PacketFields = {
|
|
35
|
+
_id: number,
|
|
36
|
+
_name: string,
|
|
37
|
+
_codec: Codec<any>,
|
|
38
|
+
_isUnreliable: boolean,
|
|
39
|
+
_isDelta: boolean,
|
|
40
|
+
_deltaMode: number,
|
|
41
|
+
_signal: Signal.Signal,
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
-- Shared methods(both contexts)
|
|
34
45
|
local SharedImpl = {}
|
|
35
46
|
|
|
36
|
-
function SharedImpl.listen
|
|
37
|
-
return self._signal:connect
|
|
47
|
+
function SharedImpl.listen(self: Packet, callback: (...any) -> ()): Connection
|
|
48
|
+
return self._signal:connect(callback)
|
|
38
49
|
end
|
|
39
50
|
|
|
40
|
-
function SharedImpl.once
|
|
41
|
-
return self._signal:once
|
|
51
|
+
function SharedImpl.once(self: Packet, callback: (...any) -> ()): Connection
|
|
52
|
+
return self._signal:once(callback)
|
|
42
53
|
end
|
|
43
54
|
|
|
44
|
-
function SharedImpl.wait
|
|
45
|
-
return self._signal:wait
|
|
55
|
+
function SharedImpl.wait(self: Packet): ...any
|
|
56
|
+
return self._signal:wait()
|
|
46
57
|
end
|
|
47
58
|
|
|
48
|
-
function SharedImpl.disconnectAll
|
|
49
|
-
self._signal:disconnectAll
|
|
59
|
+
function SharedImpl.disconnectAll(self: Packet): ()
|
|
60
|
+
self._signal:disconnectAll()
|
|
50
61
|
end
|
|
51
62
|
|
|
52
63
|
-- Server-only metatable. Single send() dispatches on target type.
|
|
53
|
-
local ServerImpl = setmetatable
|
|
64
|
+
local ServerImpl = setmetatable({}, { __index = SharedImpl })
|
|
54
65
|
ServerImpl.__index = ServerImpl
|
|
55
66
|
|
|
56
|
-
|
|
67
|
+
export type Packet = typeof(setmetatable({} :: PacketFields, ServerImpl))
|
|
68
|
+
|
|
69
|
+
local function checkDeltaMode(self: Packet, mode: number): ()
|
|
57
70
|
if not self._isDelta then
|
|
58
71
|
return
|
|
59
72
|
end
|
|
@@ -61,13 +74,13 @@ local function checkDeltaMode (self: any, mode: number): ()
|
|
|
61
74
|
if current == 0 then
|
|
62
75
|
self._deltaMode = mode
|
|
63
76
|
elseif current ~= mode then
|
|
64
|
-
error
|
|
77
|
+
error(`[Lync] Delta packet cannot mix targeted and broadcast: "{self._name}"`)
|
|
65
78
|
end
|
|
66
79
|
end
|
|
67
80
|
|
|
68
|
-
function ServerImpl.send
|
|
81
|
+
function ServerImpl.send(self: Packet, data: any, target: any?): ()
|
|
69
82
|
if target == nil then
|
|
70
|
-
error
|
|
83
|
+
error("[Lync] Server packet:send requires a target")
|
|
71
84
|
end
|
|
72
85
|
|
|
73
86
|
local id = self._id
|
|
@@ -76,9 +89,9 @@ function ServerImpl.send (self: any, data: any, target: any?): ()
|
|
|
76
89
|
local isUnreliable = self._isUnreliable
|
|
77
90
|
|
|
78
91
|
-- Single player
|
|
79
|
-
if typeof
|
|
80
|
-
checkDeltaMode
|
|
81
|
-
serverWriteTo
|
|
92
|
+
if typeof(target) == "Instance" then
|
|
93
|
+
checkDeltaMode(self, DELTA_TARGETED)
|
|
94
|
+
serverWriteTo(target :: Player, id, name, codec, data, isUnreliable)
|
|
82
95
|
return
|
|
83
96
|
end
|
|
84
97
|
|
|
@@ -87,63 +100,63 @@ function ServerImpl.send (self: any, data: any, target: any?): ()
|
|
|
87
100
|
|
|
88
101
|
-- Lync.all sentinel
|
|
89
102
|
if tag == "all" then
|
|
90
|
-
checkDeltaMode
|
|
91
|
-
serverWriteToAll
|
|
103
|
+
checkDeltaMode(self, DELTA_BROADCAST)
|
|
104
|
+
serverWriteToAll(id, name, codec, data, isUnreliable)
|
|
92
105
|
return
|
|
93
106
|
end
|
|
94
107
|
|
|
95
108
|
-- Lync.except(player, ...) descriptor
|
|
96
109
|
if tag == "except" then
|
|
97
|
-
checkDeltaMode
|
|
98
|
-
serverWriteToAllExcept
|
|
110
|
+
checkDeltaMode(self, DELTA_BROADCAST)
|
|
111
|
+
serverWriteToAllExcept(target._set, id, name, codec, data, isUnreliable)
|
|
99
112
|
return
|
|
100
113
|
end
|
|
101
114
|
|
|
102
115
|
-- Group object
|
|
103
116
|
if tag == "group" then
|
|
104
|
-
checkDeltaMode
|
|
105
|
-
serverWriteToSet
|
|
117
|
+
checkDeltaMode(self, DELTA_BROADCAST)
|
|
118
|
+
serverWriteToSet(target:getSet(), id, name, codec, data, isUnreliable)
|
|
106
119
|
return
|
|
107
120
|
end
|
|
108
121
|
|
|
109
|
-
-- Player list
|
|
110
|
-
checkDeltaMode
|
|
111
|
-
serverWriteToList
|
|
122
|
+
-- Player list(array)
|
|
123
|
+
checkDeltaMode(self, DELTA_TARGETED)
|
|
124
|
+
serverWriteToList(target :: { Player }, id, name, codec, data, isUnreliable)
|
|
112
125
|
end
|
|
113
126
|
|
|
114
|
-
table.freeze
|
|
127
|
+
table.freeze(ServerImpl)
|
|
115
128
|
|
|
116
129
|
-- Client-only metatable. Has send(), no target needed.
|
|
117
|
-
local ClientImpl = setmetatable
|
|
130
|
+
local ClientImpl = setmetatable({}, { __index = SharedImpl })
|
|
118
131
|
ClientImpl.__index = ClientImpl
|
|
119
132
|
|
|
120
|
-
function ClientImpl.send
|
|
121
|
-
clientWrite
|
|
133
|
+
function ClientImpl.send(self: Packet, data: any): ()
|
|
134
|
+
clientWrite(self._id, self._name, self._codec, data, self._isUnreliable)
|
|
122
135
|
end
|
|
123
136
|
|
|
124
|
-
table.freeze
|
|
137
|
+
table.freeze(ClientImpl)
|
|
125
138
|
|
|
126
|
-
-- Public
|
|
139
|
+
-- Public --------------------------------------------------------------
|
|
127
140
|
|
|
128
|
-
local
|
|
141
|
+
local PacketModule = {}
|
|
129
142
|
|
|
130
|
-
function
|
|
143
|
+
function PacketModule.define(name: string, config: PacketConfig<any>): Packet
|
|
131
144
|
if #name == 0 then
|
|
132
|
-
error
|
|
145
|
+
error("[Lync] Packet name must not be empty")
|
|
133
146
|
end
|
|
134
147
|
if not config.value then
|
|
135
|
-
error
|
|
148
|
+
error(`[Lync] Packet requires a value codec: "{name}"`)
|
|
136
149
|
end
|
|
137
150
|
|
|
138
151
|
local isUnreliable = config.unreliable or false
|
|
139
152
|
|
|
140
153
|
if (config.value :: InternalCodec<any>)._isDelta and isUnreliable then
|
|
141
|
-
error
|
|
154
|
+
error(`[Lync] Delta codec requires reliable delivery: "{name}"`)
|
|
142
155
|
end
|
|
143
156
|
|
|
144
|
-
local signal = Signal.create
|
|
157
|
+
local signal = Signal.create()
|
|
145
158
|
|
|
146
|
-
local reg = Registry.register
|
|
159
|
+
local reg = Registry.register(
|
|
147
160
|
name,
|
|
148
161
|
config.value,
|
|
149
162
|
isUnreliable,
|
|
@@ -155,7 +168,7 @@ function Packet.define (name: string, config: PacketConfig<any>): any
|
|
|
155
168
|
|
|
156
169
|
local isDelta = (config.value :: InternalCodec<any>)._isDelta == true
|
|
157
170
|
|
|
158
|
-
|
|
171
|
+
local fields: PacketFields = {
|
|
159
172
|
_id = reg.id,
|
|
160
173
|
_name = reg.name,
|
|
161
174
|
_codec = reg.codec,
|
|
@@ -163,7 +176,12 @@ function Packet.define (name: string, config: PacketConfig<any>): any
|
|
|
163
176
|
_isDelta = isDelta,
|
|
164
177
|
_deltaMode = 0,
|
|
165
178
|
_signal = signal,
|
|
166
|
-
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if IS_SERVER then
|
|
182
|
+
return setmetatable(fields, ServerImpl)
|
|
183
|
+
end
|
|
184
|
+
return setmetatable(fields, ClientImpl) :: Packet
|
|
167
185
|
end
|
|
168
186
|
|
|
169
|
-
return table.freeze
|
|
187
|
+
return table.freeze(PacketModule)
|
package/src/api/Query.luau
CHANGED
|
@@ -2,26 +2,27 @@
|
|
|
2
2
|
--!optimize 2
|
|
3
3
|
-- Bidirectional request-reply over RemoteEvents.
|
|
4
4
|
|
|
5
|
-
local Players = game:GetService
|
|
6
|
-
local RunService = game:GetService
|
|
5
|
+
local Players = game:GetService("Players")
|
|
6
|
+
local RunService = game:GetService("RunService")
|
|
7
7
|
|
|
8
|
-
local Client = require
|
|
9
|
-
local Registry = require
|
|
10
|
-
local Server = require
|
|
11
|
-
local Signal = require
|
|
12
|
-
local Types = require
|
|
8
|
+
local Client = require(script.Parent.Parent.transport.Client)
|
|
9
|
+
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
|
+
local Types = require(script.Parent.Parent.Types)
|
|
13
13
|
|
|
14
14
|
type Connection = Types.Connection
|
|
15
15
|
type QueryConfig<R, S> = Types.QueryConfig<R, S>
|
|
16
|
+
type Registration = Types.Registration
|
|
16
17
|
|
|
17
|
-
-- Constants
|
|
18
|
+
-- Constants -----------------------------------------------------------
|
|
18
19
|
|
|
19
|
-
local IS_SERVER = RunService:IsServer
|
|
20
|
+
local IS_SERVER = RunService:IsServer()
|
|
20
21
|
|
|
21
22
|
-- Wire ceiling: correlationId is u16 in Channel.writeQuery / Reader.process.
|
|
22
23
|
local POOL_SIZE = 65536
|
|
23
24
|
|
|
24
|
-
-- State
|
|
25
|
+
-- State ---------------------------------------------------------------
|
|
25
26
|
|
|
26
27
|
type PendingQuery = {
|
|
27
28
|
thread: thread?,
|
|
@@ -33,11 +34,11 @@ local _pending = {} :: { [number]: PendingQuery }
|
|
|
33
34
|
local _nextId = 0
|
|
34
35
|
local _activeCount = 0
|
|
35
36
|
|
|
36
|
-
-- Private
|
|
37
|
+
-- Private -------------------------------------------------------------
|
|
37
38
|
|
|
38
|
-
local function allocCorrelation
|
|
39
|
+
local function allocCorrelation(): number
|
|
39
40
|
if _activeCount >= POOL_SIZE then
|
|
40
|
-
error
|
|
41
|
+
error("[Lync] All 65536 query correlation slots exhausted")
|
|
41
42
|
end
|
|
42
43
|
|
|
43
44
|
local id = _nextId
|
|
@@ -55,38 +56,50 @@ end
|
|
|
55
56
|
|
|
56
57
|
-- Decrements the active correlation counter. Does not free a specific slot;
|
|
57
58
|
-- that is handled by nil-ing _pending[id] at the call site.
|
|
58
|
-
local function releaseCorrelation
|
|
59
|
+
local function releaseCorrelation(): ()
|
|
59
60
|
_activeCount -= 1
|
|
60
61
|
end
|
|
61
62
|
|
|
62
|
-
local function completeQuery
|
|
63
|
+
local function completeQuery(id: number, data: any): ()
|
|
63
64
|
local entry = _pending[id]
|
|
64
65
|
if not entry then
|
|
65
66
|
return
|
|
66
67
|
end
|
|
67
68
|
|
|
68
69
|
_pending[id] = nil
|
|
69
|
-
releaseCorrelation
|
|
70
|
+
releaseCorrelation()
|
|
70
71
|
|
|
71
72
|
if entry.timeout then
|
|
72
|
-
task.cancel
|
|
73
|
+
task.cancel(entry.timeout)
|
|
73
74
|
end
|
|
74
75
|
|
|
75
76
|
if entry.callback then
|
|
76
|
-
entry.callback
|
|
77
|
+
entry.callback(data)
|
|
77
78
|
elseif entry.thread then
|
|
78
|
-
coroutine.resume
|
|
79
|
+
coroutine.resume(entry.thread :: thread, data)
|
|
79
80
|
end
|
|
80
81
|
end
|
|
81
82
|
|
|
82
|
-
local function onTimeout
|
|
83
|
-
completeQuery
|
|
83
|
+
local function onTimeout(correlation: number): ()
|
|
84
|
+
completeQuery(correlation, nil)
|
|
84
85
|
end
|
|
85
86
|
|
|
87
|
+
type QueryFields = {
|
|
88
|
+
_name: string,
|
|
89
|
+
_reqReg: Registration,
|
|
90
|
+
_respReg: Registration,
|
|
91
|
+
_timeout: number,
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
local QueryImpl = {}
|
|
95
|
+
QueryImpl.__index = QueryImpl
|
|
96
|
+
|
|
97
|
+
export type Query = typeof(setmetatable({} :: QueryFields, QueryImpl))
|
|
98
|
+
|
|
86
99
|
-- Send a query to multiple players and yield. Returns { [Player]: response? }.
|
|
87
|
-
local function requestMulti
|
|
100
|
+
local function requestMulti(self: Query, players: { Player }, data: any): { [Player]: any? }
|
|
88
101
|
if not IS_SERVER then
|
|
89
|
-
error
|
|
102
|
+
error("[Lync] Multi-request is server-only")
|
|
90
103
|
end
|
|
91
104
|
|
|
92
105
|
local count = #players
|
|
@@ -95,13 +108,12 @@ local function requestMulti (self: any, players: { Player }, data: any): { [Play
|
|
|
95
108
|
end
|
|
96
109
|
|
|
97
110
|
if count == 1 then
|
|
98
|
-
|
|
99
|
-
local
|
|
100
|
-
local thread = coroutine.running ()
|
|
111
|
+
local correlation = allocCorrelation()
|
|
112
|
+
local thread = coroutine.running()
|
|
101
113
|
local entry: PendingQuery = { thread = thread, timeout = nil }
|
|
102
114
|
_pending[correlation] = entry
|
|
103
115
|
|
|
104
|
-
Server.writeQuery
|
|
116
|
+
Server.writeQuery(
|
|
105
117
|
players[1],
|
|
106
118
|
self._reqReg.id,
|
|
107
119
|
self._name,
|
|
@@ -110,15 +122,15 @@ local function requestMulti (self: any, players: { Player }, data: any): { [Play
|
|
|
110
122
|
data
|
|
111
123
|
)
|
|
112
124
|
|
|
113
|
-
entry.timeout = task.delay
|
|
114
|
-
local result = coroutine.yield
|
|
125
|
+
entry.timeout = task.delay(self._timeout, onTimeout, correlation)
|
|
126
|
+
local result = coroutine.yield()
|
|
115
127
|
return { [players[1]] = result }
|
|
116
128
|
end
|
|
117
129
|
|
|
118
|
-
local thread = coroutine.running
|
|
130
|
+
local thread = coroutine.running()
|
|
119
131
|
local results = {} :: { [Player]: any? }
|
|
120
132
|
local remaining = count
|
|
121
|
-
local correlations = table.create
|
|
133
|
+
local correlations = table.create(count) :: { number }
|
|
122
134
|
local finished = false
|
|
123
135
|
|
|
124
136
|
local reqId = self._reqReg.id
|
|
@@ -128,28 +140,27 @@ local function requestMulti (self: any, players: { Player }, data: any): { [Play
|
|
|
128
140
|
|
|
129
141
|
for i = 1, count do
|
|
130
142
|
local player = players[i]
|
|
131
|
-
local correlation = allocCorrelation
|
|
143
|
+
local correlation = allocCorrelation()
|
|
132
144
|
correlations[i] = correlation
|
|
133
145
|
|
|
134
146
|
local entry: PendingQuery = {
|
|
135
147
|
thread = nil,
|
|
136
|
-
callback = function
|
|
148
|
+
callback = function(resp: any): ()
|
|
137
149
|
results[player] = resp
|
|
138
150
|
remaining -= 1
|
|
139
151
|
if remaining == 0 and not finished then
|
|
140
152
|
finished = true
|
|
141
|
-
task.spawn
|
|
153
|
+
task.spawn(thread, results)
|
|
142
154
|
end
|
|
143
155
|
end,
|
|
144
156
|
timeout = nil,
|
|
145
157
|
}
|
|
146
158
|
|
|
147
159
|
_pending[correlation] = entry
|
|
148
|
-
|
|
149
|
-
Server.writeQuery (player, reqId, reqName, correlation, reqCodec, data)
|
|
160
|
+
Server.writeQuery(player, reqId, reqName, correlation, reqCodec, data)
|
|
150
161
|
end
|
|
151
162
|
|
|
152
|
-
local timeoutThread = task.delay
|
|
163
|
+
local timeoutThread = task.delay(timeout, function(): ()
|
|
153
164
|
if finished then
|
|
154
165
|
return
|
|
155
166
|
end
|
|
@@ -157,14 +168,13 @@ local function requestMulti (self: any, players: { Player }, data: any): { [Play
|
|
|
157
168
|
|
|
158
169
|
for i = 1, count do
|
|
159
170
|
local cid = correlations[i]
|
|
160
|
-
|
|
161
|
-
if entry then
|
|
171
|
+
if _pending[cid] then
|
|
162
172
|
_pending[cid] = nil
|
|
163
|
-
releaseCorrelation
|
|
173
|
+
releaseCorrelation()
|
|
164
174
|
end
|
|
165
175
|
end
|
|
166
176
|
|
|
167
|
-
task.spawn
|
|
177
|
+
task.spawn(thread, results)
|
|
168
178
|
end)
|
|
169
179
|
|
|
170
180
|
for i = 1, count do
|
|
@@ -175,44 +185,41 @@ local function requestMulti (self: any, players: { Player }, data: any): { [Play
|
|
|
175
185
|
end
|
|
176
186
|
end
|
|
177
187
|
|
|
178
|
-
return coroutine.yield
|
|
188
|
+
return coroutine.yield()
|
|
179
189
|
end
|
|
180
190
|
|
|
181
|
-
|
|
182
|
-
QueryImpl.__index = QueryImpl
|
|
183
|
-
|
|
184
|
-
function QueryImpl.listen (self: any, callback: (...any) -> any): Connection
|
|
191
|
+
function QueryImpl.listen(self: Query, callback: (...any) -> any): Connection
|
|
185
192
|
local respId = self._respReg.id
|
|
186
193
|
local respName = self._name
|
|
187
194
|
local respCodec = self._respReg.codec
|
|
188
195
|
|
|
189
196
|
if IS_SERVER then
|
|
190
|
-
return self._reqReg.signal:connect
|
|
191
|
-
function
|
|
192
|
-
local ok, response = pcall
|
|
197
|
+
return self._reqReg.signal:connect(
|
|
198
|
+
function(request: any, player: Player, correlation: number): ()
|
|
199
|
+
local ok, response = pcall(callback, request, player)
|
|
193
200
|
if not ok then
|
|
194
|
-
warn
|
|
201
|
+
warn(`[Lync] Query handler error on "{respName}": {response}`)
|
|
195
202
|
end
|
|
196
203
|
|
|
197
204
|
if ok and response ~= nil then
|
|
198
|
-
Server.writeQuery
|
|
205
|
+
Server.writeQuery(player, respId, respName, correlation, respCodec, response)
|
|
199
206
|
else
|
|
200
|
-
Server.writeQueryNil
|
|
207
|
+
Server.writeQueryNil(player, respId, respName, correlation)
|
|
201
208
|
end
|
|
202
209
|
end
|
|
203
210
|
)
|
|
204
211
|
else
|
|
205
|
-
return self._reqReg.signal:connect
|
|
206
|
-
function
|
|
207
|
-
local ok, response = pcall
|
|
212
|
+
return self._reqReg.signal:connect(
|
|
213
|
+
function(request: any, _player: Player?, correlation: number): ()
|
|
214
|
+
local ok, response = pcall(callback, request)
|
|
208
215
|
if not ok then
|
|
209
|
-
warn
|
|
216
|
+
warn(`[Lync] Query handler error on "{respName}": {response}`)
|
|
210
217
|
end
|
|
211
218
|
|
|
212
219
|
if ok and response ~= nil then
|
|
213
|
-
Client.writeQuery
|
|
220
|
+
Client.writeQuery(respId, respName, correlation, respCodec, response)
|
|
214
221
|
else
|
|
215
|
-
Client.writeQueryNil
|
|
222
|
+
Client.writeQueryNil(respId, respName, correlation)
|
|
216
223
|
end
|
|
217
224
|
end
|
|
218
225
|
)
|
|
@@ -220,78 +227,77 @@ function QueryImpl.listen (self: any, callback: (...any) -> any): Connection
|
|
|
220
227
|
end
|
|
221
228
|
|
|
222
229
|
-- Client: send request to server, yield until response.
|
|
223
|
-
function QueryImpl.request
|
|
230
|
+
function QueryImpl.request(self: Query, data: any): any
|
|
224
231
|
if IS_SERVER then
|
|
225
|
-
error
|
|
232
|
+
error("[Lync] query:request is client-only. Use query:requestFrom on server")
|
|
226
233
|
end
|
|
227
234
|
|
|
228
|
-
local correlation = allocCorrelation
|
|
229
|
-
local thread = coroutine.running
|
|
235
|
+
local correlation = allocCorrelation()
|
|
236
|
+
local thread = coroutine.running()
|
|
230
237
|
local entry: PendingQuery = { thread = thread, timeout = nil }
|
|
231
238
|
_pending[correlation] = entry
|
|
232
239
|
|
|
233
|
-
Client.writeQuery
|
|
240
|
+
Client.writeQuery(self._reqReg.id, self._name, correlation, self._reqReg.codec, data)
|
|
234
241
|
|
|
235
|
-
entry.timeout = task.delay
|
|
236
|
-
return coroutine.yield
|
|
242
|
+
entry.timeout = task.delay(self._timeout, onTimeout, correlation)
|
|
243
|
+
return coroutine.yield()
|
|
237
244
|
end
|
|
238
245
|
|
|
239
246
|
-- Server: send request to one player, yield until response.
|
|
240
|
-
function QueryImpl.requestFrom
|
|
247
|
+
function QueryImpl.requestFrom(self: Query, player: Player, data: any): any
|
|
241
248
|
if not IS_SERVER then
|
|
242
|
-
error
|
|
249
|
+
error("[Lync] query:requestFrom is server-only. Use query:request on client")
|
|
243
250
|
end
|
|
244
251
|
|
|
245
|
-
local correlation = allocCorrelation
|
|
246
|
-
local thread = coroutine.running
|
|
252
|
+
local correlation = allocCorrelation()
|
|
253
|
+
local thread = coroutine.running()
|
|
247
254
|
local entry: PendingQuery = { thread = thread, timeout = nil }
|
|
248
255
|
_pending[correlation] = entry
|
|
249
256
|
|
|
250
|
-
Server.writeQuery
|
|
257
|
+
Server.writeQuery(player, self._reqReg.id, self._name, correlation, self._reqReg.codec, data)
|
|
251
258
|
|
|
252
|
-
entry.timeout = task.delay
|
|
253
|
-
return coroutine.yield
|
|
259
|
+
entry.timeout = task.delay(self._timeout, onTimeout, correlation)
|
|
260
|
+
return coroutine.yield()
|
|
254
261
|
end
|
|
255
262
|
|
|
256
263
|
-- Server: send request to all players, yield until all respond or timeout.
|
|
257
|
-
function QueryImpl.requestAll
|
|
258
|
-
|
|
259
|
-
return requestMulti (self, players, data)
|
|
264
|
+
function QueryImpl.requestAll(self: Query, data: any): { [Player]: any? }
|
|
265
|
+
return requestMulti(self, Players:GetPlayers(), data)
|
|
260
266
|
end
|
|
261
267
|
|
|
262
268
|
-- Server: send request to a list of players.
|
|
263
|
-
function QueryImpl.requestList
|
|
264
|
-
return requestMulti
|
|
269
|
+
function QueryImpl.requestList(self: Query, players: { Player }, data: any): { [Player]: any? }
|
|
270
|
+
return requestMulti(self, players, data)
|
|
265
271
|
end
|
|
266
272
|
|
|
267
273
|
-- Server: send request to all players in a group.
|
|
268
|
-
function QueryImpl.requestGroup
|
|
269
|
-
local set = group:getSet
|
|
274
|
+
function QueryImpl.requestGroup(self: Query, group: any, data: any): { [Player]: any? }
|
|
275
|
+
local set = group:getSet()
|
|
270
276
|
local players = {} :: { Player }
|
|
271
277
|
for player in set do
|
|
272
|
-
table.insert
|
|
278
|
+
table.insert(players, player)
|
|
273
279
|
end
|
|
274
|
-
return requestMulti
|
|
280
|
+
return requestMulti(self, players, data)
|
|
275
281
|
end
|
|
276
282
|
|
|
277
|
-
table.freeze
|
|
283
|
+
table.freeze(QueryImpl)
|
|
278
284
|
|
|
279
|
-
-- Public
|
|
285
|
+
-- Public --------------------------------------------------------------
|
|
280
286
|
|
|
281
|
-
local
|
|
287
|
+
local QueryModule = {}
|
|
282
288
|
|
|
283
|
-
function
|
|
289
|
+
function QueryModule.define(name: string, config: QueryConfig<any, any>): Query
|
|
284
290
|
if not config.request then
|
|
285
|
-
error
|
|
291
|
+
error(`[Lync] Query requires a request codec: "{name}"`)
|
|
286
292
|
end
|
|
287
293
|
if not config.response then
|
|
288
|
-
error
|
|
294
|
+
error(`[Lync] Query requires a response codec: "{name}"`)
|
|
289
295
|
end
|
|
290
296
|
|
|
291
|
-
local reqSignal = Signal.create
|
|
292
|
-
local respSignal = Signal.create
|
|
297
|
+
local reqSignal = Signal.create()
|
|
298
|
+
local respSignal = Signal.create()
|
|
293
299
|
|
|
294
|
-
local reqReg, respReg = Registry.registerQueryPair
|
|
300
|
+
local reqReg, respReg = Registry.registerQueryPair(
|
|
295
301
|
name,
|
|
296
302
|
config.request,
|
|
297
303
|
config.response,
|
|
@@ -301,11 +307,11 @@ function Query.define (name: string, config: QueryConfig<any, any>): any
|
|
|
301
307
|
config.validate
|
|
302
308
|
)
|
|
303
309
|
|
|
304
|
-
respSignal:connect
|
|
305
|
-
completeQuery
|
|
310
|
+
respSignal:connect(function(resp: any, correlation: number): ()
|
|
311
|
+
completeQuery(correlation, resp)
|
|
306
312
|
end)
|
|
307
313
|
|
|
308
|
-
return setmetatable
|
|
314
|
+
return setmetatable({
|
|
309
315
|
_name = name,
|
|
310
316
|
_reqReg = reqReg,
|
|
311
317
|
_respReg = respReg,
|
|
@@ -314,8 +320,8 @@ function Query.define (name: string, config: QueryConfig<any, any>): any
|
|
|
314
320
|
end
|
|
315
321
|
|
|
316
322
|
-- Returns the number of queries currently awaiting a response.
|
|
317
|
-
function
|
|
323
|
+
function QueryModule.pendingCount(): number
|
|
318
324
|
return _activeCount
|
|
319
325
|
end
|
|
320
326
|
|
|
321
|
-
return table.freeze
|
|
327
|
+
return table.freeze(QueryModule)
|