ReplicationService: Put client to server replication in your own hands

Before you start, it is important you know about filtering enabled (FE) first. If you don’t know what it is please watch this video.

https://www.youtube.com/watch?v=_jTd4sfCh7Y

For all doccmentation and examples, please read the “docs” file inside the module.

What is ReplicationService?

ReplicationService is a module dedicated to fixing latency in filtering enabled (FE) experiences and improving user experience in general.
As an Australian, we usually average around 300 ms in American servers (which is most servers on ROBLOX) which can be very annoying in parts that require action from the user (such as in survival, building or fps games).

Before filtering enabled, latency usually wasn’t a problem as something called “replication” would bassically replicate a state of an instance in a client to the server.
So no matter how laggy you were, you still always had an enjoyable and satisfying experience.

Unfortunately, filtering enabled pratically removed the entire replication system, leaving us with only remote events and remote functions.

Sadly, most developers still cant fully grasp filtering enabled properly, resulting in them simply directly wiring a remote event/function which can be a HORRIBLE thing for users that don’t have top tier internet or latency, such as me which can make a mechanic very unsatisfying or outright unplayable.

Now, imagine if you were able to use BasePart:SetNetworkOwnership() on practically anything?

ReplicationService absolutely does it all! Plus, it comes included with many many more features to make the experience as fast and secure as possible such
as being able to script your own replication filter and put replication fully in your control!

ReplicationService is also very easy to learn and use, and lightweight as well!

With this module, it brings back replication and enhances the experience while playing with other clients.

	Here is how you can set up ReplicationService:
	
		1: Put the module in ReplicatedStorage
		2: Make sure RejectCharacterDeletions is Enabled, this will make sure ReplicationService has full replication control.
		
			game > workspace > RejectCharacterDeletions > Enabled
			
		3: Make sure HTTPService is enabled, this is so ReplicationService will have access to the latest properties from: https://anaminus.github.io/rbx/json/api/latest.json
		
			You can enable it in an unpublished game by copying and pasting this code into the command bar.
			
			game:GetService("HttpService").HttpEnabled = true
			
		
		With that, you should be done!

Demonstrations

With ReplicationService, I can create a Replicator instance and choose a client, instance, and property.

This is before using ReplicationService:

color_false

Now with the Replicator instance I created, I can make the Color property on a BasePart replicate from the client to the server, its so cool and satisfying!

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

local Replicator = ReplicationService:ReplicatePropertyFromClient(workspace.Part, "Color", game.Players:GetChildren()[1])

Replicator:Run()

This is after using ReplicationService:

Color_true

Here is a really REALLY important feature that also comes with ReplicationService…

ReplicationService supports a feature called “Secure Replicators”!

With this, you can code a custom filter for a replicator! This allows for extremely secure replication, for example:

The client has only unlocked 3 Materials which are Wood, Plastic and Grass. But the client is trying to change the material of a placed part to Metal which has not been unlocked, so deny the replication request as it is not valid.

--[[

		LibraryTemplate.lua
		
		This template lets you create your own security library for safer replication.
		
		
		
		[ TUTORIAL ]
		
			On every single client to server update, .OnReplicationUpdate will be fired with these values given.
		
				client: The player that the data is replicating from
		
				instance: The instance that is being handled by the client
		
				propertyname: The name of the property that is being replicated
		
				propertyvalue: The replicated value of the property from the client
				
				replicator: The replicator instance that is handling the replication
				
			
			With all this data, you can write a script that "filters" the replication inside the .OnReplicationUpdate function.
			At the end, you return your status of your check which looks like this:
			
				return true, propertyvalue
				
			These are what the values mean IN ORDER.
			
				proceed: If this is set to false, it will skip the replication and not proceed with replicating the object.
				
				propertyvalue: If you have modified/editted the replicated value, you can put in your own custom value which will be replicated instead.

]]

local SecurityLibrary = {}

function SecurityLibrary.OnReplicationUpdate(client, instance, propertyname, propertyvalue, replicator)
	local unlockedMaterials = client:WaitForChild("OwnedMaterials") -- A folder inside the Player istance that contains the names of Materials that are owned.
	
	if unlockedMaterials:FindFirstChild(propertyvalue.Name) then
		return true, propertyvalue -- The client owns the material, proceed with the replication.
	else
		return false, propertyvalue -- The client does NOT own the material, don't replicate.
	end
end

return SecurityLibrary

All doccumentation about security libraries and examples can be found inside the actual module itself. Here are a few examples of how to create a secure replicator:

1: Create the secure replicator from source.

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

local SecureReplicator = ReplicationService:ReplicatePropertyFromClientWithSecurity(workspace.Part, "Color", game.Players:GetChildren()[1], "ColorExample")

-- The security library we are using is ColorExample, i'll touch in a bit how to install security libraries.

SecureReplicator:Run()

2: Upgrade a regular replicator to a secure version.

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

local Replicator = ReplicationService:ReplicatePropertyFromClient(workspace.Part, "Color", game.Players:GetChildren()[1])
Replicator:Run()

wait(5) -- Have the replicator be completely unfiltered for 5 seconds.

Replicator:SwitchToSecure("ColorExample")

-- SwitchToSecure() should only be used in a case where the replicator was originally specified to be a non secure version and you want to upgrade it.
-- Else, you should use the example above.

This is a pretty powerful module in my opinion, plus it makes gameplay THOUSANDS of times better and satisfying with the instant snappy and latency free response that comes with client to server replication.

For example, this gun made by @Rufus14 has had its latency of moving the gun around COMPLETELY removed and results in a satisfying experience.

so smooth 2 (1)

This module is also being used and featured in a game called Space Wars!

Currently known issues that will be patched soon:

- Localscripts as of now currently don’t interact well with ReplicationService and is pretty buggy when having a property of it replicated.

- Unanchored parts currently have buggy behaviour due to network ownership conflict

- As of now, descendants of a replicated object will not have any server replication updates

So, what are you waiting for?

It’s time to stop having developers directly wire precise mechanics that require user interaction to a remote event constantly, start using ReplicationService now!

Package (constantly updated)

36 Likes

Packages can’t be made offsale if i remember correctly

Can you show Performance Metrics? I’m worried this can clog up network bandwidth.

dont worry: replication updates are calculated on property changes and are not linked to any RenderStepped or loop in that case.

1 Like

the package has been reupdated to use packagelink, i recommend you replace your standalone version with the package version for constant updates.


ignore memory, the gun has some memory leaks that need to be patched.

new update coming soon:

  • object deletion replication (client part:Destroy() > server)
  • object addition replication (client Instance.new(“Part”) > server)
1 Like

Network Owner sent part position to server is 1.00 Kbps but yours is higher than network owner

network ownership works differently to replicationservice

(however, replicationservice does need a little bit of some changes rn)

FD was deprecated for a good reason, I get that this still has the option to add limits to what a client can replicate, but at that point I don’t understand why use this, just focus on adding client prediction to your game mechanics to avoid stuff input delay and keep your game responsive.

1 Like

The problem is that most developers today simply connect remoteevent to something precise (like the movement of the barrel on the gun) which makes the game unplayable for people with high ping (me).

With replicationservice, we can simply this process and make the game snappy and responsive for the client with the benefit of the server having the data replicated.

Think of this as another type of remoteevent, ive given this thing many features to stay secure such as secure replicators and property only replicators.

example: https://devforum-uploads.s3.dualstack.us-east-2.amazonaws.com/uploads/original/5X/1/9/0/5/1905314894a1dadd26b71628697fff9862c6da12.gif

This isn’t an issue that your resource addresses either.

Lets look at the gun example you posted.

The way you are intended to actually do it is by having your code utilize client prediction, which in this case is instantly updating the client’s gun angle localy, then we send that angle every tick through a remote event, then we change the gun’s angle on server side and we replicate this to other clients.

Here is why often the solution ends up on the ping problems you described, Sending angles every frame to the server is not a problem, the issue is not compressing said data and on top of that not utilizing an unreliable remote event.

Then there is the problem with just letting the Roblox built in replication replicate the server’s gun angles to the clients in game, Roblox’s replication is very bad for a lot of stuff that is constantly changing because asides from stressing the server a lot, it doesn’t even have client interpolation to make other client’s angles look smooth from their end.

Your resource does not even use unreliable remote events nor compression, meaning an exploiter could probably keep spamming a remote event with garbage data for no reason and just lag the server, additionally your game systems should actually acknowledge a player can provide the server with input and not just let it replicate properties and stuff to it.

Brilliant- while I think the examples aren’t good use-cases, the idea is something I’ve wanted for a while. My biggest feature ask is for data network ownership i.e. like the remote property/replication service modules, but with functionality for client to server.

Its so easy and useful, its sad that network ownership only works on unanchored parts and only replicates CFrame, so why not do it with every other property?

The reason is something about Roblox ideology, as weird as it sounds. It’s not that they can’t, it’s that they /don’t want to/

Did you not… Read the resource??

why does this take so looonger to update this?

i didnt know some people still used the project, so i just left it stand still for awhile

ill think about updating it later

1 Like


I got an error when I tried to update that package module