@rbxts/tether 1.4.0 → 1.4.2
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 +1 -1
- package/out/emitters/client-emitter.d.ts +49 -0
- package/out/emitters/client-emitter.luau +156 -0
- package/out/emitters/contextual-emitter.d.ts +26 -0
- package/out/emitters/contextual-emitter.luau +49 -0
- package/out/emitters/message-emitter.d.ts +41 -0
- package/out/emitters/message-emitter.luau +222 -0
- package/out/emitters/server-emitter.d.ts +30 -0
- package/out/emitters/server-emitter.luau +107 -0
- package/out/index.d.ts +1 -1
- package/out/init.luau +1 -1
- package/out/logging.d.ts +15 -0
- package/out/logging.luau +4 -0
- package/out/relayer.d.ts +16 -0
- package/out/relayer.luau +214 -0
- package/out/serdes.d.ts +13 -0
- package/out/serdes.luau +58 -0
- package/out/structs.d.ts +3 -2
- package/out/utility.d.ts +12 -0
- package/out/utility.luau +74 -0
- package/package.json +1 -1
- package/out/message-emitter.d.ts +0 -128
- package/out/message-emitter.luau +0 -792
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local RunService = TS.import(script, TS.getModule(script, "@rbxts", "services")).RunService
|
|
4
|
+
local ContextualEmitter = TS.import(script, script.Parent, "contextual-emitter").ContextualEmitter
|
|
5
|
+
if setLuneContext == nil then
|
|
6
|
+
setLuneContext = function() end
|
|
7
|
+
end
|
|
8
|
+
local ServerEmitter
|
|
9
|
+
do
|
|
10
|
+
local super = ContextualEmitter
|
|
11
|
+
ServerEmitter = setmetatable({}, {
|
|
12
|
+
__tostring = function()
|
|
13
|
+
return "ServerEmitter"
|
|
14
|
+
end,
|
|
15
|
+
__index = super,
|
|
16
|
+
})
|
|
17
|
+
ServerEmitter.__index = ServerEmitter
|
|
18
|
+
function ServerEmitter.new(...)
|
|
19
|
+
local self = setmetatable({}, ServerEmitter)
|
|
20
|
+
return self:constructor(...) or self
|
|
21
|
+
end
|
|
22
|
+
function ServerEmitter:constructor(...)
|
|
23
|
+
super.constructor(self, ...)
|
|
24
|
+
self.context = "server"
|
|
25
|
+
end
|
|
26
|
+
function ServerEmitter:emit(message, data, unreliable)
|
|
27
|
+
if unreliable == nil then
|
|
28
|
+
unreliable = false
|
|
29
|
+
end
|
|
30
|
+
if RunService:IsServer() then
|
|
31
|
+
error("[tether::error] Cannot emit message from server to server")
|
|
32
|
+
end
|
|
33
|
+
task.spawn(function()
|
|
34
|
+
local _binding = self.master:runServerMiddlewares(message, data)
|
|
35
|
+
local dropRequest = _binding[1]
|
|
36
|
+
local newData = _binding[2]
|
|
37
|
+
if dropRequest then
|
|
38
|
+
return nil
|
|
39
|
+
end
|
|
40
|
+
self.master.relayer:queueMessage(self.context, message, { message, newData, unreliable })
|
|
41
|
+
end)
|
|
42
|
+
end
|
|
43
|
+
function ServerEmitter:setCallback(message, returnMessage, callback)
|
|
44
|
+
if RunService:IsClient() then
|
|
45
|
+
error("[tether::error] Cannot listen to client message from server")
|
|
46
|
+
end
|
|
47
|
+
return self:on(message, function(player, data)
|
|
48
|
+
local returnValue = callback(player, data)
|
|
49
|
+
-- Defer the response emission to end of frame and swap context to avoid context check issues
|
|
50
|
+
-- task.defer guarantees response is sent by end of current frame, ensuring predictable timing in production
|
|
51
|
+
task.defer(function()
|
|
52
|
+
setLuneContext("server")
|
|
53
|
+
self.master.client:emit(player, returnMessage, returnValue)
|
|
54
|
+
setLuneContext("both")
|
|
55
|
+
end)
|
|
56
|
+
end)
|
|
57
|
+
end
|
|
58
|
+
function ServerEmitter:invoke(message, returnMessage, data, unreliable)
|
|
59
|
+
if unreliable == nil then
|
|
60
|
+
unreliable = false
|
|
61
|
+
end
|
|
62
|
+
if RunService:IsServer() then
|
|
63
|
+
error("[tether::error] Cannot invoke function from server to server")
|
|
64
|
+
end
|
|
65
|
+
local _binding = self.master
|
|
66
|
+
local clientFunctions = _binding.clientFunctions
|
|
67
|
+
local _returnMessage = returnMessage
|
|
68
|
+
if not (clientFunctions[_returnMessage] ~= nil) then
|
|
69
|
+
local _returnMessage_1 = returnMessage
|
|
70
|
+
clientFunctions[_returnMessage_1] = {}
|
|
71
|
+
end
|
|
72
|
+
local _returnMessage_1 = returnMessage
|
|
73
|
+
local functions = clientFunctions[_returnMessage_1]
|
|
74
|
+
local returnValue
|
|
75
|
+
local responseCallback = function(data)
|
|
76
|
+
returnValue = data
|
|
77
|
+
return returnValue
|
|
78
|
+
end
|
|
79
|
+
functions[responseCallback] = true
|
|
80
|
+
self:emit(message, data, unreliable)
|
|
81
|
+
return TS.Promise.new(function(resolve, reject)
|
|
82
|
+
-- awful
|
|
83
|
+
local frames = 0
|
|
84
|
+
while true do
|
|
85
|
+
local _condition = returnValue == nil
|
|
86
|
+
if _condition then
|
|
87
|
+
local _original = frames
|
|
88
|
+
frames += 1
|
|
89
|
+
_condition = _original < 400
|
|
90
|
+
end
|
|
91
|
+
if not _condition then
|
|
92
|
+
break
|
|
93
|
+
end
|
|
94
|
+
RunService.Heartbeat:Wait()
|
|
95
|
+
end
|
|
96
|
+
if frames == 400 then
|
|
97
|
+
return reject("[tether::error] Server function timed out (no response)")
|
|
98
|
+
end
|
|
99
|
+
-- clean up the callback after receiving the response
|
|
100
|
+
functions[responseCallback] = nil
|
|
101
|
+
resolve(returnValue)
|
|
102
|
+
end)
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
return {
|
|
106
|
+
ServerEmitter = ServerEmitter,
|
|
107
|
+
}
|
package/out/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { MessageEmitter } from "./message-emitter";
|
|
1
|
+
export { MessageEmitter } from "./emitters/message-emitter";
|
|
2
2
|
export { BuiltinMiddlewares } from "./builtin-middlewares";
|
|
3
3
|
export { DropRequest, type ClientMiddleware, type ServerMiddleware, type SharedMiddleware, type Middleware, type MiddlewareContext } from "./middleware";
|
package/out/init.luau
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
-- Compiled with roblox-ts v3.0.0
|
|
2
2
|
local TS = _G[script]
|
|
3
3
|
local exports = {}
|
|
4
|
-
exports.MessageEmitter = TS.import(script, script, "message-emitter").MessageEmitter
|
|
4
|
+
exports.MessageEmitter = TS.import(script, script, "emitters", "message-emitter").MessageEmitter
|
|
5
5
|
exports.BuiltinMiddlewares = TS.import(script, script, "builtin-middlewares").BuiltinMiddlewares
|
|
6
6
|
exports.DropRequest = TS.import(script, script, "middleware").DropRequest
|
|
7
7
|
return exports
|
package/out/logging.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare const enum Error {
|
|
2
|
+
NoServerListen = "[tether::error] Cannot listen to server message from client",
|
|
3
|
+
NoClientListen = "[tether::error] Cannot listen to client message from server",
|
|
4
|
+
NoServerToServer = "[tether::error] Cannot emit message from server to server",
|
|
5
|
+
NoClientToClient = "[tether::error] Cannot emit message from client to client",
|
|
6
|
+
NoClientToAllClients = "[tether::error] Cannot emit message from client to all clients",
|
|
7
|
+
NoServerToServerFunction = "[tether::error] Cannot invoke function from server to server",
|
|
8
|
+
NoClientToClientFunction = "[tether::error] Cannot invoke function from client to client",
|
|
9
|
+
ServerFunctionTimeout = "[tether::error] Server function timed out (no response)",
|
|
10
|
+
ClientFunctionTimeout = "[tether::error] Client function timed out (no response)"
|
|
11
|
+
}
|
|
12
|
+
export declare const enum Warning {
|
|
13
|
+
MessageBufferTooLong = "[tether::warning] Rejected packet because message buffer was larger than one byte",
|
|
14
|
+
MetaGenerationFailed = "[tether::warning] Failed to generate message metadata - make sure you have the Flamework transformer and are using Flamework macro-friendly types in your schemas"
|
|
15
|
+
}
|
package/out/logging.luau
ADDED
package/out/relayer.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { BaseMessage } from "./structs";
|
|
2
|
+
import type { MessageEmitter } from "./emitters/message-emitter";
|
|
3
|
+
export type ServerQueuedMessageData<MessageData> = [keyof MessageData & BaseMessage, MessageData[keyof MessageData], boolean];
|
|
4
|
+
export type ClientQueuedMessageData<MessageData> = [Player | Player[], ...ServerQueuedMessageData<MessageData>];
|
|
5
|
+
export type QueuedMessageData<MessageData> = ClientQueuedMessageData<MessageData> | ServerQueuedMessageData<MessageData>;
|
|
6
|
+
export declare class Relayer<MessageData> {
|
|
7
|
+
private readonly emitter;
|
|
8
|
+
private serverQueue;
|
|
9
|
+
private clientBroadcastQueue;
|
|
10
|
+
private clientQueue;
|
|
11
|
+
constructor(emitter: MessageEmitter<MessageData>);
|
|
12
|
+
queueMessage<K extends keyof MessageData>(context: "client" | "server" | true, message: K & BaseMessage, data: QueuedMessageData<MessageData>): void;
|
|
13
|
+
/** Send all queued data across the network simultaneously */
|
|
14
|
+
relayAll(): void;
|
|
15
|
+
private relay;
|
|
16
|
+
}
|
package/out/relayer.luau
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local _services = TS.import(script, TS.getModule(script, "@rbxts", "services"))
|
|
4
|
+
local ReplicatedStorage = _services.ReplicatedStorage
|
|
5
|
+
local RunService = _services.RunService
|
|
6
|
+
local _utility = TS.import(script, script.Parent, "utility")
|
|
7
|
+
local getAllPacketsWhich = _utility.getAllPacketsWhich
|
|
8
|
+
local isReliable = _utility.isReliable
|
|
9
|
+
local isUnreliable = _utility.isUnreliable
|
|
10
|
+
local shouldBatch = _utility.shouldBatch
|
|
11
|
+
if setLuneContext == nil then
|
|
12
|
+
setLuneContext = function() end
|
|
13
|
+
end
|
|
14
|
+
local sendMessage
|
|
15
|
+
do
|
|
16
|
+
local name = "sendMessage"
|
|
17
|
+
local existing = ReplicatedStorage:FindFirstChild(name)
|
|
18
|
+
local remote = (existing or Instance.new("RemoteEvent", ReplicatedStorage))
|
|
19
|
+
if existing == nil then
|
|
20
|
+
remote.Name = name
|
|
21
|
+
end
|
|
22
|
+
sendMessage = remote
|
|
23
|
+
end
|
|
24
|
+
local sendUnreliableMessage
|
|
25
|
+
do
|
|
26
|
+
local name = "unreliableMessage"
|
|
27
|
+
local existing = ReplicatedStorage:FindFirstChild(name)
|
|
28
|
+
local remote = (existing or Instance.new("UnreliableRemoteEvent", ReplicatedStorage))
|
|
29
|
+
if existing == nil then
|
|
30
|
+
remote.Name = name
|
|
31
|
+
end
|
|
32
|
+
sendUnreliableMessage = remote
|
|
33
|
+
end
|
|
34
|
+
local Relayer
|
|
35
|
+
do
|
|
36
|
+
Relayer = setmetatable({}, {
|
|
37
|
+
__tostring = function()
|
|
38
|
+
return "Relayer"
|
|
39
|
+
end,
|
|
40
|
+
})
|
|
41
|
+
Relayer.__index = Relayer
|
|
42
|
+
function Relayer.new(...)
|
|
43
|
+
local self = setmetatable({}, Relayer)
|
|
44
|
+
return self:constructor(...) or self
|
|
45
|
+
end
|
|
46
|
+
function Relayer:constructor(emitter)
|
|
47
|
+
self.emitter = emitter
|
|
48
|
+
self.serverQueue = {}
|
|
49
|
+
self.clientBroadcastQueue = {}
|
|
50
|
+
self.clientQueue = {}
|
|
51
|
+
setLuneContext("client")
|
|
52
|
+
if RunService:IsClient() then
|
|
53
|
+
self.emitter.trash:add(sendMessage.OnClientEvent:Connect(function(...)
|
|
54
|
+
local serializedPacket = { ... }
|
|
55
|
+
return self.emitter:onRemoteFire(false, serializedPacket)
|
|
56
|
+
end))
|
|
57
|
+
self.emitter.trash:add(sendUnreliableMessage.OnClientEvent:Connect(function(...)
|
|
58
|
+
local serializedPacket = { ... }
|
|
59
|
+
return self.emitter:onRemoteFire(false, serializedPacket)
|
|
60
|
+
end))
|
|
61
|
+
end
|
|
62
|
+
setLuneContext("server")
|
|
63
|
+
if RunService:IsServer() then
|
|
64
|
+
self.emitter.trash:add(sendMessage.OnServerEvent:Connect(function(player, ...)
|
|
65
|
+
local serializedPacket = { ... }
|
|
66
|
+
return self.emitter:onRemoteFire(true, serializedPacket, player)
|
|
67
|
+
end))
|
|
68
|
+
self.emitter.trash:add(sendUnreliableMessage.OnServerEvent:Connect(function(player, ...)
|
|
69
|
+
local serializedPacket = { ... }
|
|
70
|
+
return self.emitter:onRemoteFire(true, serializedPacket, player)
|
|
71
|
+
end))
|
|
72
|
+
end
|
|
73
|
+
local elapsed = 0
|
|
74
|
+
local _binding = self.emitter.options
|
|
75
|
+
local batchRemotes = _binding.batchRemotes
|
|
76
|
+
local batchRate = _binding.batchRate
|
|
77
|
+
if not batchRemotes then
|
|
78
|
+
return self
|
|
79
|
+
end
|
|
80
|
+
self.emitter.trash:add(RunService.Heartbeat:Connect(function(dt)
|
|
81
|
+
elapsed += dt
|
|
82
|
+
if elapsed < batchRate then
|
|
83
|
+
return nil
|
|
84
|
+
end
|
|
85
|
+
elapsed -= batchRate
|
|
86
|
+
self:relayAll()
|
|
87
|
+
end))
|
|
88
|
+
end
|
|
89
|
+
function Relayer:queueMessage(context, message, data)
|
|
90
|
+
local queue = if context == "client" then self.clientQueue elseif context == true then self.clientBroadcastQueue else self.serverQueue
|
|
91
|
+
local _data = data
|
|
92
|
+
table.insert(queue, _data)
|
|
93
|
+
if not shouldBatch(message, self.emitter.options) then
|
|
94
|
+
self:relayAll()
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
function Relayer:relayAll()
|
|
98
|
+
if RunService:IsClient() then
|
|
99
|
+
return self:relay(function(...)
|
|
100
|
+
local packets = { ... }
|
|
101
|
+
return sendMessage:FireServer(unpack(packets))
|
|
102
|
+
end, function(...)
|
|
103
|
+
local packets = { ... }
|
|
104
|
+
return sendUnreliableMessage:FireServer(unpack(packets))
|
|
105
|
+
end, self.serverQueue, function()
|
|
106
|
+
self.serverQueue = {}
|
|
107
|
+
return self.serverQueue
|
|
108
|
+
end)
|
|
109
|
+
end
|
|
110
|
+
self:relay(function(...)
|
|
111
|
+
local packets = { ... }
|
|
112
|
+
return sendMessage:FireAllClients(unpack(packets))
|
|
113
|
+
end, function(...)
|
|
114
|
+
local packets = { ... }
|
|
115
|
+
return sendUnreliableMessage:FireAllClients(unpack(packets))
|
|
116
|
+
end, self.clientBroadcastQueue, function()
|
|
117
|
+
self.clientBroadcastQueue = {}
|
|
118
|
+
return self.clientBroadcastQueue
|
|
119
|
+
end)
|
|
120
|
+
local playerPacketInfos = {}
|
|
121
|
+
local addClientPacket = function(player, packetInfo)
|
|
122
|
+
local _player = player
|
|
123
|
+
local _condition = playerPacketInfos[_player]
|
|
124
|
+
if _condition == nil then
|
|
125
|
+
_condition = {}
|
|
126
|
+
end
|
|
127
|
+
local packetInfos = _condition
|
|
128
|
+
local _packetInfo = packetInfo
|
|
129
|
+
table.insert(packetInfos, _packetInfo)
|
|
130
|
+
local _player_1 = player
|
|
131
|
+
playerPacketInfos[_player_1] = packetInfos
|
|
132
|
+
end
|
|
133
|
+
for _, _binding in self.clientQueue do
|
|
134
|
+
local player = _binding[1]
|
|
135
|
+
local message = _binding[2]
|
|
136
|
+
local data = _binding[3]
|
|
137
|
+
local unreliable = _binding[4]
|
|
138
|
+
local packet = self.emitter.serdes:serializePacket(message, data)
|
|
139
|
+
local info = {
|
|
140
|
+
packet = packet,
|
|
141
|
+
unreliable = unreliable,
|
|
142
|
+
}
|
|
143
|
+
if typeof(player) == "Instance" then
|
|
144
|
+
addClientPacket(player, info)
|
|
145
|
+
else
|
|
146
|
+
for _1, p in player do
|
|
147
|
+
addClientPacket(p, info)
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
if not (#self.clientQueue == 0) then
|
|
152
|
+
for player, packetInfos in playerPacketInfos do
|
|
153
|
+
if #packetInfos == 0 then
|
|
154
|
+
continue
|
|
155
|
+
end
|
|
156
|
+
local unreliablePackets = getAllPacketsWhich(packetInfos, isUnreliable)
|
|
157
|
+
local packets = getAllPacketsWhich(packetInfos, isReliable)
|
|
158
|
+
if not (#unreliablePackets == 0) then
|
|
159
|
+
sendUnreliableMessage:FireClient(player, unpack(unreliablePackets))
|
|
160
|
+
end
|
|
161
|
+
if not (#packets == 0) then
|
|
162
|
+
sendMessage:FireClient(player, unpack(packets))
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
self.clientQueue = {}
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
function Relayer:relay(send, sendUnreliable, queue, clearQueue)
|
|
169
|
+
if #queue == 0 then
|
|
170
|
+
return nil
|
|
171
|
+
end
|
|
172
|
+
-- ▼ ReadonlyArray.map ▼
|
|
173
|
+
local _newValue = table.create(#queue)
|
|
174
|
+
local _callback = function(messageData)
|
|
175
|
+
local message
|
|
176
|
+
local data
|
|
177
|
+
local unreliable
|
|
178
|
+
local _arg0 = messageData[1]
|
|
179
|
+
if typeof(_arg0) == "Instance" then
|
|
180
|
+
local _binding = messageData
|
|
181
|
+
message = _binding[2]
|
|
182
|
+
data = _binding[3]
|
|
183
|
+
unreliable = _binding[4]
|
|
184
|
+
else
|
|
185
|
+
local _binding = messageData
|
|
186
|
+
message = _binding[1]
|
|
187
|
+
data = _binding[2]
|
|
188
|
+
unreliable = _binding[3]
|
|
189
|
+
end
|
|
190
|
+
local packet = self.emitter.serdes:serializePacket(message, data)
|
|
191
|
+
return {
|
|
192
|
+
packet = packet,
|
|
193
|
+
unreliable = unreliable,
|
|
194
|
+
}
|
|
195
|
+
end
|
|
196
|
+
for _k, _v in queue do
|
|
197
|
+
_newValue[_k] = _callback(_v, _k - 1, queue)
|
|
198
|
+
end
|
|
199
|
+
-- ▲ ReadonlyArray.map ▲
|
|
200
|
+
local packetInfos = _newValue
|
|
201
|
+
local unreliablePackets = getAllPacketsWhich(packetInfos, isUnreliable)
|
|
202
|
+
local packets = getAllPacketsWhich(packetInfos, isReliable)
|
|
203
|
+
if not (#unreliablePackets == 0) then
|
|
204
|
+
sendUnreliable(unpack(unreliablePackets))
|
|
205
|
+
end
|
|
206
|
+
if not (#packets == 0) then
|
|
207
|
+
send(unpack(packets))
|
|
208
|
+
end
|
|
209
|
+
clearQueue()
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
return {
|
|
213
|
+
Relayer = Relayer,
|
|
214
|
+
}
|
package/out/serdes.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Modding } from "@flamework/core";
|
|
2
|
+
import type { Serializer, SerializerMetadata } from "@rbxts/serio";
|
|
3
|
+
import type { BaseMessage, SerializedPacket } from "./structs";
|
|
4
|
+
export declare class Serdes<MessageData> {
|
|
5
|
+
serializers: Partial<Record<keyof MessageData, Serializer<MessageData[keyof MessageData]>>>;
|
|
6
|
+
serializePacket<Kind extends keyof MessageData>(message: Kind & BaseMessage, data?: MessageData[Kind]): SerializedPacket;
|
|
7
|
+
deserializePacket<K extends keyof MessageData>(message: K & BaseMessage, serializedPacket: SerializedPacket): MessageData[K] | undefined;
|
|
8
|
+
/** @metadata macro */
|
|
9
|
+
addSerializer<K extends keyof MessageData>(message: K & BaseMessage, meta?: Modding.Many<SerializerMetadata<MessageData[K]>>): void;
|
|
10
|
+
/** @metadata macro */
|
|
11
|
+
createMessageSerializer<Kind extends keyof MessageData>(meta?: Modding.Many<SerializerMetadata<MessageData[Kind]>>): Serializer<MessageData[Kind]>;
|
|
12
|
+
getSerializer<Kind extends keyof MessageData>(message: Kind & BaseMessage): Serializer<MessageData[Kind] | undefined> | undefined;
|
|
13
|
+
}
|
package/out/serdes.luau
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local createSerializer = TS.import(script, TS.getModule(script, "@rbxts", "serio").out).default
|
|
4
|
+
local createMessageBuffer = TS.import(script, script.Parent, "utility").createMessageBuffer
|
|
5
|
+
local Serdes
|
|
6
|
+
do
|
|
7
|
+
Serdes = setmetatable({}, {
|
|
8
|
+
__tostring = function()
|
|
9
|
+
return "Serdes"
|
|
10
|
+
end,
|
|
11
|
+
})
|
|
12
|
+
Serdes.__index = Serdes
|
|
13
|
+
function Serdes.new(...)
|
|
14
|
+
local self = setmetatable({}, Serdes)
|
|
15
|
+
return self:constructor(...) or self
|
|
16
|
+
end
|
|
17
|
+
function Serdes:constructor()
|
|
18
|
+
self.serializers = {}
|
|
19
|
+
end
|
|
20
|
+
function Serdes:serializePacket(message, data)
|
|
21
|
+
local serializer = self:getSerializer(message)
|
|
22
|
+
local messageBuf = createMessageBuffer(message)
|
|
23
|
+
if serializer == nil then
|
|
24
|
+
return {
|
|
25
|
+
messageBuf = messageBuf,
|
|
26
|
+
buf = buffer.create(0),
|
|
27
|
+
blobs = {},
|
|
28
|
+
}
|
|
29
|
+
end
|
|
30
|
+
local _object = {
|
|
31
|
+
messageBuf = messageBuf,
|
|
32
|
+
}
|
|
33
|
+
for _k, _v in serializer.serialize(data) do
|
|
34
|
+
_object[_k] = _v
|
|
35
|
+
end
|
|
36
|
+
return _object
|
|
37
|
+
end
|
|
38
|
+
function Serdes:deserializePacket(message, serializedPacket)
|
|
39
|
+
local serializer = self:getSerializer(message)
|
|
40
|
+
local _result = serializer
|
|
41
|
+
if _result ~= nil then
|
|
42
|
+
_result = _result.deserialize(serializedPacket)
|
|
43
|
+
end
|
|
44
|
+
return _result
|
|
45
|
+
end
|
|
46
|
+
function Serdes:addSerializer(message, meta)
|
|
47
|
+
self.serializers[message] = self:createMessageSerializer(meta)
|
|
48
|
+
end
|
|
49
|
+
function Serdes:createMessageSerializer(meta)
|
|
50
|
+
return createSerializer(meta)
|
|
51
|
+
end
|
|
52
|
+
function Serdes:getSerializer(message)
|
|
53
|
+
return self.serializers[message]
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
return {
|
|
57
|
+
Serdes = Serdes,
|
|
58
|
+
}
|
package/out/structs.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { Modding } from "@flamework/core";
|
|
2
2
|
import type { SerializerMetadata, SerializedData, Transform, Vector, String, u8, u16, u24, u32, i8, i16, i24, i32, f16, f24, f32, f64 } from "@rbxts/serio";
|
|
3
3
|
export type MessageCallback<T = unknown> = ServerMessageCallback<T> | ClientMessageCallback<T>;
|
|
4
|
+
export type FunctionMessageCallback<T = unknown, R = unknown> = ServerFunctionMessageCallback<T, R> | ClientFunctionMessageCallback<T, R>;
|
|
4
5
|
export type ClientMessageCallback<T = unknown> = (data: T) => void;
|
|
5
|
-
export type
|
|
6
|
+
export type ClientFunctionMessageCallback<T = unknown, R = unknown> = (data: T) => R;
|
|
6
7
|
export type ServerMessageCallback<T = unknown> = (player: Player, data: T) => void;
|
|
7
|
-
export type
|
|
8
|
+
export type ServerFunctionMessageCallback<T = unknown, R = unknown> = (player: Player, data: T) => R;
|
|
8
9
|
export type BaseMessage = number;
|
|
9
10
|
export interface PacketInfo {
|
|
10
11
|
readonly packet: SerializedPacket;
|
package/out/utility.d.ts
CHANGED
|
@@ -1 +1,13 @@
|
|
|
1
|
+
import type { BaseMessage, PacketInfo, SerializedPacket } from "./structs";
|
|
2
|
+
import type { MessageEmitterOptions } from "./emitters/message-emitter";
|
|
1
3
|
export declare function bufferToString(buf?: buffer): string;
|
|
4
|
+
export declare function encodeMessage(message: BaseMessage): number;
|
|
5
|
+
export declare function decodeMessage(encoded: number): BaseMessage;
|
|
6
|
+
export declare function writeMessage(buf: buffer, message: BaseMessage): void;
|
|
7
|
+
export declare function readMessage(packet: SerializedPacket | buffer): BaseMessage;
|
|
8
|
+
export declare function createMessageBuffer(message: BaseMessage): buffer;
|
|
9
|
+
export declare function getAllPacketsWhich(infos: PacketInfo[], predicate: (info: PacketInfo) => boolean): SerializedPacket[];
|
|
10
|
+
export declare function isUnreliable(info: PacketInfo): boolean;
|
|
11
|
+
export declare function isReliable(info: PacketInfo): boolean;
|
|
12
|
+
export declare function getPacket(info: PacketInfo): SerializedPacket;
|
|
13
|
+
export declare function shouldBatch<MessageData>(message: keyof MessageData & BaseMessage, options: MessageEmitterOptions<MessageData>): boolean;
|
package/out/utility.luau
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local COEFF = 0xFA
|
|
2
3
|
local function bufferToString(buf)
|
|
3
4
|
local s = { "{ " }
|
|
4
5
|
if buf ~= nil then
|
|
@@ -25,6 +26,79 @@ local function bufferToString(buf)
|
|
|
25
26
|
table.insert(s, "}")
|
|
26
27
|
return table.concat(s, "")
|
|
27
28
|
end
|
|
29
|
+
local function encodeMessage(message)
|
|
30
|
+
message = bit32.band((bit32.bxor(message, COEFF)), 0xFF)
|
|
31
|
+
return bit32.bor((bit32.lshift(message, 3)), (bit32.arshift(message, 5)))
|
|
32
|
+
end
|
|
33
|
+
local function decodeMessage(encoded)
|
|
34
|
+
encoded = bit32.bor((bit32.arshift(encoded, 3)), (bit32.lshift(encoded, 5)))
|
|
35
|
+
return bit32.band((bit32.bxor(encoded, COEFF)), 0xFF)
|
|
36
|
+
end
|
|
37
|
+
local function writeMessage(buf, message)
|
|
38
|
+
local _arg0 = buffer.len(buf) == 1
|
|
39
|
+
assert(_arg0)
|
|
40
|
+
buffer.writeu8(buf, 0, encodeMessage(message))
|
|
41
|
+
end
|
|
42
|
+
local function readMessage(packet)
|
|
43
|
+
local _packet = packet
|
|
44
|
+
local buf = if type(_packet) == "buffer" then packet else packet.messageBuf
|
|
45
|
+
return decodeMessage(buffer.readu8(buf, 0))
|
|
46
|
+
end
|
|
47
|
+
local function createMessageBuffer(message)
|
|
48
|
+
local messageBuf = buffer.create(1)
|
|
49
|
+
writeMessage(messageBuf, message)
|
|
50
|
+
return messageBuf
|
|
51
|
+
end
|
|
52
|
+
local getPacket
|
|
53
|
+
local function getAllPacketsWhich(infos, predicate)
|
|
54
|
+
local _infos = infos
|
|
55
|
+
local _predicate = predicate
|
|
56
|
+
-- ▼ ReadonlyArray.filter ▼
|
|
57
|
+
local _newValue = {}
|
|
58
|
+
local _length = 0
|
|
59
|
+
for _k, _v in _infos do
|
|
60
|
+
if _predicate(_v, _k - 1, _infos) == true then
|
|
61
|
+
_length += 1
|
|
62
|
+
_newValue[_length] = _v
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
-- ▲ ReadonlyArray.filter ▲
|
|
66
|
+
-- ▼ ReadonlyArray.map ▼
|
|
67
|
+
local _newValue_1 = table.create(#_newValue)
|
|
68
|
+
for _k, _v in _newValue do
|
|
69
|
+
_newValue_1[_k] = getPacket(_v, _k - 1, _newValue)
|
|
70
|
+
end
|
|
71
|
+
-- ▲ ReadonlyArray.map ▲
|
|
72
|
+
return _newValue_1
|
|
73
|
+
end
|
|
74
|
+
local function isUnreliable(info)
|
|
75
|
+
return info.unreliable
|
|
76
|
+
end
|
|
77
|
+
local function isReliable(info)
|
|
78
|
+
return not info.unreliable
|
|
79
|
+
end
|
|
80
|
+
function getPacket(info)
|
|
81
|
+
return info.packet
|
|
82
|
+
end
|
|
83
|
+
local function shouldBatch(message, options)
|
|
84
|
+
local _condition = options.batchRemotes
|
|
85
|
+
if _condition then
|
|
86
|
+
local _doNotBatch = options.doNotBatch
|
|
87
|
+
local _message = message
|
|
88
|
+
_condition = not (_doNotBatch[_message] ~= nil)
|
|
89
|
+
end
|
|
90
|
+
return _condition
|
|
91
|
+
end
|
|
28
92
|
return {
|
|
29
93
|
bufferToString = bufferToString,
|
|
94
|
+
encodeMessage = encodeMessage,
|
|
95
|
+
decodeMessage = decodeMessage,
|
|
96
|
+
writeMessage = writeMessage,
|
|
97
|
+
readMessage = readMessage,
|
|
98
|
+
createMessageBuffer = createMessageBuffer,
|
|
99
|
+
getAllPacketsWhich = getAllPacketsWhich,
|
|
100
|
+
isUnreliable = isUnreliable,
|
|
101
|
+
isReliable = isReliable,
|
|
102
|
+
getPacket = getPacket,
|
|
103
|
+
shouldBatch = shouldBatch,
|
|
30
104
|
}
|