Custom Remote Framework

Remote Framework

Description
This is a custom Remote Framework which I made to keep communication with the sever to client and vise-versa organised and secure! It gets ridge of the need to make RemoteEvent and RemoteFunction objects while having a very organised workflow.

Note: This only works with the Roblox workflow, I am planning to expand to the Rojo workflow in the future!

Model:

Setting up:
The setting up process is fairly easy and simple!

  1. Insert the Module to your game
  2. Place in ReplicatedStorage

It comes with 2 templates, a ServerScript and a Local Script which can be used as example of the features provided. Important notice, changing or destroy any elements within the Framework can result in critical errors!

Implementing to Game:
If you’re not already using the template listed, then you are required to create a script in ServerScriptService called “Runner”, this script is going to function as the server host.

The Start operation should only be performed once by the server, right after requiring the Framework! Forgetting to call the .Start() function on the RemoteFramework will cause critical malfunctions and errors!

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local RemoteFramework = require(ReplicatedStorage:WaitForChild("RemoteFramework"))
local Archive = {} --// Important To Keep A Record Of The Player's Remote Object \\--

RemoteFramework.Start()

Players.PlayerAdded:Connect(function(Player)
	local PlayerObject = RemoteFramework.new(Player) --// Creates A Remote Communication With The Player Attached To It.

	PlayerObject:Process()
	Archive["SECURE" .. Player.UserId] = PlayerObject
end)


Players.PlayerRemoving:Connect(function(Player)
	pcall(function()
		--// It Is Recommend To Use A PCall function as this can error! \\--

		if Archive["SECURE" .. Player.UserId] then
			--// Cleaning \\--
			Archive["SECURE" .. Player.UserId]:Destroy()
		end
	end)
end)

You are expected to save and clean! Note that the :Process should be called right after setting up the PlayerObject with the RemoteCommunication object and it’s functions attached to it!

There are 2 current ways to create Remote Communication Object,

--// First Method \\--

local Example = PlayerObject:NewRemote("Example")
Example:BindToServer(function(Message)
	print(Message)
	return true
end)

BindToFunction is a function which can ONLY be performed by the Server. What does it do? Example:BindToServer() connects a function to the RemoteFunction Instance, the function binded gets triggered when the Example:FireServer() function is called.

--// Second Method \\--

local List = {
	Example = function(Message) 
		print(Message)
		return true
	end,
	"Example2" --// Creates A Communication Instance with no functions binded to it.
}

PlayerObject:FromList(List)

Binding Functions should be done before calling the :Process function, it is possible to call the :Process function on the PlayerObject multiple times but it’s not recommended!

Getting the Communication Object [Server Method]

--// Method One \\--

PlayerObject:GetRemote("Example") --// Providing The Name As Argument
--// Method one is Replicated through both Server and Client but Method2 isn't!

--// Method 2 \\--

--// It's Not Recommend To Use Method 2 But You Can Still Use It ONLY On The Server \\--
local AllCommunicationObjects = PlayerObject:RequestAllRemotes()

Sending information to the Client via the Server

RemoteObject:FireClient("Argument1", ...)
--// NOTE: Arguments no longer have to be sent in a table
--// The Player Argument Is NOT Required Since The RemoteObject Already Contains A Copy Of The Player \\--

Let’s see how it works on the client now!

What is the Structure?
The structure is an object containing all the Remotes created. In order to have remote Creations you’ve created on the Server in your Structure Object, you need to Process it which is done with the PlayerObject:Process().

local ReplicatedStorage = game:GetService("ReplicatedStorage")
--// Get The Framework \\--
local RemoteFramework = require(ReplicatedStorage:WaitForChild("RemoteFramework"))

local Structure = RemoteFramework.Structure()

--// Getting A Remote Communication Is Same As The Server \\--

Structure:GetRemote("Example2)

There are 2 Methods to bind functions on the Client

--// Method One \\--

local functionList = {
--// The Function List NEEDS To Contain The Name Of The Remote And The Function Which You Want To Be Fired When The Server Triggers The Remote \\--

	Example2 = function(Argument) 
		local Part = Instance.new("Part")
		Part.Name = "Example2"
		Part.Anchored = true
		Part.CanCollide = false

		Part.Position = Vector3.new(0, 10, 0)
		Part.Parent = workspace

		print(Argument)

		return true
	end
}

Structure:FromStructure(functionList)

--// Method Two \\--
local Example = Structure:GetRemote(Name)

Example:BindToClient(function(Args)
	print(Args)
	return "Hello World From Lua"
end)

Sending information from the Client to the Server

local Example = Structure:GetRemote(Name)
Example:FireServer(Arguments)

Firing Remote Communication Objects from other Script beside the Runner Script.

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RemoteFramework = require(ReplicatedStorage:WaitForChild("RemoteFramework"))

local Structure = RemoteFramework.Structure(Player)
local Example2 = PlayerRemotes:GetRemote("Example2")
	
task.wait(12)
Example2:FireClient("Custom Message!")

Example:
This is a sprinting system example adapted to the Framework,

ServerScript:


local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local RemoteFramework = require(ReplicatedStorage:WaitForChild("RemoteFramework"))

local Archive = {}

RemoteFramework.Start() --// Starting \\--

local RemoteList = {
	Sprinting = function(Player, Sprint)
		local Character = Player.Character
		
		if Character and Character:FindFirstChild("Humanoid") and Character.Humanoid.Health > 0 then
			local Speed = (Sprint == true) and 20 or 16
			Character.Humanoid.WalkSpeed = Speed
			
			return Speed
		end
	end
}

Players.PlayerAdded:Connect(function(Player)
	local PlayerObject = RemoteFramework.new(Player)
	
	PlayerObject:FromList(RemoteList)
	PlayerObject:Process()
	
	Archive["SECURE_" .. Player.UserId] = PlayerObject
end)

Players.PlayerRemoving:Connect(function(Player)
	if Archive["SECURE_" .. Player.UserId] then
		local PlayerObject = Archive["SECURE_" .. Player.UserId]
		
		PlayerObject:Destroy()
		Archive["SECURE_" .. Player.UserId] = nil
	end
end)

ClientScript:


local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local UserInputService = game:GetService("UserInputService")

local RemoteFramework = require(ReplicatedStorage:WaitForChild("RemoteFramework"))

local Player = Players.LocalPlayer

local CurrentWalkSpeed = 16
local IsSprinting = false

wait(.12)

local Structure = RemoteFramework.Structure() --// Player Argument Not Required Because It's On The Client \\--
local SprintRemote = Structure:GetRemote("Sprinting")

local function TriggerSprint()	
	if Player.Character and Player.Character:FindFirstChild("Humanoid") and Player.Character.Humanoid.Health > 0 then		
		IsSprinting = not IsSprinting
		CurrentWalkSpeed = SprintRemote:FireServer(IsSprinting)
	end	
end

UserInputService.InputBegan:Connect(function(InputObject, GameProcessed)
	if GameProcessed then return end

	if InputObject.KeyCode == Enum.KeyCode.Q then
		TriggerSprint()
	end	
end)

UserInputService.InputEnded:Connect(function(InputObject, GameProcessed)
	if GameProcessed then return end

	if InputObject.KeyCode == Enum.KeyCode.Q then
		TriggerSprint()
	end	
end)

If ever you come across a bug or problems, feel free to DM me on the Forums or Discord, ImportLua#9522! You will be notified of new features and updates via this post!

5 Likes

I’m wondering what functionality this library offers compared to something like Ropost. It just seems like another abstraction.

All the functionalities are listed above, I’ve never heard of ropost before… It’s still under development.