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

This actually showcases a flaw with BridgeNet I’ll get on fixing when available.

As of right now there’s no way to tell when BridgeNet is started. This means you’re kinda forced to use single-script architecture which is something I encourage you to research, but I’m not going to assume everyone who uses BridgeNet will do this.

So, I think what I’m going to do is make functions such as CreateBridge yield until BridgeNet starts. However, it’s possible that it plays nicely without starting because starting BridgeNet connects to heartbeat and all that. I’m still going to make this functions yield until start because I don’t want completely unexpected behavior in my module :sweat_smile:

the code snippet you asked for:
Client

local Object = BridgeNet.CreateBridge("Test")

Object:Connect(function(arg1, arg2, arg3)
	print(arg1)
end)

while task.wait(1) do
	Object:Fire("Hello", "world")
end

Server

local Object = BridgeNet.CreateBridge("Test")

Object:Connect(function(plr, arg1, arg2)
	print(plr, arg1)
end)

while task.wait(1) do
	Object:FireTo(game.Players:GetPlayers()[1], "Received: Fire")
end

To answer your second question, the bridges are just connected by string, and you need to call CreateBridge separately on the client and the server. However, if you need to index a bridge that’s already created, you can do .FromBridge(). As of right now, this will return nil if it doesn’t exist, which means I could probably add in a .WaitForBridge() function to make this process easier.


I think one thing I could do is use symbols instead of text indexes, so it would be like

BridgeNet.Start({
[BridgeNet.DefaultReceive] = 60,
[BridgeNet.DefaultSend] = 60,
})

You’re right, plain text keys are easy to forget and get confused (it’s already happened!), but the reason I don’t want to use the order of arguments is because of how difficult it is to change. Say I want to remove the default send and receive options in a year, what happens then? Backwards compatibility breaks.

And thank you! Every bit of support means a lot to me.

4 Likes

An enum thing is also fine. Thank you for this! will there ever be roblox-ts support too?

1 Like

Thank You!! One more follow up question.

Assuming I use 1 script architecture, I still need to use 1 server script and 1 client script. Do I need to call BridgeNet.Start both on Server and on Client, or just call it only on the server?

I have it planned for the future, but I wouldn’t count on it.


You do need to call it on both the server and client.

apologize for bad formatting, on mobile lol

2 Likes

0.4.3-alpha

Get it here.

  • Connections now spawn a thread, making them yield-safe and error-proof.
  • Added .WaitForBridge()
  • Added Roact’s Symbol class- not used for now, will be used for .Start configuration in the future.
  • .CreateBridge() now has the same functionality of .FromBridge()
  • Server now checks for the BridgeObject to exist before trying to run connections. If it doesn’t exist, nothing happens.

Friendly reminder, you should be using the latest version of BridgeNet at all times. Not doing so can cause issues with your game / result in errors and buggy behavior. For example, before this update, any error in connections would halt the whole process and prevent other connections on the object from running. It was also not yield-safe. This is fixed now.

4 Likes

I don’t know how you achieved this, but this is amazing. I’m doing the same thing I explained above, firing bridge event from client, and on the server changing waist rotation.

I wanted to test the difference myself, so first I fired 100 remote events without using bridge. My ping was 3k+.

Then I implemented bridge and did the absolute same thing. Literally nothing in the code is changed, except instead of remote events I am using Bridge Events. Firing 100 in a single frame. This is the result:

To clarify, even on an empty baseplate I have 100 ping because I live far from the servers, so firing 100 Bridge Events every frame has basically same toll on performance as an empty baseplate.

TLDR: Magnificent module providing incredible network optimization.
I definitely recommend everyone using this module, as it will allow you to implement much more things in your game without causing massive lags.

@ffrostfall I recommend you create a way to donate to this module voluntarily, I would gladly donate.

1 question: “CreateBridge() now has the same functionality of .FromBridge()”

If I understand correctly, this means that if a bridge is already created, it will get the already created bridge, instead of creating a new one with same string, right? Or should I implement my own logic for that?

4 Likes

Thank you so so much for the feedback! Appreciate the praise a lot, however I do have a tip for you- instead of sending it constantly per heartbeat/whatever, you can cache the value to detect if it’s the same. That way you’re not firing it constantly.

If you’re firing anything else like a string to say “this is rotation”, do it with BridgeNet.CreateIdentifier. It was made specifically to compress strings, and it’ll further optimize your networking.

As per your question, yes. If you create a BridgeObject with .CreateBridge and one already exists, it’ll return that.

This is because it doesn’t make sense to have multiple objects for a single remote. You do not need to implement your own object.

2 Likes

1.4.3-beta

Get it here.

  • Removed .FromBridge, use .WaitForBridge or .CreateBridge (createbridge returns the existing bridge object if it exists)
  • Configuration object now uses symbols instead of regular strings
  • Added global custom logging support. UNSTABLE, DONT USE IN PRODUCTION
  • Changed some loops to use ipairs instead of pairs
  • Used table.clear instead of tbl = {} for better efficiency
  • Fixed Disconnect
  • General optimizations (thank you @Baileyeatspizza)
  • Fixed ClientBridge breaking if the client’s bridge was created before the server created the bridge (thank you evanchan0819)
  • Fixed client-to-server communication only sending the first argument

Upcoming features

  • roblox-ts port
  • Re-adding middleware
  • Re-adding rate limiting
  • Runtime typechecking for RemoteEvents
5 Likes

Just a thought, I’ve got no idea how this works but could you make sending the data from the server parallel? It could probably speed it up on the server.

1 Like

I’m not sure how I’d do that. It’s a single table that produces a single table

1 Like

Server to client seems to be working for me, client to server doesn’t seem to be working for me. Is this a bug or am I doing something wrong?

Server

local MineBlock = BridgeNet.CreateBridge("MineBlock")

BridgeNet.Start({
	[BridgeNet.DefaultReceive] = 60,
	[BridgeNet.DefaultSend] = 60,
})

MineBlock:Connect(function(Player, Block)
	print('fired')
end)

Client

local MineBlock = BridgeNet.CreateBridge("MineBlock")
local UserInputService = game:GetService("UserInputService")

BridgeNet.Start({
	[BridgeNet.DefaultReceive] = 60,
	[BridgeNet.DefaultSend] = 60,
})

UserInputService.InputBegan:Connect(function(Input, GameProcessed)
	if GameProcessed then return; end
	if Input.UserInputType == Enum.UserInputType.MouseButton1 or Input.UserInputType == Enum.UserInputType.Touch then
		local Target = RbxMouse:GetTarget()
		if Target.Instance then
			MineBlock:Fire(Target.Instance)
		end
	end
end)

No errors whatsoever, I have print lines in my actual code for debugging and they all print fine. Is there something I missed?

1 Like

I tried testing but it doesn’t work for me nor print anything on the server.
Server:

local BridgeNet = require(game.ReplicatedStorage.BridgeNet)

local Remote1 = BridgeNet.CreateBridge("RemoteEvent1")

BridgeNet.Start({
	[BridgeNet.DefaultReceive] = 60,
	[BridgeNet.DefaultSend] = 60,
})

Remote1:Connect(function(Player, ...)
	print(Player, ...)
end)

Client:

local BridgeNet = require(game.ReplicatedStorage.BridgeNet)

local Remote1 = BridgeNet.CreateBridge("RemoteEvent1")

script.Parent.MouseButton1Click:Connect(function()
	Remote1:Fire("Hello", "this is a test.")
end)
1 Like

You need to start it on the client too

1 Like

Can you try putting your Bridge objects below .Start? This shouldn’t affect anything in theory but idk.

1 Like

I haven’t got it to work for me yet, and I’m very confused on what I did wrong, but nice module anyways!

Am I doing something wrong? I’m trying to see how it works, before I implement it fully in my game. This will work great with my big game, and save bytes.

Server:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local BridgeNet = require(ReplicatedStorage.BridgeNet)

BridgeNet.Start({
	send_default_rate = 60,
	receive_default_rate = 60,
})

local Bridge = BridgeNet.CreateBridge("Testing")
Bridge:Fire("hello", "world")

Client:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local BridgeNet = require(ReplicatedStorage.BridgeNet)

BridgeNet.Start({
	send_default_rate = 60,
	receive_default_rate = 60,
})


BridgeNet.CreateBridge("Testing"):Connect(function()
	print("s")
end)
1 Like

I got it to work finally after experimenting with a couple of things, and the documentation isn’t really clear on how you Fire stuff and retrieve stuff from server to client and client to server, but overall it’s a good module.

1 Like

Apparently that fixed it? Kinda unsure. Whatever the case may be it works now.

1 Like

How did you do it? Can you show me your test code.

1 Like

I’m still experimenting and unsure how to create a server-to-client bridge and via verse.

1 Like

This is Client to Server that I figured out, but I don’t know how to do the complete opposite because the functions are not the same as Client to Server.

Client:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local BridgeNet = require(ReplicatedStorage.BridgeNet)

BridgeNet.Start({
	send_default_rate = 60,
	receive_default_rate = 60,
})


BridgeNet.CreateBridge("Something"):Fire("something")

Server:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local BridgeNet = require(ReplicatedStorage.BridgeNet)

BridgeNet.Start({
	send_default_rate = 60,
	receive_default_rate = 60,
})

BridgeNet.CreateBridge("Something"):Connect(function(player, test)
	print(player.Name, test)
end)
1 Like