· 2 years ago · Feb 10, 2023, 05:50 AM
1--[[
2 ,,╓╓╥╗╗@@@╣╢
3 ,²╓╓╥╗@@@╣╣╢▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒U
4 ,,╓╓╥m╗@@@╣╢▒▒▒▒▒▒▒▒▒Ñ╜` "╙╣▒▒▒▒▒▒▒▒╣
5 ,,╓╓╗╗╗@@╣╣╢▒▒▒▒▒▒╣╝╨╜╙"`║▒▒▒▒▒▒▒▒╢╜ `╣▒▒▒▒▒▒▒
6 ,╓╓╥╗@@@╣╢╢▒▒▒▒ÑÑ╝╝╨╜╨╝╝╣▒▒▒▒▒▒▒▒╢ ]▒▒▒▒▒▒▒╝ ,, ╙▒▒▒▒▒▒
7 ║▒▒▒▒▒"` `╝▒▒▒▒▒▒ ▒▒▒▒▒▒╝ ,@▒▒▒▒▒╣╗ ╓╗╣▒▒▒▒▒[
8 ▒▒▒▒▒U └▒▒▒▒▒ ║▒▒▒▒╣ ╢▒▒▒▒▒▒▒▒╢╗╣╣▒▒▒▒▒▒▒▒▒▒
9 ▒▒▒▒▒╣ ²╓╓╥╗╗╗╖ ]▒▒▒▒[ ]▒▒▒▒[ ║▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
10 ║▒▒▒▒▒ ▒▒▒▒▒▒▒▒╣ ]▒▒▒▒▒ ▒▒▒▒[ ║▒▒▒▒▒▒▒▒▒▒╢╢Ñ╝╨╜╙╙▒▒▒▒▒[
11 ]▒▒▒▒▒ ╢▒▒▒▒▒▒╢╜ ║▒▒▒▒▒ ╢▒▒▒[ ]▒▒▒▒▒[ ╢▒▒▒▒╢
12 ▒▒▒▒▒[ └╙"`` @▒▒▒▒▒▒[ ]▒▒▒╢ ▒▒▒▒▒╣ ║▒▒▒▒▒
13 ║▒▒▒▒╢ ²╙╣▒▒▒▒▒▒ ▒▒▒▒ ║▒▒▒▒▒ ,²╓ ]▒▒▒▒▒U
14 ]▒▒▒▒▒ ╣▒▒▒▒ ╢▒▒▒╣ ╢▒▒▒▒▒▒▒▒▒╜ ▒▒▒▒▒╣
15 ▒▒▒▒▒[ ]@╣╣▒▒▒▒╣╗ ▒▒▒▒[ ║▒▒▒▒╗ ╙╣▒▒▒▒▒Ñ` ║▒▒▒▒▒
16 ╢▒▒▒▒╢ ▒▒▒▒▒▒▒▒▒U ║▒▒▒╢ ]▒▒▒▒▒@ ]▒▒▒▒▒
17 ║▒▒▒▒▒ ╣▒▒▒▒▒▒▒╢ ║▒▒▒▒ ▒▒▒▒▒▒╣╖ ,[ ▒▒▒▒▒[
18 ▒▒▒▒▒U ║Ñ╝╨╜╙"² ▒▒▒▒▒ ║▒▒▒▒▒▒▒▒@╖, ,╥╣▒╢@@╣╣╢▒▒▒▒╢╢
19 ▒▒▒▒▒[ ╓╢▒▒▒▒▒[ ]▒▒▒▒▒▒▒▒▒▒▒▒▒╢╢╢▒╢ÑÑ╝╝╜╙""`
20 ║▒▒▒▒▒ ,╓@╢▒▒▒▒▒▒▒▒@╣╣╢▒▒▒▒╢Ñ╝╝╨╜╙""` ╓╗@@@╗╖
21 ]▒▒▒▒▒ ,,╓╓╗╗@@@╣▒▒▒▒▒▒╢ÑÑ╝╝╜╙"`` ,²╓ ╔@@@╣╣╢▒▒▒U ,╣▒Ñ╙"╙╢▒Ñ
22 ▒▒▒▒▒▒▒▒▒╢Ñ╝╝╨╜╙"`` ╥@@@╗ ]▒▒▒▒ ]▒▒╣"`` ]▒▒╗,
23 "`` ,╓╖╓, ]▒▒▒╣ ]▒▒▒▒╖ ║▒▒▒▒[ ▒▒▒ ,, ╙╣▒▒▒▒╣%╖
24 ,╣▒▒╢╣╣▒▒@ ╢▒▒╣▒╣ ▒▒╢╣▒╖ ▒▒[▒▒╢ ║▒▒▒▒▒▒▒r `"╙╣▒▒╕
25 ╣▒╣ ╙╜` ▒▒╢ ╣▒╣ ▒▒▒╙▒▒╕]▒▒ ║▒▒ ]▒▒[ ╓@ ▒▒╢
26 ║▒▒[ , ]▒▒[ ▒▒╣ ║▒▒ ╙▒▒@▒▒ ]▒▒L ▒▒╢ ,,╓╓ ╣▒▒╣@╣▒▒╣
27 ]▒▒[ ]╢▒▒▒▒[ ║▒▒╣╣╣╢▒▒╣ ]▒▒[ ╙▒▒▒[ ▒▒╣ ╢▒▒▒▒▒▒▒╢Ñ~ "╙"`
28 ╢▒▒ ]▒▒╢ ╢▒▒╙"``╙▒▒@ ▒▒╢ ╙▒╢` ╨╜╜ ``
29 ╣▒▒h╖╥@▒▒▒▒ j▒▒╣ ╙╜╙` `
30 `╙╝ÑÑ╝╙ "`
31
32
33 BIG Games rbx.lua Framework [2017] - [2021]
34 Written by Preston - preston@biggames.io
35 Developed with a keyboard and pixie dust.
36
37 -+-+-+- SPECIFICS -+-+-+-
38 _L.Network
39 ===========
40 Handles all the networking from client to server. Automatically compresses strings and tables to save bandwidth (theoretical)
41 Makes networking completely automatic and somehow also makes the syntax simplier. No fiddling with remotes required. B)
42
43 Event example:
44 CLIENT:
45 _L.Network.Fire("Bullet Fired", bullet.CFrame, bullet, {speed = 33, damage = 423})
46
47 SERVER:
48 _L.Network.Fired("Bullet Fired"):Connect(function(player, ...)
49 FireBullet(player, ...)
50 end)
51
52 Function example:
53 CLIENT:
54 local success = _L.Network.Invoke("Buy", "Super Soaker 5000", 2455)
55
56 SERVER:
57 _L.Network.Invoked("Buy").OnInvoke = function(player, itemName, price)
58 return (price <= 3000)
59 end
60
61 ===========
62 \\\ Subsititute for RemoteEvent:FireServer() / RemoteEvent:FireClient()
63 Network.Fire(
64 remoteName, <-- |REQ| Remote name
65 player, <-- |REQ| Player instance (SERVER ONLY)
66 ..., <-- Anything :)
67 )
68
69 \\\ Subsititute for RemoteFunction:InvokeClient() / RemoteFunction:InvokeServer()
70 Network.Invoke(
71 remoteName, <-- |REQ| Remote name
72 player, <-- |REQ| Player instance (SERVER ONLY)
73 ..., <-- Anything :)
74 )
75
76 \\\ Subsititute for RemoteEvent.OnClientEvent / RemoteEvent.OnServerEvent
77 Network.Fired(
78 remoteName, <-- |REQ| Remote name
79 )
80
81 \\\ Subsititute for RemoteFunction.OnClientInvoke / RemoteFunction.OnServerInvoke
82 Network.Invoked.OnInvoke(
83 remoteName, <-- |REQ| Remote name
84 )
85
86 \\\ Subsititute for RemoteEvent:FireAllClients()
87 Network.FireAll(
88 remoteName, <-- |REQ| Remote name
89 ..., <-- Anything :)
90 )
91--]]
92------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
93------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
94------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
95
96
97--------| Top |--------
98local Network = {}
99
100--------| Setting |--------
101local compressionEnabled = true --- disable if you want to sacrifice bandwidth for server performance. Disabling defaults to vanilla remote behavior.
102
103--------| Library |--------
104local _L; coroutine.wrap(function() _L = require(game.ReplicatedStorage:WaitForChild("Framework"):WaitForChild("Library")) end)()
105
106--------| Reference |--------
107local isServer = _L.Services.RunService:IsServer()
108local things = game.Workspace:WaitForChild("__THINGS")
109local remotes = things:WaitForChild("__REMOTES")
110local mainRemote = remotes:WaitForChild("MAIN")
111
112--------| Variables |--------
113local queue = {}
114local lastQueue = tick()
115local events = {}
116local listening = {}
117
118------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
119------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
120------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
121
122
123--- Fire
124Network.Fire = function(remoteName, arg, ...)
125 --- Variables
126 remoteName = string.lower(remoteName)
127
128 --- Get/create remote
129 local remote = GetRemote(remoteName)
130
131 --- Signal for visualization/tracking purposes on Debug (Client only)
132 if not isServer then
133 _L.Signal.Fire("CORE Network Fire", remoteName)
134 end
135
136 --- Create packet with arguments
137 if isServer then
138 --- Server
139 local packet = CreatePacket(...)
140 local player = arg
141
142 --- Check if player is past intro
143 if not player:FindFirstChild("__LOADED") then
144 return
145 end
146
147 --- Send
148 remote:FireClient(player, packet)
149
150 else
151 --- Client
152 local packet = CreatePacket(arg, ...)
153
154 --- Send
155 remote:FireServer(packet)
156 end
157end
158
159
160--- Fire (everyone)
161Network.FireAll = function(remoteName, ...)
162 --- Variables
163 remoteName = string.lower(remoteName)
164
165 --- Get/create remote
166 local remote = GetRemote(remoteName)
167
168 --- Create packet with arguments
169 local packet = CreatePacket(...)
170
171 --- Get a list of players loaded past intro (that we can fire event on)
172 local players = game.Players:GetPlayers()
173 local playersToSend = {}
174 --
175 for _, player in ipairs(players) do
176 if player:FindFirstChild("__LOADED") then
177 table.insert(playersToSend, player)
178 end
179 end
180
181 --- Send
182 if #playersToSend >= #players then
183 --- Can use optimized FireAllClients
184 remote:FireAllClients(packet)
185
186 else
187 --- Some players are in intro, so we gotta fire each manually
188 for _, player in ipairs(playersToSend) do
189 coroutine.wrap(function()
190 remote:FireClient(player, packet)
191 end)()
192 end
193 end
194end
195
196
197--- Invoke
198Network.Invoke = function(remoteName, arg, ...)
199 --- Variables
200 remoteName = string.lower(remoteName)
201
202 --- Get/create remote
203 local remote = GetRemote(remoteName, true)
204
205 --- Signal for visualization/tracking purposes on Debug (Client only)
206 if not isServer then
207 _L.Signal.Fire("CORE Network Invoke", remoteName)
208 end
209
210 --- Create packet with arguments
211 if isServer then
212 --- Server
213 local packet = CreatePacket(...)
214 local player = arg
215
216 --- Check if player is past intro
217 if not player:FindFirstChild("__LOADED") then
218 return
219 end
220
221 --- Return decoded packet
222 return DecodePacket(remote:InvokeClient(arg, packet))
223
224 else
225 --- Client
226 local packet = CreatePacket(arg, ...)
227
228 --- Return decoded packet
229 return DecodePacket(remote:InvokeServer(packet))
230 end
231end
232
233
234--- On Fire
235Network.Fired = function(remoteName)
236 --- Variables
237 remoteName = string.lower(remoteName)
238
239 --- Get/create bindableEvent
240 local event = GetEvent(remoteName)
241
242 --
243 return event.Event
244end
245
246
247--- On Invoke
248Network.Invoked = function(remoteName)
249 --- Variables
250 remoteName = string.lower(remoteName)
251
252 --- Get/create bindableFunction
253 local event = GetEvent(remoteName, true)
254
255 --
256 return event
257end
258
259
260--- Packet recieved from server/client
261Network.Recieve = function(packetType, ...)
262 --- Variables
263 local data = {...}
264
265 --- Direct packet info based on packetType
266 if packetType == "a" then
267 --- SERVER | Create remote event
268 GetRemote(unpack(data))
269
270 elseif packetType == "b" then
271 --- SERVER | Create remote function
272 GetRemote(unpack(data), true)
273
274 elseif packetType == "c" then
275 --- CLIENT | Recieved event
276 local remoteName, packet = unpack(data)
277 local event = GetEvent(remoteName)
278 event:Fire(DecodePacket(packet))
279
280 elseif packetType == "d" then
281 --- CLIENT | Recieved invoke
282 local remoteName, packet = unpack(data)
283 local event = GetEvent(remoteName, true)
284 return CreatePacket(event:Invoke(DecodePacket(packet)))
285
286 elseif packetType == "e" then
287 --- SERVER | Recieved event
288 local remoteName, player, packet = unpack(data)
289 local event = GetEvent(remoteName)
290 event:Fire(player, DecodePacket(packet))
291
292 elseif packetType == "f" then
293 --- SERVER | Recieved invoke
294 local remoteName, player, packet = unpack(data)
295 local event = GetEvent(remoteName, true)
296 return CreatePacket(event:Invoke(player, DecodePacket(packet)))
297
298 else
299 --- packetType returned doesn't exist :(
300 _L.Print("_L.Network.Recieve | Corrupted packet (packet type recieved as [bold]" .. packetType .. "[/bold])", true)
301 end
302end
303
304
305----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
306----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
307
308
309--- Turn series of arguments into compressed 'packet'
310function CreatePacket(...)
311 --- Variables
312 local newPacket = {{}, {}}
313 local newPacketData = newPacket[1]
314 local newPacketIndex = newPacket[2]
315
316 --- Return if compression is disabled
317 if not compressionEnabled then
318 return ...
319 end
320
321 --- Straight up magic (lets us iterate through nil)
322 local packet, _n = {...}, select("#", ...)
323
324 --- Iterate through all arguments
325 for i = 1, _n do
326 local data = packet[i]
327
328 --- Process non-nil arguments
329 if data ~= nil then
330 --- Eligible for compression?
331 if (type(data) == "table" and (not _L.Functions.HasUserdata(data))) or (type(data) == "string" and utf8.len(data) >= 10) then
332 --- Vars
333 local wasTable = (type(data) == "table")
334 local compressed, success, convertedToJSON
335
336 --- Attempt to compress
337 success = pcall(function()
338 compressed, convertedToJSON = _L.Functions.Compress.Encode(data)
339 end)
340
341 --- Successfully compressed?
342 if success and compressed and (not convertedToJSON) and (compressed ~= data) then
343 --- Add!
344 newPacketData[i] = compressed
345 newPacketIndex[i] = (wasTable and 1 or true)
346
347 else
348 --- Failed to compress. Add!
349 newPacketData[i] = data
350 newPacketIndex[i] = false
351 end
352
353 else
354 --- Add!
355 newPacketData[i] = data
356 newPacketIndex[i] = false
357 end
358
359 else
360 --- Process nil arguments
361 data = false
362 newPacketData[i] = data
363 newPacketIndex[i] = 2
364 end
365 end
366
367 return newPacket
368end
369
370
371--- Decode previously encoded packet into a series of readable arguments
372function DecodePacket(packet)
373 --- Variables
374 local newData = {}
375
376 --- Return if compression is disabled
377 if not compressionEnabled then
378 return unpack(packet)
379 end
380
381 --- Seperate packet
382 local packetData = packet[1]
383 local packetIndex = packet[2]
384 local packetLength = 0
385
386 --- Iterate through packet contents
387 for i, isEncoded in pairs(packetIndex) do
388 --- Packet data
389 local data = packetData[i]
390
391 --- Packet content compressed?
392 if isEncoded then
393 --- Is it an encoded table/string?
394 if isEncoded ~= 2 then
395 --- Vars
396 local wasTable = (isEncoded == 1)
397 local decoded, success
398
399 --- Attempt to uncompress packet
400 success = pcall(function()
401 decoded = _L.Functions.Compress.Decode(data)
402 end)
403
404 --- Successfully uncompressed packet?
405 if success and decoded then
406 --- If table, decode from JSON
407 if wasTable then
408 decoded = _L.Services.HttpService:JSONDecode(decoded)
409 end
410
411 --- Add!
412 newData[i] = decoded
413 --table.insert(newData, decoded)
414
415 else
416 --- Failed to uncompress packet content
417 _L.Print("Failed to decode packet argument [bold](" .. data .. ")[/bold]", true)
418 end
419
420 else
421 --- Add nil argument
422 newData[i] = nil
423 end
424
425 else
426 --- Add!
427 newData[i] = data
428 --table.insert(newData, data)
429 end
430
431 --- Update packet length
432 packetLength = i
433 end
434
435 --
436 return unpack(newData, 1, packetLength)
437end
438
439
440--- Get (or create) BindableEvent / BindableFunction
441function GetEvent(remoteName, isRemoteFunction)
442 --- Variables
443 remoteName = string.lower(remoteName)
444 local event = events[remoteName]
445
446 --- Check if event already exists
447 if not event then
448 --- Create event
449 event = Instance.new(isRemoteFunction and "BindableFunction" or "BindableEvent")
450 event.Name = remoteName
451 event.Parent = script
452 events[remoteName] = event
453 end
454
455 --
456 return event
457end
458
459
460--- Get (or create) RemtoeEvent / RemoteFunction
461function GetRemote(remoteName, isRemoteFunction)
462 --- Variables
463 remoteName = string.lower(remoteName)
464 local remote = remotes:FindFirstChild(remoteName)
465
466 --- Check if remote already exists
467 if not remote then
468 if isServer then
469 --- Server -> create remote
470 remote = Instance.new(isRemoteFunction and "RemoteFunction" or "RemoteEvent")
471 remote.Name = remoteName
472 remote.Parent = remotes
473
474 --- Track remote traffic
475 ListenRemote(remoteName, isRemoteFunction)
476 else
477 --- Client -> Tell server to create remote
478 mainRemote:FireServer((isRemoteFunction and "b" or "a"), remoteName)
479
480 --- Wait for remote to exist
481 repeat _L.Services.RunService.RenderStepped:Wait() until remotes:FindFirstChild(remoteName)
482 remote = remotes:FindFirstChild(remoteName)
483
484 --- Track remote traffic
485 ListenRemote(remoteName, isRemoteFunction)
486 end
487 end
488
489 return remote
490end
491
492
493--- Listen for data from remotes
494function ListenRemote(remoteName, isRemoteFunction)
495 --- Variables
496 remoteName = string.lower(remoteName)
497 local remote = GetRemote(remoteName, isRemoteFunction)
498
499 --- Check if remote is already being tracked
500 if not listening[remoteName] then
501 listening[remoteName] = true
502 else
503 return
504 end
505
506 --- Listen to remote
507 if isServer then
508 --- Server
509 if isRemoteFunction then
510 --- Remote function
511 function remote.OnServerInvoke(player, ...)
512 return Network.Recieve("f", remoteName, player, ...)
513 end
514
515 else
516 --- Remote event
517 remote.OnServerEvent:Connect(function(player, ...)
518 Network.Recieve("e", remoteName, player, ...)
519 end)
520 end
521
522 else
523 --- Client
524 if isRemoteFunction then
525 --- Remote function
526 function remote.OnClientInvoke(...)
527 --- Signal for visualization/tracking purposes on Debug (Client only)
528 if not isServer then
529 _L.Signal.Fire("CORE Network Invoked", remoteName)
530 end
531
532 --
533 return Network.Recieve("d", remoteName, ...)
534 end
535
536 else
537 --- Remote event
538 remote.OnClientEvent:Connect(function(...)
539 --- Signal for visualization/tracking purposes on Debug (Client only)
540 if not isServer then
541 _L.Signal.Fire("CORE Network Fired", remoteName)
542 end
543
544 --
545 Network.Recieve("c", remoteName, ...)
546 end)
547 end
548 end
549end
550
551
552--- Initailize client
553function ClientInit()
554 --- Scan all remotes
555 for _, remote in ipairs(remotes:GetChildren()) do
556 if remote.Name ~= "MAIN" then
557 --- Listen for traffic
558 ListenRemote(remote.Name, remote:IsA("RemoteFunction"))
559 end
560 end
561end
562
563
564--- First time
565if isServer then
566 --- If server, listen for any traffic from MAIN remote
567 mainRemote.OnServerEvent:Connect(function(player, packetType, remoteName, ...)
568 Network.Recieve(packetType, remoteName, ...)
569 end)
570
571else
572 --- If client, initailize
573 coroutine.wrap(function()
574 wait()
575 ClientInit()
576 end)()
577end
578
579
580--- Listen in on newly added remotes
581remotes.ChildAdded:Connect(function(remote)
582 if remote:IsA("RemoteEvent") or remote:IsA("RemoteFunction") then
583 ListenRemote(remote.Name, remote:IsA("RemoteFunction"))
584 end
585end)
586
587
588------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
589------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
590------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
591
592return Network