BridgeNet | Insanely optimized, easy-to-use networking library full of utilities, now with roblox-ts! | v1.9.9-beta

That would be a really good library, but there’s one question I’d like to ask. Would there be any way to introduce this in a Rojo workflow? (Visual Studio Code)

1 Like

A wally package for it exists, if you are lookijg for roblox-ts package that exists too

1 Like

Will there be an invoke client?

Quick polls

One thing that helps me a lot developing BridgeNet is how battle-tested it is and how many people are using it. Factors like these decide how I want to develop BridgeNet, where I should improve BridgeNet, and overall how safe the module is to use.

Do you use BridgeNet?
  • Yes
  • No

0 voters

If you don’t use BridgeNet, please message me (on the devforum) what features/design BridgeNet is lacking in order for you to use it.


Have you used the receive/send network logging feature?
  • I have used it / it is useful to me
  • I have never used it
  • I don’t know what that is (lacking sufficient documentation)

0 voters


Have you used the middleware feature?
  • Yes
  • No
  • I don’t know what that is (lacking sufficient documentation)

0 voters


Do you use .CreateBridgesInDictionary()?
  • Yes
  • No

0 voters


Are you okay with the way that bridges / identifiers are defined/created right now?
  • Yes, I’m okay with it
  • No, I would like another way.

0 voters


(Please direct message me for these next questions)

What features (apart from basic :Fire(), :FireTo()) do you use in BridgeNet the most?
What features do you wish were in BridgeNet?
What issues do you have with networking code that BridgeNet doesn’t fix?


2.0.0-rc2

This is a release candidate for 2.0. It is unfinished, unstable, and not ready for production usage- that being said, it would mean a lot to me if anyone could help poke around and help find some bugs / issues. It is only available on wally at the moment under 2.0.0-rc2

  • Middleware now is defaulted off if there’s nothing in the table
  • Some small improvements
  • Renamed Declare to CreateBridgeTree
  • Exposed the typings Bridge, ClientBridge and ServerBridge to the user.
  • Added Bridge:SetReplicationRate()
  • Started on a better way of doing releases for wally and non-wally. Kinda experimenting right now!

Again- 2.0 is not stable at the moment.

1 Like

No, as invoking the client is an antipattern. RemoteFunctions: Don't use InvokeClient - YouTube

2.0.0-rc3

This is likely going to be pushed out as 2.0.0- not much left I want to do, this leaves the library in a pretty finished state. After intensive testing & 2.0.0 released, I may consider labeling the library as production-ready.

Roblox marketplace
Github release
ffrostflame/bridgenet@2.0.0-rc3 on Wally

  • Multiple :Fire()s can be sent in the same frame
  • Performance improvements
  • Bugfixes w/ SerdesLayer & replication
  • Added more test cases- 2.0.0 should be usable and more stable.
  • Fixed invokes
3 Likes

Is there any setup tutorials anywhere?

I see you removed WaitForBridge. What can I use instead? This breaks a ton of code. I wrote around that function existing.

1 Like

You should theoretically be able to use CreateBridge.

Hello @ffrostfall,

I am really impressed with everything you’ve done here - the github page, the documentation, etc. It’s all very well organized. However, something stood out to me that and is your ping measurements. I wondered: how can something that uses RemoteEvents to send over data be faster than the RemoteEvents themselves? It’s somewhat a paradox.

I had a theory, but to test it, I created an empty baseplate. I would measure ping by doing the following with both Roblox’s remote event API and your own API:

  1. Client stores tick in a variable and calls :FireServer with no parameters
  2. Server receives the event and does :FireClient immediately with no parameters
  3. Once the client receives the event, it subtracts the current tick from the stored one to get the elapsed time.

This is a very simple but rigorous method to test the ping of a specific network event. I tested 100 requests after waiting 5 seconds on the client for any more lag due to replication/first joining to settle. The environment is exactly the same. After putting it to the test, there were the results:

Results

image
BridgeNet consistently gets ~60ms, while roblox gets ~40ms. Although Roblox’s time is far more spread out, the overall difference between the two makes it negligent.

I do have an explanation for this and why it is different from your results:
I believe the way your system queues the results and sends them once per frame slowly allows the packet size to be smaller overall and allows roblox to more quickly send packets that are used to measure ping, however this is at the cost of the speed in which the server/client receives data. Although Roblox’s stats show the ping to be low, that is not a measurement of how long it takes for the data going through the BridgeNet to reach the server, its a measurement that ROBLOX takes internally. The actual time it takes for the server to receive the event, particularly when done multiple times per frame, takes tremendous amounts of time, (>1000ms).

Personally, I’m almost certain that ROBLOX already handles serialization of instances and compression on the backend for anything sent over the network. In fact, I’m certain most multiplayer games do; compression algorithms have been one of the most researched and developed algorithms I can think of. I totally agree with your last statement though. ROBLOX should have an alternative API for handling data that is loss-tolerable (UDP).

TL;DR: My main complaint is that your original post describes it as if there are no cons. Overall, this system is great if the delay between when the packet is sent and received isn’t important; however, this isn’t always the case (for example, when a player hits an enemy and the client requests the enemy to be damaged. Speed is very important here!)

I have attached the Google Sheets file with the data along with the place file with the test scripts of both ROBLOX and BridgeNet.
Testing game (90.4 KB)
Spreadsheet download (35.1 KB)

4 Likes

I see. Could you update the documentation? It’s very out of date and I find it hard to keep up with the frequent breaking changes. Fortunately, I can find/replace all bridgenet calls to a wrapper module (which may be the done way anyway?)

1 Like

You’re fundamentally misinterpreting what BridgeNet does. “how can something that uses RemoteEvents to send over data be faster than the RemoteEvents themselves?” I never claim to be faster as in less ping, I claim to use less data, which is true.

“however this is at the cost of the speed in which the server/client receives data.” Actually, this is a bug with 2.0.0. I don’t think you’ll see this sort of behavior in earlier versions- and if you do, please report it. 2.0.0-rc3 is short for 2.0.0 release-candidate 3, which means that it’s an unstable version that isn’t ready for production usage. I introduced variable replication rates (replicating some remotes at 20hz), and in that I suppose I must have code that accidentally waits one more frame per remote call. I’ll definitely be investigating and fixing this.

“Personally, I’m almost certain that ROBLOX already handles serialization of instances and compression on the backend for anything sent over the network.” No, they don’t unfortunately.

Blank remote call: ~9 bytes

string (len 0): 2 bytes
string (len 1): 4 bytes
string (len 2): 8 bytes
string (len 3): 9 bytes
string (len 4): 10 bytes
string (len 5): 11 bytes
string (len 6): 12 bytes
string (len 8): 14 bytes
string (len 16): 22 bytes
string (len 32): 36 bytes

boolean: 2 bytes
number: 9 bytes

table (empty): 2 bytes
table (array with 4 numbers): 38 bytes

EnumItem: 4 bytes
Vector3: 13 bytes
CFrame (axis aligned): 14 bytes
CFrame (random rotation): 20 bytes

Source listed here: In-Depth Explanation of Roblox's RemoteEvents, Instance Replication, and Physics Replication (w/ sources!)

Your post does actually remind me of another critical flaw of Roblox though- we don’t have the ability to tap into when networksteps happen, and do behavior on those steps. Feature request is here, if you want to support it! RunService.NetworkStepped Event

I actually really appreciate this post because it brought attention to a bug in 2.0.0, which is an unstable version. Thank you! Oh, and one more thing: Any test you do is going to be fundamentally flawed, because network receive is done at the beginning of the frame, however code that reacts to it will not take effect until later stages, so the ping there is mostly irrelevant.

8 Likes

I’ll be updating the documentation when 2.0.0 is fully ready- as shown by the above post, it is not ready at the moment.

i’m scared of writing all the documentation though not gonna lie

1 Like

Even incremental updates would be nice! I have no idea how to use new bridgenet and can’t figure out how to modify my code to support it. I might just use regular network events until then.

this is a must have, i am definetely going to use this for my current and future projects.

2 Likes

I’m confused;
Roblox Remotes
Sent: 426.82 KB/s
Received: 541.99 KB/s

BridgeNet
Sent: 496.77 KB/s
Received 496.07 KB/s

With bridgenet you’ve received 0.70 KB/s less than you sent,
doesn’t that imply the amount of data sent wasn’t fully received? ie; data loss?

1 Like

It’s separate numbers afaik, it’s not passing the value through and then back again.
Also- there’s variance, you shouldn’t rely on exact numbers like that because Roblox has net code that gets logged in there too.

I really like this module but how can I invoke from server to client and why you haven’t add remote function APIs

1 Like

Invoking the client is an anti-pattern. It’s an exploit vulnerability, pretty much.

However, the client can invoke the server through InvokeServerAsync

1 Like

Hi,

When I run the test below it does not show the correct values and returns a table for Val1 and nil for Val2 and 3.

What am I doing wrong?

23:06:25.493 plr CanterCrow - Server - BNet-Client-To-Server-SS:7
23:06:25.493 Val1 table: 0x986ee00f34d665e4 - Server - BNet-Client-To-Server-SS:8
23:06:25.493 Val2 nil - Server - BNet-Client-To-Server-SS:9
23:06:25.493 Val3 nil - Server - BNet-Client-To-Server-SS:10

–Local Script
local BridgeNet = require(game.ReplicatedStorage.Modules.BridgeNet)
BridgeNet.Start({})
local ClientRemoteLS = BridgeNet.CreateBridge(“Remote”)
while true do
ClientRemoteLS:Fire(“Val1”, “Val2”, “Val3”)
task.wait(1)
end

–Remote Script
local BridgeNet = require(game.ReplicatedStorage.Modules.BridgeNet)
BridgeNet.Start({})
local ClientRemoteSS = BridgeNet.CreateBridge(“Remote”)
ClientRemoteSS:Connect(function(plr, Val1, Val2, Val3)
print("plr " … tostring(plr))
print("Val1 " … tostring(Val1))
print("Val2 " … tostring(Val2))
print("Val3 " … tostring(Val3))
end)

1 Like