@rbxts/tether 1.0.4 → 1.0.5

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 CHANGED
@@ -4,16 +4,16 @@ A message-based networking solution for Roblox with automatic binary serializati
4
4
  ### In `shared/messaging.ts`
5
5
  ```ts
6
6
  import type { DataType } from "@rbxts/flamework-binary-serializer";
7
+ import { MessageEmitter } from "@rbxts/tether";
7
8
 
8
- export const messageEmitter = MessageEmitter.create<MessageData>();
9
- messageEmitter.initialize();
9
+ export const messaging = MessageEmitter.create<MessageData>();
10
10
 
11
11
  export const enum Message {
12
- TEST
12
+ Test
13
13
  }
14
14
 
15
15
  export interface MessageData {
16
- [Message.TEST]: {
16
+ [Message.Test]: {
17
17
  readonly foo: string;
18
18
  readonly n: DataType.u8;
19
19
  };
@@ -25,18 +25,18 @@ export interface MessageData {
25
25
 
26
26
  ### Server
27
27
  ```ts
28
- import { Message, messageEmitter } from "shared/messaging";
28
+ import { Message, messaging } from "shared/messaging";
29
29
 
30
- messageEmitter.onServerMessage(Message.TEST, (player, data) => {
30
+ messaging.onServerMessage(Message.TEST, (player, data) => {
31
31
  print(player, "sent data:", data);
32
32
  });
33
33
  ```
34
34
 
35
35
  ### Client
36
36
  ```ts
37
- import { Message, messageEmitter } from "shared/messaging";
37
+ import { Message, messaging } from "shared/messaging";
38
38
 
39
- messageEmitter.emitServer(Message.TEST, {
39
+ messaging.emitServer(Message.TEST, {
40
40
  foo: "bar",
41
41
  n: 69
42
42
  });
@@ -0,0 +1,4 @@
1
+ import { Middleware } from "./middleware";
2
+ export declare namespace BuiltinMiddlewares {
3
+ function rateLimit<Data>(interval: number): Middleware<Data>;
4
+ }
@@ -0,0 +1,20 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local TS = _G[script]
3
+ local DropRequest = TS.import(script, script.Parent, "middleware").DropRequest
4
+ local BuiltinMiddlewares = {}
5
+ do
6
+ local _container = BuiltinMiddlewares
7
+ local function rateLimit(interval)
8
+ local lastRequest = 0
9
+ return function()
10
+ if os.clock() - lastRequest < interval then
11
+ return DropRequest
12
+ end
13
+ lastRequest = os.clock()
14
+ end
15
+ end
16
+ _container.rateLimit = rateLimit
17
+ end
18
+ return {
19
+ BuiltinMiddlewares = BuiltinMiddlewares,
20
+ }
package/out/index.d.ts CHANGED
@@ -1,29 +1,3 @@
1
- import { Modding } from "@flamework/core";
2
- import { type SerializerMetadata } from "@rbxts/flamework-binary-serializer";
3
- type ClientMessageCallback<T = unknown> = (data: T) => void;
4
- type ServerMessageCallback<T = unknown> = (player: Player, data: T) => void;
5
- export declare class MessageEmitter<MessageData> {
6
- private readonly clientCallbacks;
7
- private readonly serverCallbacks;
8
- private readonly serializers;
9
- private readonly serverEvents;
10
- private readonly clientEvents;
11
- /** @metadata macro */
12
- static create<MessageData>(metaForEachMessage?: Modding.Many<{
13
- [Kind in keyof MessageData]: Modding.Many<SerializerMetadata<MessageData[Kind]>>;
14
- }>): MessageEmitter<MessageData>;
15
- private constructor();
16
- /** @metadata macro */
17
- addSerializer<Kind extends keyof MessageData>(message: Kind, meta?: Modding.Many<SerializerMetadata<MessageData[Kind]>>): void;
18
- initialize(): RBXScriptConnection;
19
- onServerMessage<Kind extends keyof MessageData>(message: Kind, callback: ServerMessageCallback<MessageData[Kind]>): () => void;
20
- onClientMessage<Kind extends keyof MessageData>(message: Kind, callback: ClientMessageCallback<MessageData[Kind]>): () => void;
21
- emitServer<Kind extends keyof MessageData>(message: Kind, data: MessageData[Kind], unreliable?: boolean): void;
22
- emitClient<Kind extends keyof MessageData>(player: Player, message: Kind, data: MessageData[Kind], unreliable?: boolean): void;
23
- emitAllClients<Kind extends keyof MessageData>(message: Kind, data: MessageData[Kind], unreliable?: boolean): void;
24
- private getPacket;
25
- /** @metadata macro */
26
- private createMessageSerializer;
27
- private getSerializer;
28
- }
29
- export {};
1
+ export { MessageEmitter } from "./message-emitter";
2
+ export { BuiltinMiddlewares } from "./builtin-middlewares";
3
+ export { MiddlewareProvider, DropRequest, type ClientMiddleware, type ServerMiddleware, type Middleware } from "./middleware";
package/out/init.luau CHANGED
@@ -1,212 +1,9 @@
1
1
  -- Compiled with roblox-ts v3.0.0
2
2
  local TS = _G[script]
3
- local t = TS.import(script, TS.getModule(script, "@rbxts", "t").lib.ts).t
4
- local Networking = TS.import(script, TS.getModule(script, "@flamework", "networking").out).Networking
5
- local createBinarySerializer = TS.import(script, TS.getModule(script, "@rbxts", "flamework-binary-serializer").out).createBinarySerializer
6
- local RunService = TS.import(script, TS.getModule(script, "@rbxts", "services")).RunService
7
- local GlobalEvents = Networking.createEvent("@rbxts/tether:init@GlobalEvents")
8
- local MessageEmitter
9
- do
10
- MessageEmitter = setmetatable({}, {
11
- __tostring = function()
12
- return "MessageEmitter"
13
- end,
14
- })
15
- MessageEmitter.__index = MessageEmitter
16
- function MessageEmitter.new(...)
17
- local self = setmetatable({}, MessageEmitter)
18
- return self:constructor(...) or self
19
- end
20
- function MessageEmitter:constructor()
21
- self.clientCallbacks = {}
22
- self.serverCallbacks = {}
23
- self.serializers = {}
24
- if RunService:IsServer() then
25
- self.serverEvents = GlobalEvents:createServer({}, {
26
- incomingIds = { "sendServerMessage", "sendUnreliableServerMessage" },
27
- incoming = {
28
- sendServerMessage = { { t.union(t.string, t.number), t.interface({
29
- buffer = t.typeof("buffer"),
30
- blobs = t.array(t.any),
31
- }) }, nil },
32
- sendUnreliableServerMessage = { { t.union(t.string, t.number), t.interface({
33
- buffer = t.typeof("buffer"),
34
- blobs = t.array(t.any),
35
- }) }, nil },
36
- },
37
- incomingUnreliable = {
38
- sendUnreliableServerMessage = true,
39
- },
40
- outgoingIds = { "sendClientMessage", "sendUnreliableClientMessage" },
41
- outgoingUnreliable = {
42
- sendUnreliableClientMessage = true,
43
- },
44
- namespaceIds = {},
45
- namespaces = {},
46
- })
47
- else
48
- self.clientEvents = GlobalEvents:createClient({}, {
49
- incomingIds = { "sendClientMessage", "sendUnreliableClientMessage" },
50
- incoming = {
51
- sendClientMessage = { { t.union(t.string, t.number), t.interface({
52
- buffer = t.typeof("buffer"),
53
- blobs = t.array(t.any),
54
- }) }, nil },
55
- sendUnreliableClientMessage = { { t.union(t.string, t.number), t.interface({
56
- buffer = t.typeof("buffer"),
57
- blobs = t.array(t.any),
58
- }) }, nil },
59
- },
60
- incomingUnreliable = {
61
- sendUnreliableClientMessage = true,
62
- },
63
- outgoingIds = { "sendServerMessage", "sendUnreliableServerMessage" },
64
- outgoingUnreliable = {
65
- sendUnreliableServerMessage = true,
66
- },
67
- namespaceIds = {},
68
- namespaces = {},
69
- })
70
- end
71
- end
72
- function MessageEmitter:create(metaForEachMessage)
73
- if metaForEachMessage == nil then
74
- warn("[Tether]: Failed to generate serializer metadata for MessageEmitter")
75
- end
76
- local emitter = MessageEmitter.new()
77
- if metaForEachMessage == nil then
78
- return emitter
79
- end
80
- for kind, meta in pairs(metaForEachMessage) do
81
- emitter:addSerializer(kind, meta)
82
- end
83
- return emitter
84
- end
85
- function MessageEmitter:addSerializer(message, meta)
86
- self.serializers[message] = self:createMessageSerializer(meta)
87
- end
88
- function MessageEmitter:initialize()
89
- if RunService:IsClient() then
90
- return self.clientEvents.sendClientMessage:connect(function(sentMessage, _param)
91
- local buffer = _param.buffer
92
- local blobs = _param.blobs
93
- local _clientCallbacks = self.clientCallbacks
94
- local _sentMessage = sentMessage
95
- local _condition = _clientCallbacks[_sentMessage]
96
- if _condition == nil then
97
- _condition = {}
98
- end
99
- local messageCallbacks = _condition
100
- if #messageCallbacks == 0 then
101
- return nil
102
- end
103
- local serializer = self:getSerializer(sentMessage)
104
- local data = serializer.deserialize(buffer, blobs)
105
- for _, callback in messageCallbacks do
106
- callback(data)
107
- end
108
- end)
109
- else
110
- return self.serverEvents.sendServerMessage:connect(function(player, sentMessage, _param)
111
- local buffer = _param.buffer
112
- local blobs = _param.blobs
113
- local _serverCallbacks = self.serverCallbacks
114
- local _sentMessage = sentMessage
115
- local _condition = _serverCallbacks[_sentMessage]
116
- if _condition == nil then
117
- _condition = {}
118
- end
119
- local messageCallbacks = _condition
120
- if #messageCallbacks == 0 then
121
- return nil
122
- end
123
- local serializer = self:getSerializer(sentMessage)
124
- local data = serializer.deserialize(buffer, blobs)
125
- for _, callback in messageCallbacks do
126
- callback(player, data)
127
- end
128
- end)
129
- end
130
- end
131
- function MessageEmitter:onServerMessage(message, callback)
132
- local _serverCallbacks = self.serverCallbacks
133
- local _message = message
134
- if not (_serverCallbacks[_message] ~= nil) then
135
- local _serverCallbacks_1 = self.serverCallbacks
136
- local _message_1 = message
137
- _serverCallbacks_1[_message_1] = {}
138
- end
139
- local _serverCallbacks_1 = self.serverCallbacks
140
- local _message_1 = message
141
- local callbacks = _serverCallbacks_1[_message_1]
142
- local _callback = callback
143
- table.insert(callbacks, _callback)
144
- local _serverCallbacks_2 = self.serverCallbacks
145
- local _message_2 = message
146
- _serverCallbacks_2[_message_2] = callbacks
147
- return function()
148
- local _callback_1 = callback
149
- local _arg0 = (table.find(callbacks, _callback_1) or 0) - 1
150
- return table.remove(callbacks, _arg0 + 1)
151
- end
152
- end
153
- function MessageEmitter:onClientMessage(message, callback)
154
- local _clientCallbacks = self.clientCallbacks
155
- local _message = message
156
- if not (_clientCallbacks[_message] ~= nil) then
157
- local _clientCallbacks_1 = self.clientCallbacks
158
- local _message_1 = message
159
- _clientCallbacks_1[_message_1] = {}
160
- end
161
- local _clientCallbacks_1 = self.clientCallbacks
162
- local _message_1 = message
163
- local callbacks = _clientCallbacks_1[_message_1]
164
- local _callback = callback
165
- table.insert(callbacks, _callback)
166
- local _clientCallbacks_2 = self.clientCallbacks
167
- local _message_2 = message
168
- _clientCallbacks_2[_message_2] = callbacks
169
- return function()
170
- local _callback_1 = callback
171
- local _arg0 = (table.find(callbacks, _callback_1) or 0) - 1
172
- return table.remove(callbacks, _arg0 + 1)
173
- end
174
- end
175
- function MessageEmitter:emitServer(message, data, unreliable)
176
- if unreliable == nil then
177
- unreliable = false
178
- end
179
- local send = if unreliable then self.clientEvents.sendUnreliableServerMessage else self.clientEvents.sendServerMessage
180
- send(message, self:getPacket(message, data))
181
- end
182
- function MessageEmitter:emitClient(player, message, data, unreliable)
183
- if unreliable == nil then
184
- unreliable = false
185
- end
186
- local send = if unreliable then self.serverEvents.sendUnreliableClientMessage else self.serverEvents.sendClientMessage
187
- send(player, message, self:getPacket(message, data))
188
- end
189
- function MessageEmitter:emitAllClients(message, data, unreliable)
190
- if unreliable == nil then
191
- unreliable = false
192
- end
193
- local send = if unreliable then self.serverEvents.sendUnreliableClientMessage else self.serverEvents.sendClientMessage
194
- send:broadcast(message, self:getPacket(message, data))
195
- end
196
- function MessageEmitter:getPacket(message, data, unreliable)
197
- if unreliable == nil then
198
- unreliable = false
199
- end
200
- local serializer = self:getSerializer(message)
201
- return serializer.serialize(data)
202
- end
203
- function MessageEmitter:createMessageSerializer(meta)
204
- return createBinarySerializer(meta)
205
- end
206
- function MessageEmitter:getSerializer(message)
207
- return self.serializers[tostring(message)]
208
- end
209
- end
210
- return {
211
- MessageEmitter = MessageEmitter,
212
- }
3
+ local exports = {}
4
+ exports.MessageEmitter = TS.import(script, script, "message-emitter").MessageEmitter
5
+ exports.BuiltinMiddlewares = TS.import(script, script, "builtin-middlewares").BuiltinMiddlewares
6
+ local _middleware = TS.import(script, script, "middleware")
7
+ exports.MiddlewareProvider = _middleware.MiddlewareProvider
8
+ exports.DropRequest = _middleware.DropRequest
9
+ return exports
@@ -0,0 +1,59 @@
1
+ import { Modding } from "@flamework/core";
2
+ import { type SerializerMetadata } from "@rbxts/flamework-binary-serializer";
3
+ import Destroyable from "@rbxts/destroyable";
4
+ import { MiddlewareProvider } from "./middleware";
5
+ import type { ClientMessageCallback, ServerMessageCallback } from "./structs";
6
+ export declare class MessageEmitter<MessageData> extends Destroyable {
7
+ private readonly middleware?;
8
+ private readonly clientCallbacks;
9
+ private readonly serverCallbacks;
10
+ private serializers;
11
+ private serverEvents;
12
+ private clientEvents;
13
+ /** @metadata macro */
14
+ static create<MessageData>(middleware?: MiddlewareProvider<MessageData>, metaForEachMessage?: Modding.Many<{
15
+ [Kind in keyof MessageData]: MessageData[Kind] extends undefined ? undefined : Modding.Many<SerializerMetadata<MessageData[Kind]>>;
16
+ }>): MessageEmitter<MessageData>;
17
+ private constructor();
18
+ /**.
19
+ * @returns A destructor function that disconnects the callback from the message
20
+ */
21
+ onServerMessage<Kind extends keyof MessageData>(message: Kind, callback: ServerMessageCallback<MessageData[Kind]>): () => void;
22
+ /**.
23
+ * @returns A destructor function that disconnects the callback from the message
24
+ */
25
+ onClientMessage<Kind extends keyof MessageData>(message: Kind, callback: ClientMessageCallback<MessageData[Kind]>): () => void;
26
+ private on;
27
+ /**
28
+ * Emits a message to all connected clients.
29
+ *
30
+ * @param message - The message kind to be sent.
31
+ * @param data - The data associated with the message.
32
+ * @param unreliable - Optional flag indicating if the message should be sent unreliably.
33
+ */
34
+ emitServer<Kind extends keyof MessageData>(message: Kind, data?: MessageData[Kind], unreliable?: boolean): void;
35
+ /**
36
+ * Emits a message to a specific client.
37
+ *
38
+ * @param player - The player to whom the message is sent.
39
+ * @param message - The message kind to be sent.
40
+ * @param data - The data associated with the message.
41
+ * @param unreliable - Optional flag indicating if the message should be sent unreliably.
42
+ */
43
+ emitClient<Kind extends keyof MessageData>(player: Player, message: Kind, data?: MessageData[Kind], unreliable?: boolean): void;
44
+ /**
45
+ * Emits a message to all connected clients.
46
+ *
47
+ * @param message - The message kind to be sent.
48
+ * @param data - The data associated with the message.
49
+ * @param unreliable - Optional flag indicating if the message should be sent unreliably.
50
+ */
51
+ emitAllClients<Kind extends keyof MessageData>(message: Kind, data?: MessageData[Kind], unreliable?: boolean): void;
52
+ private initialize;
53
+ private getPacket;
54
+ /** @metadata macro */
55
+ private addSerializer;
56
+ /** @metadata macro */
57
+ private createMessageSerializer;
58
+ private getSerializer;
59
+ }
@@ -0,0 +1,244 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local TS = _G[script]
3
+ local t = TS.import(script, TS.getModule(script, "@rbxts", "t").lib.ts).t
4
+ local Networking = TS.import(script, TS.getModule(script, "@flamework", "networking").out).Networking
5
+ local createBinarySerializer = TS.import(script, TS.getModule(script, "@rbxts", "flamework-binary-serializer").out).createBinarySerializer
6
+ local _services = TS.import(script, TS.getModule(script, "@rbxts", "services"))
7
+ local Players = _services.Players
8
+ local RunService = _services.RunService
9
+ local Destroyable = TS.import(script, TS.getModule(script, "@rbxts", "destroyable").out).default
10
+ local DropRequest = TS.import(script, script.Parent, "middleware").DropRequest
11
+ local GlobalEvents = Networking.createEvent("@rbxts/tether:message-emitter@GlobalEvents")
12
+ local MessageEmitter
13
+ do
14
+ local super = Destroyable
15
+ MessageEmitter = setmetatable({}, {
16
+ __tostring = function()
17
+ return "MessageEmitter"
18
+ end,
19
+ __index = super,
20
+ })
21
+ MessageEmitter.__index = MessageEmitter
22
+ function MessageEmitter.new(...)
23
+ local self = setmetatable({}, MessageEmitter)
24
+ return self:constructor(...) or self
25
+ end
26
+ function MessageEmitter:constructor(middleware)
27
+ super.constructor(self)
28
+ self.middleware = middleware
29
+ self.clientCallbacks = {}
30
+ self.serverCallbacks = {}
31
+ self.serializers = {}
32
+ self.janitor:Add(function()
33
+ table.clear(self.clientCallbacks)
34
+ table.clear(self.serverCallbacks)
35
+ self.serializers = nil
36
+ self.serverEvents = nil
37
+ self.clientEvents = nil
38
+ end)
39
+ if RunService:IsServer() then
40
+ self.serverEvents = GlobalEvents:createServer({}, {
41
+ incomingIds = { "sendServerMessage", "sendUnreliableServerMessage" },
42
+ incoming = {
43
+ sendServerMessage = { { t.union(t.string, t.number), t.optional(t.interface({
44
+ buffer = t.typeof("buffer"),
45
+ blobs = t.array(t.any),
46
+ })) }, nil },
47
+ sendUnreliableServerMessage = { { t.union(t.string, t.number), t.optional(t.interface({
48
+ buffer = t.typeof("buffer"),
49
+ blobs = t.array(t.any),
50
+ })) }, nil },
51
+ },
52
+ incomingUnreliable = {
53
+ sendUnreliableServerMessage = true,
54
+ },
55
+ outgoingIds = { "sendClientMessage", "sendUnreliableClientMessage" },
56
+ outgoingUnreliable = {
57
+ sendUnreliableClientMessage = true,
58
+ },
59
+ namespaceIds = {},
60
+ namespaces = {},
61
+ })
62
+ else
63
+ self.clientEvents = GlobalEvents:createClient({}, {
64
+ incomingIds = { "sendClientMessage", "sendUnreliableClientMessage" },
65
+ incoming = {
66
+ sendClientMessage = { { t.union(t.string, t.number), t.optional(t.interface({
67
+ buffer = t.typeof("buffer"),
68
+ blobs = t.array(t.any),
69
+ })) }, nil },
70
+ sendUnreliableClientMessage = { { t.union(t.string, t.number), t.optional(t.interface({
71
+ buffer = t.typeof("buffer"),
72
+ blobs = t.array(t.any),
73
+ })) }, nil },
74
+ },
75
+ incomingUnreliable = {
76
+ sendUnreliableClientMessage = true,
77
+ },
78
+ outgoingIds = { "sendServerMessage", "sendUnreliableServerMessage" },
79
+ outgoingUnreliable = {
80
+ sendUnreliableServerMessage = true,
81
+ },
82
+ namespaceIds = {},
83
+ namespaces = {},
84
+ })
85
+ end
86
+ end
87
+ function MessageEmitter:create(middleware, metaForEachMessage)
88
+ local emitter = MessageEmitter.new(middleware)
89
+ if metaForEachMessage == nil then
90
+ warn("[Tether]: Failed to generate serializer metadata for MessageEmitter")
91
+ return emitter:initialize()
92
+ end
93
+ for kind, meta in pairs(metaForEachMessage) do
94
+ if meta == nil then
95
+ continue
96
+ end
97
+ emitter:addSerializer(kind, meta)
98
+ end
99
+ return emitter:initialize()
100
+ end
101
+ function MessageEmitter:onServerMessage(message, callback)
102
+ return self:on(message, callback)
103
+ end
104
+ function MessageEmitter:onClientMessage(message, callback)
105
+ return self:on(message, callback)
106
+ end
107
+ function MessageEmitter:on(message, callback)
108
+ local callbacksMap = if RunService:IsServer() then self.serverCallbacks else self.clientCallbacks
109
+ local _message = message
110
+ if not (callbacksMap[_message] ~= nil) then
111
+ local _message_1 = message
112
+ callbacksMap[_message_1] = {}
113
+ end
114
+ local _message_1 = message
115
+ local callbacks = callbacksMap[_message_1]
116
+ local _callback = callback
117
+ callbacks[_callback] = true
118
+ local _message_2 = message
119
+ callbacksMap[_message_2] = callbacks
120
+ return function()
121
+ local _callback_1 = callback
122
+ -- ▼ Set.delete ▼
123
+ local _valueExisted = callbacks[_callback_1] ~= nil
124
+ callbacks[_callback_1] = nil
125
+ -- ▲ Set.delete ▲
126
+ return _valueExisted
127
+ end
128
+ end
129
+ function MessageEmitter:emitServer(message, data, unreliable)
130
+ if unreliable == nil then
131
+ unreliable = false
132
+ end
133
+ if self.middleware ~= nil then
134
+ for _, middleware in self.middleware:getServer(message) do
135
+ local result = middleware(data)
136
+ if result == DropRequest then
137
+ return nil
138
+ end
139
+ end
140
+ end
141
+ local send = if unreliable then self.clientEvents.sendUnreliableServerMessage else self.clientEvents.sendServerMessage
142
+ send(message, self:getPacket(message, data))
143
+ end
144
+ function MessageEmitter:emitClient(player, message, data, unreliable)
145
+ if unreliable == nil then
146
+ unreliable = false
147
+ end
148
+ if self.middleware ~= nil then
149
+ for _, middleware in self.middleware:getClient(message) do
150
+ local result = middleware(player, data)
151
+ if result == DropRequest then
152
+ return nil
153
+ end
154
+ end
155
+ end
156
+ local send = if unreliable then self.serverEvents.sendUnreliableClientMessage else self.serverEvents.sendClientMessage
157
+ send(player, message, self:getPacket(message, data))
158
+ end
159
+ function MessageEmitter:emitAllClients(message, data, unreliable)
160
+ if unreliable == nil then
161
+ unreliable = false
162
+ end
163
+ if self.middleware ~= nil then
164
+ for _, middleware in self.middleware:getClient(message) do
165
+ for _1, player in Players:GetPlayers() do
166
+ local result = middleware(player, data)
167
+ if result == DropRequest then
168
+ return nil
169
+ end
170
+ end
171
+ end
172
+ end
173
+ local send = if unreliable then self.serverEvents.sendUnreliableClientMessage else self.serverEvents.sendClientMessage
174
+ send:broadcast(message, self:getPacket(message, data))
175
+ end
176
+ function MessageEmitter:initialize()
177
+ if RunService:IsClient() then
178
+ self.janitor:Add(self.clientEvents.sendClientMessage:connect(function(sentMessage, packet)
179
+ local _clientCallbacks = self.clientCallbacks
180
+ local _sentMessage = sentMessage
181
+ local _condition = _clientCallbacks[_sentMessage]
182
+ if _condition == nil then
183
+ _condition = {}
184
+ end
185
+ local messageCallbacks = _condition
186
+ -- ▼ ReadonlySet.size ▼
187
+ local _size = 0
188
+ for _ in messageCallbacks do
189
+ _size += 1
190
+ end
191
+ -- ▲ ReadonlySet.size ▲
192
+ if _size == 0 then
193
+ return nil
194
+ end
195
+ local serializer = self:getSerializer(sentMessage)
196
+ local data = if packet ~= nil then serializer.deserialize(packet.buffer, packet.blobs) else nil
197
+ for callback in messageCallbacks do
198
+ callback(data)
199
+ end
200
+ end))
201
+ else
202
+ self.janitor:Add(self.serverEvents.sendServerMessage:connect(function(player, sentMessage, packet)
203
+ local _serverCallbacks = self.serverCallbacks
204
+ local _sentMessage = sentMessage
205
+ local _condition = _serverCallbacks[_sentMessage]
206
+ if _condition == nil then
207
+ _condition = {}
208
+ end
209
+ local messageCallbacks = _condition
210
+ -- ▼ ReadonlySet.size ▼
211
+ local _size = 0
212
+ for _ in messageCallbacks do
213
+ _size += 1
214
+ end
215
+ -- ▲ ReadonlySet.size ▲
216
+ if _size == 0 then
217
+ return nil
218
+ end
219
+ local serializer = self:getSerializer(sentMessage)
220
+ local data = if packet ~= nil then serializer.deserialize(packet.buffer, packet.blobs) else nil
221
+ for callback in messageCallbacks do
222
+ callback(player, data)
223
+ end
224
+ end))
225
+ end
226
+ return self
227
+ end
228
+ function MessageEmitter:getPacket(message, data)
229
+ local serializer = self:getSerializer(message)
230
+ return if data == nil then nil else serializer.serialize(data)
231
+ end
232
+ function MessageEmitter:addSerializer(message, meta)
233
+ self.serializers[message] = self:createMessageSerializer(meta)
234
+ end
235
+ function MessageEmitter:createMessageSerializer(meta)
236
+ return createBinarySerializer(meta)
237
+ end
238
+ function MessageEmitter:getSerializer(message)
239
+ return self.serializers[tostring(message)]
240
+ end
241
+ end
242
+ return {
243
+ MessageEmitter = MessageEmitter,
244
+ }
@@ -0,0 +1,18 @@
1
+ type DropRequestSymbol = symbol & {
2
+ _skip_middleware?: undefined;
3
+ };
4
+ export declare const DropRequest: DropRequestSymbol;
5
+ export type ClientMiddleware<Data = unknown> = (player: Player, data: Data | undefined) => DropRequestSymbol | void;
6
+ export type ServerMiddleware<Data = unknown> = (data: Data | undefined) => DropRequestSymbol | void;
7
+ export type Middleware<Data = unknown> = ServerMiddleware<Data> & ClientMiddleware<Data>;
8
+ export declare class MiddlewareProvider<MessageData> {
9
+ private readonly clientMiddlewares;
10
+ private readonly serverMiddlewares;
11
+ /** @hidden */
12
+ getClient<Kind extends keyof MessageData>(message: Kind): ClientMiddleware<MessageData[Kind]>[];
13
+ /** @hidden */
14
+ getServer<Kind extends keyof MessageData>(message: Kind): ServerMiddleware<MessageData[Kind]>[];
15
+ useClient<Kind extends keyof MessageData>(message: Kind, middlewares: ClientMiddleware<MessageData[Kind]> | ClientMiddleware<MessageData[Kind]>[], order?: number): this;
16
+ useServer<Kind extends keyof MessageData>(message: Kind, middlewares: ServerMiddleware<MessageData[Kind]> | ServerMiddleware<MessageData[Kind]>[], order?: number): this;
17
+ }
18
+ export {};
@@ -0,0 +1,77 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local function createSymbol(name)
3
+ local symbol = newproxy(true)
4
+ local mt = getmetatable(symbol)
5
+ mt.__tostring = function()
6
+ return name
7
+ end
8
+ return symbol
9
+ end
10
+ local DropRequest = createSymbol("DropRequest")
11
+ local MiddlewareProvider
12
+ do
13
+ MiddlewareProvider = setmetatable({}, {
14
+ __tostring = function()
15
+ return "MiddlewareProvider"
16
+ end,
17
+ })
18
+ MiddlewareProvider.__index = MiddlewareProvider
19
+ function MiddlewareProvider.new(...)
20
+ local self = setmetatable({}, MiddlewareProvider)
21
+ return self:constructor(...) or self
22
+ end
23
+ function MiddlewareProvider:constructor()
24
+ self.clientMiddlewares = {}
25
+ self.serverMiddlewares = {}
26
+ end
27
+ function MiddlewareProvider:getClient(message)
28
+ if self.clientMiddlewares[message] == nil then
29
+ self.clientMiddlewares[message] = {}
30
+ end
31
+ return self.clientMiddlewares[message]
32
+ end
33
+ function MiddlewareProvider:getServer(message)
34
+ if self.serverMiddlewares[message] == nil then
35
+ self.serverMiddlewares[message] = {}
36
+ end
37
+ return self.serverMiddlewares[message]
38
+ end
39
+ function MiddlewareProvider:useClient(message, middlewares, order)
40
+ local messageMiddleware = self:getClient(message)
41
+ local _middlewares = middlewares
42
+ if typeof(_middlewares) == "function" then
43
+ local _condition = order
44
+ if _condition == nil then
45
+ _condition = #messageMiddleware - 1
46
+ end
47
+ local _middlewares_1 = middlewares
48
+ table.insert(messageMiddleware, _condition + 1, _middlewares_1)
49
+ else
50
+ for _, middleware in middlewares do
51
+ self:useClient(message, middleware)
52
+ end
53
+ end
54
+ return self
55
+ end
56
+ function MiddlewareProvider:useServer(message, middlewares, order)
57
+ local messageMiddleware = self:getServer(message)
58
+ local _middlewares = middlewares
59
+ if typeof(_middlewares) == "function" then
60
+ local _condition = order
61
+ if _condition == nil then
62
+ _condition = #messageMiddleware - 1
63
+ end
64
+ local _middlewares_1 = middlewares
65
+ table.insert(messageMiddleware, _condition + 1, _middlewares_1)
66
+ else
67
+ for _, middleware in middlewares do
68
+ self:useServer(message, middleware)
69
+ end
70
+ end
71
+ return self
72
+ end
73
+ end
74
+ return {
75
+ DropRequest = DropRequest,
76
+ MiddlewareProvider = MiddlewareProvider,
77
+ }
@@ -0,0 +1,19 @@
1
+ import type { Networking } from "@flamework/networking";
2
+ export type MessageCallback<T = unknown> = ServerMessageCallback<T> | ClientMessageCallback<T>;
3
+ export type ClientMessageCallback<T = unknown> = (data: T) => void;
4
+ export type ServerMessageCallback<T = unknown> = (player: Player, data: T) => void;
5
+ export type BaseMessage = number | string | symbol;
6
+ export interface SerializedPacket {
7
+ readonly buffer: buffer;
8
+ readonly blobs: defined[];
9
+ }
10
+ export type MessageEvent = (kind: BaseMessage, packet?: SerializedPacket) => void;
11
+ export type UnreliableMessageEvent = Networking.Unreliable<MessageEvent>;
12
+ export interface ServerEvents {
13
+ sendServerMessage: MessageEvent;
14
+ sendUnreliableServerMessage: UnreliableMessageEvent;
15
+ }
16
+ export interface ClientEvents {
17
+ sendClientMessage: MessageEvent;
18
+ sendUnreliableClientMessage: UnreliableMessageEvent;
19
+ }
@@ -0,0 +1,2 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ return nil
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rbxts/tether",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "main": "out/init.lua",
5
5
  "scripts": {
6
6
  "build": "rbxtsc",
@@ -37,6 +37,7 @@
37
37
  "dependencies": {
38
38
  "@flamework/core": "^1.2.3",
39
39
  "@flamework/networking": "^1.2.3",
40
+ "@rbxts/destroyable": "^1.0.1",
40
41
  "@rbxts/flamework-binary-serializer": "^0.6.0",
41
42
  "@rbxts/services": "^1.5.5"
42
43
  }