A simple declarative networking module

This module allows you to create remote events and remote functions in code rather than by hand. Many people prefer doing things declaratively, hence why things like declarative UI exists. This does a similar thing but its for Networking rather than UI. I’m not going to go over every little thing about this so by reading this I’m assuming you have learned the basics of Remote Events, Remote Functions and ModuleScripts, or just a basic understanding of everything overall.

There are 2 modules.

The Server module:

local module = {}

local remotes

local function waitForRemotes()
	while not remotes do
		task.wait()
	end
end

local function makeRemote(remoteType, name)
	local remote = Instance.new(remoteType)
	remote.Name = name
	remote.Parent = remotes

	return remote
end

function module.RegisterRemoteEvent(name: string)
	waitForRemotes()

	local existingRemote = remotes:FindFirstChild(name)

	if existingRemote then
		error("Name Collision")
	end

	makeRemote("RemoteEvent", name)
end

function module.RegisterRemoteFunction(name: string)
	waitForRemotes()

	local existingRemote = remotes:FindFirstChild(name)

	if existingRemote then
		error("Name Collision")
	end

	makeRemote("RemoteFunction", name)
end

function module.Listen(remote, callback)
	remote = remotes:FindFirstChild(remote)

	if remote:IsA("RemoteEvent") then
		return remote.OnServerEvent:Connect(callback)
	elseif remote:IsA("RemoteFunction") then
		remote.OnServerInvoke = callback
	end
end

function module.FireAllClients(remote, ...)
	remote = remotes:FindFirstChild(remote)

	remote:FireAllClients(...)
end

function module.FireClient(remote, ...)
	remote = remotes:FindFirstChild(remote)

	remote:FireClient(...)
end

remotes = Instance.new("Folder")
remotes.Name = "Remotes"
remotes.Parent = game:GetService("ReplicatedStorage")

return module

And the client module:

local module = {}

local remotes = game:GetService("ReplicatedStorage"):WaitForChild("Remotes")

function module.Listen(remote, callback)
	remote = remotes:WaitForChild(remote)

	return remote.OnClientEvent:Connect(callback)
end

function module.FireServer(remote, ...)
	remote = remotes:WaitForChild(remote)

	remote:FireServer(...)
end

function module.InvokeServer(remote, ...)
	remote = remotes:WaitForChild(remote)
	
	return remote:InvokeServer(...)
end

return module

You may notice I left out support for InvokeClient, this is due to the fact that using InvokeClient is a bad practice due to the fact an exploiter can stop their client from returning the call leading the server to infinitely wait for a response.

What it does support however is:

  • Fire Server
  • Invoke Server
  • Fire Client
  • Fire All Clients
  • And ofc creating remotes with RegisterRemoteFunction and RegisterRemoteEvent

You can pass in additional arguments to these functions that will then get replicated to whoever they’re getting fired to:

  • Fire Server
  • Invoke Server
  • Fire Client
  • Fire All Clients

Here is an example of using these modules:

Server:

local networkServer = require(path_to_server_module)

networkServer.RegisterRemoteEvent("test")
networkServer.Listen("test", function(player)
    print(`Player {player.Name} fired test remote`)
end)

Client:

local networkClient = require(path_to_client_module)

networkClient.FireServer("test")

Lets go over what just happened. The server made a remote event called “test”, and called .Listen and passed in the name of the remote to listen to when it gets fired. The client then called .FireServer and passed in the name of the remote which then made the server print.

Thanks for reading this, feel free to use these modules ofc. If you have any questions feel free to ask even though I never use the devforum, maybe I’ll see them or someone smarter than me will respond. :slight_smile:

9 Likes

Thank you breakon. Very cool!
Will definitely be using this :slightly_smiling_face:

1 Like

I’m really struggling to see why so many people hate just creating a new remote event instance with a passion.

2 Likes

It’s not that people really hate it, it’s just a preference :man_shrugging:

1 Like