Replicate your states with ReplicaService! (Networking system)

Woah, this is amazing, I havent seen something like this before (Maybe its just cause I just started browsing community resources and only 1 year with roblox development) however, I am amazed how many good resources madstudio has been able to create, I hope to see more from you in the future!

6 Likes

Definitely going to be experimenting with this in an upcoming game and will probably end up creating a tutorial on using it practically.

17 Likes

Would this work with mass replicating physics properties from tons of constraints like hingeconstraints, ropeconstraints etc?

My game needs to use tons of remote events from the client to the server and throttles regularly.

8 Likes

If you want to send massive amounts of data there’s nothing that will magically make that data disappear. You can effectively send up to 50 KB/s constantly with casual spikes through RemoteEvents for each individual player - anything more than that can be unstable. For reference, 1 CFrame value, for example, might take up to 50 bytes to replicate (Assuming it uses 32-bit floats) plus any overhead the RemoteEvent itself imposes. Updating a single CFrame 10 frames per second would use around 500 to 600 bytes, so you could effectively only have 100 CFrame streams like that in a single Roblox game.

Overall Roblox was not designed for this kind of data streaming - the best approach is to leave physics updates to the Roblox physics engine.

You’ll have to test your game yourself and see what works.

11 Likes

Its not the physics updates i have to replicate to the server, its the properties of the constraints.

In roblox, if you dont replicate the property changes made on the client to the server, stuff like this will happen.



Thats why i have to update every single property such as “Length” and “Angularvelocity” to the server.

6 Likes

If you’re not able to configure your models properly with BasePart Network Ownership or somehow make the vehicle rigs more stable by using the proper joints / avoiding excessive lose parts and joints, then nothing else will help you as much.

Character flings should be handled on the client-side.

9 Likes

The network owner ship and everything is set correctly and renderstep checking is going to be gamebreaking for my game as you can fly with planes and drive with cars which can reach extreme velocity’s.

6 Likes

I’m really intrigued by the idea of creating a more adaptive StreamingEnabled system. Can you go into more detail (or if you had a moment, provide a code snippet example) of how to properly use ReplicaService for a task like this? There’s a ton of API documentation on this which is great, but initially it’s a little tough to see where the best starting point is and what the optimal logic method would be for a large and helpful new system like this.

2 Likes

Although the API is lengthy, most of it are just variations of mutators and listeners. For StreamingEnabled-like implementations you’ll need to use the Replica:ReplicateFor() and Replica:DestroyFor() server-side methods.

The functionality is straightforward - From a client’s perspective, the same replica can be created, destroyed, created again - the server decides whether the replica is loaded on any particular client.

The only difference from real StreamingEnabled is that you have to tell ReplicaService when to replicate and destroy Replicas when the player enters a region yourself. That being said… Don’t try to reinvent StreamingEnabled - ProfileService is going to be better for map chunks and finite “dimensions” (like MeepCity, AdoptMe) the player is teleported to.

10 Likes

Saw this thread and instantly started looking for a tutorial from you. I’ll most likely start using this after seeing a tutorial or two, this sounds like something I would need for a project I’m currently working on.

3 Likes

So if I understand correctly we can use ReplicaService as an easy way to replicate data back and forth as well as Remote /Event/Function?

  • ReplicaService is Server side?
  • ReplicaController is Client side?

and these are all standalone? I don’t need to import any thing else like the RateLimiter, ScriptSignal and Maid?

2 Likes

As shown in the “Setting up” section of the wiki,
image
you will need a few modules server-side and client-side to run ReplicaService. ReplicaController is the main client-side module. If you miss any modules, the system will not run and will let you know about missing dependencies.

You may group these modules into folders as dependancies will be searched for recursively inside the entirety of ReplicatedStorage and ServerScriptService.

10 Likes

Hi I’m confused why ListenToChange is only available on client, I want to use it on server when SetValue is called as well as I want to generalise what I’m calling on the client to the server, here is my use-case: on the client

ReplicaController.ReplicaOfClassCreated("PlayerProfile", function(replica)
	local data = replica.Data;
	
	local function updateCash(newCash: number)
		activeLobbyManager.store:dispatch(UpdateCash(newCash));
	end;
	
	local function updateOwned(newOwned)
		activeLobbyManager.store:dispatch(UpdateOwned(newOwned));
	end;
	
	updateCash(data.cash);
	updateOwned(data.owned);
	
	replica:ListenToChange("cash", updateCash);
	replica:ListenToChange("owned", updateOwned);
end);

I want the server to recognise the calls to ListenToChange to dispatch to the store on the server as well. (The server would just take the stuff in the body of the function since replica of class created cant be used on server.)

4 Likes

I decided to opt out server-side replica change listeners because a lot of the time server states are going to be passive / have no rendering hooks for GUI’s & parts. Additionally, it was designed to work with ProfileService which accepts direct writing to the table instead of using setter functions - you’re supposed to wrap Profile.Data with a Replica when using them together.

I also though that object.Replica:ListenToChange() would look pretty weird instead of something like object.CoinsChanged:Connect() on the server-side.

However, the overhead of checking for listeners might be negligible, so I’ll look into it. I would appreciate more examples of use cases where the server would need lots of change listening. I’ll try to evaluate that overhead and make a decision quickly.

6 Likes

I would assume that object.CoinsChanged:Connect() would require you to fire that event consecutively every time you change the data in ProfileService as from memory I believe there is no event that detects change in data on ProfileService that you can listen to. object.Replica:ListenToChange() does look kinda weird, however it can be a function call all based on preference:

function activeLobbyManager:hook(replica)
-- the body of the ReplicaController.ReplicaOfClassCreated listener mentioned above
end;

and then the server and client would just plug into that function when created. This would allow really easy management on server & client especially if you want to store player data in Rodux as you don’t have to pass the player data argument everytime as Rodux has more general uses, I can include player data & i can include other state stuff like managing UI.

This is my main use case, I can’t think of many other examples other than Rodux (unless you have another state management module). However, you could probably incorporate other calls to specific modules.

However, take the example in the other post I made, lets say in updateOwned I wanted to update it to Rodux store and imagine I wanted to call a module or function only available where the listeners are located, in my case, lobby manager. Imagine I wanted to fire a function or module only exclusive inside that specific module, this would be another use case other than Rodux.

4 Likes

Another problem with Replicas is that they usually are a clone of select members of a custom object (An object will have members that can’t or shouldn’t be replicated) and in many cases accessing data would be desired by indexing object.Value (Remember that custom objects also usually have methods as members!) instead of object.Replica.Data.Value. In other words, ReplicaService breaks the single source of truth paradigm in practical implementations and, in my opinion, can lead to nasty coding patterns when used as a signal provider server-side - I’m influenced by the fact that these features are something my future team would use.

If you’d still want this functionality, I could probably write a clean enough wrapper for the server-side to enable listeners for Replicas?

Just to be clear, my proposed alternative is to wrap replica mutator calls inside setter methods that also trigger signals created by the developer.

3 Likes

Yes, that would be really helpful, thanks

2 Likes

Added server-side listeners as an experimental module!

This module injects the following missing methods to the ReplicaService module that are only available client-side by default:
image

I’ve also added a modified “AbstractExample” version that showcases server-side listeners.

5 Likes

Thanks for this, Im getting an error though on launchup in the github and roblox model versions

2 Likes

You’ll need to update the ReplicaService module to the latest version as the Replica class table has been publicly exposed to make this experimental module work.

2 Likes