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

2.0.0-rc1

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. As of right now, there is no written documentation. However I’ll give a brief summary of the critical functions that have been added.

It is available under wally as 2.0.0-rc1, and it is on the github repository.


Declare

Declare is the solution to a major design flaw with BridgeNet- since BridgeNet’s references are completely decentralized, you often need to do lengthy things like so:

local BridgeA = BridgeNet.CreateBridge("BridgeA")
local BridgeB = BridgeNet.CreateBridge("BridgeB")
local BridgeC = BridgeNet.CreateBridge("BridgeC")

There’s also another problem with this- you can’t tell if it’s getting or creating the remote. It’s not clean, it’s pretty messy. You also have the problem of things like middleware, replication rate, all that. My solution to this was Declare:

local Bridges = BridgeNet.Declare({
  RemoteA = BridgeNet.Bridge({
    Middleware = {},
  }),
  RemoteCategory = {
    RemoteB = BridgeNet.Bridge(),
    RemoteC = BridgeNet.Bridge({
      Middleware = {},
   }),
  }
})

The intended way to use Declare is to put all of your remotes in one ModuleScript, and then require the modulescript to access your BridgeObjects. This is cool, but it also kind of forces you into a structure- that’s why I’m leaving .CreateBridge untouched. In fact, Declare internally uses .CreateBridge.

Identifiers

The same exact issue with .CreateBridge showed up with identifier strings too, so I pretty much did the same thing. One module for your identifiers maybe, or maybe use the function multiple times across scripts to access your identifier strings- it’s open ended.


  • Removed rateManager entirely
  • Removed .CreateIdentifiersFromDictionary()
  • Removed .CreateBridgesFromDictionary()
  • Removed .WhatIsThis()
  • Removed .WaitForBridge()
  • Removed PrintRemotes symbol- it was useless.
  • Added GetCompressedIdentifier
  • Added .Declare()
  • Added .Identifiers()
  • Added .GetCompressed()
  • Added .GetIdentifier()
  • Each BridgeObject now has a variable rate it sends information at. This is by default 60.
  • A lot of functions are now modules that return a function
  • Repeat loops are now while loops
  • Renamed serdeLayer to SerdesLayer
  • Optimizations
  • Symbols are now loaded in via a module
  • Added hot reloading support(?)
  • Rewrote test code

Changes to be done

  • Remove receive queueing(?)
  • Typings should use never and unknown types
  • Add :SetReplicationRate(). There should be a partial implementation already there
  • Finish polishing and testing, then do the full release.
4 Likes

This is a great update that I would definitely play around with.

Declare sounds pretty cool, but perhaps something like createRoot or createTree would be a better fit? This makes sense in my eyes since it perfectly matches the intended usage.


If you don’t mind, can you mention these new optimizations, perhaps in a PM if clogging the thread is a concern to you?

1 Like

I could definitely go with createTree or something similar, definitely more self descriptive. Looking back, I agree Declare probably wasn’t the best name. I picked it because in my head I thought “youd declare bridges in a module somewhere else”, and then just toon declare from that.

As per the optimizations - table manipulation is more efficient because the tables are constructed with the elements inside, instead of inserting after construction. Originally this was due to my plans on using table.create, however it didn’t prove viable and I forgot to switch back. Considering how much table manipulation BridgeNet does, I think this might be a pretty considerable speedup.

1 Like

This probably makes sense. You can stick with it if you wanna go with the “declarative programming” terminology or something like that, but createTree definitely fits the whole design of the library.

As far as I know, table.create is only useful if you are planning to fill it up with some unknown elements in the future but putting all the elements on the construction is definitely optimized more (I remember it is mentioned in the luau official website).

1 Like

I’ve got a security question.

I want to change my game’s hit detection to client sided, and use bridge net to deal the damage on server. Now I know that exploiters can easily fire remote events. Can they also fire Bridge Net event, since it’s not an actual instance?

BridgeNet is fundamentally a wrapper for remote events, all the rules applied on remotes are still applied on BridgeNet.

The real solution for this is to validate your client’s requests.

2 Likes

Can you also make a wally package for this?

1 Like

There should be a Wally package under the version of ffrostflame/bridgenet@2.0.0-rc1, or the latest stable version 1.9.9

2 Likes

Hi,

I followed the documents but can’t get to work, I am getting the following errors.

Infinite yield possible on ‘ReplicatedStorage:WaitForChild(“AutoSerde”)’
Infinite yield possible on ‘ReplicatedStorage:WaitForChild(“RemoteEvent”)’

Thanks

You need to run BridgeNet.Start() with the required parameters- doesn’t look like you’re doing that.

I think this should have some sort of default middleware functions because args that i send from the client are recieved as nil on server because of this

for _ = 1, timesConnected do
	if obj._middlewareFunctions == nil then

		callback(v.plr, table.unpack(v.args))
	else
		task.spawn(function()
			print(v.args)

			local result

			print(obj._middlewareFunctions)

			for _, func in obj._middlewareFunctions do
				if result then
					local potential = {func(table.unpack(result))}
					if #potential == 0 then
						continue
					end
					result = potential
				else
					result = {func(table.unpack(v.args))}
					print(result)
				end
			end

			callback(v.plr, result)
		end)
	end
end

now, self._middlewareFunctions is not nil but just an empty table, this will cause the first if condition to not run because it’s not nil, but still errors because there’s nothing in the table.

I suppose this can get added to the next 2.0 release, but I’m not sure why you’d set the middleware table and then not put anything in it. Dynamic middleware doesn’t seem like that good of an idea to me :thinking:

The thing is, I didn’t. I didn’t modify any code except for debugging purposes (mostly print and warn functions). Well I could just fix this by doing the code below, but I wanted to tell you just in case.

self._middlewareFunctions = middlewareFunctions or nil

-- some other line
function ServerBridge:AddMiddleware(func: (...any) -> nil)
	if self._middlewareFunctions == nil then
		self._middlewareFunctions = {}
	end
	
	table.insert(self._middlewareFunctions, func)
end

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?