When using Replica:ReplicateFor() does passing a Player instance add them to the dictionary of players that the Replica is or does it overwrite the whole dictionary to now only replicate to that player.
If it just adds them, would you consider expanding the functionality of Replicas to have a function like Replica:SetReplication() which might allow for adjusting the Replication property like you would on Replica creation (“All”, {[Player1] = true, [Player2] = true, …}, Player) ?
There’s no need for a table argument in ReplicateFor, because it wouldn’t help the module make this change any more efficiently. Just call it for every individual player.
We use this library in Wild Worms and it makes iterating on existing network features super easy. It also helps abstract away all of the code that handles keeping track of things like worms, pickups, and player profiles and instead lets us focus directly on adding/fixing features. I would love to make a video on our use case soon!
Are there any examples of handling replicas across multiple client scripts? The things I have tried so far have lead to issues with the listeners potentially being set up after .RequestData(), or scripts attempting to index (from a central module) replicas that weren’t recieved yet.
Is this just an issue with using more than one localscript?
Regardless of what you use, you’ll need some sort of load sequence manager that will know when to call RequestData() after all scripts / modulescripts made their connections
Hey, rather than easily supporting server-client replication, is there a way you can implement a much easier way to allow a client to communicate with the server? Right now, I generally believe it’s more difficult than to manually create a remote event.
Is there any way I can request data to be changed FROM the client TO the server? For example, what if a player clicks a button that toggles a mute radio setting. Would I have my own remote event request FireServer() to update that setting, and then on the server verify the parameters?
Is there anyway to set values to nil in bulk? Since the SetValues() method does not work with nil values I’m unsure how to go about removing a lot of items at once in my inventory system.
If you’re clearing large datasets consistently, consider turning them into nested replicas (replicas parented to other replicas) and create / destroy those replicas instead of editing one replica table.
If that’s not exactly what you’re looking for, then you might’ve overlooked WriteLib (Replica:Write()) functionality which has more power over built-in mutators (Replica:SetValue()).
Is there a particular reason why the Replication and Parent parameters need to be mutually exclusive on a Replica?
Could a ListenToChildRemoved function be potentially added to the ReplicaController?
My current use case where 1. is problematic involves having inventory Replicas parented to character Replicas. I would like an inventory Replica to be able to be parented to a character Replica while maintaining potentially different replication settings from the character Replica. The reason for this is that while I would like some data about a character to be public (replicated) to all players, such as their appearance or what item they are holding, I would like the data about the character’s inventory to be private only to the player who controls that character. In the future, I could also foresee modifying the replication settings of an inventory Replica to multiple players to facilitate trading (while still being parented to the character Replica).
The major benefit that would come out of allowing separate replication settings for child Replicas in the above case would be that the client no longer has to keep track of both character Replicas and inventory Replicas via ReplicaController.ReplicaOfClassCreated at the same time; the client could now just keep track of character Replicas alone and check whether an inventory Replica has been added to it or not. This benefit is also why I ask about 2. We currently have a way of tracking whether a child Replica has been added via Replica.ListenToChildAdded, but no way of tracking when it has been removed.
My current solution is to have each character Replica contain a Data field for the Replica Id of its corresponding inventory Replica, so that on the clientside a separate storage table of known inventory Replicas may be indexed to see if that Id has been replicated for the local client. What I don’t really like about this approach is the dependency on an external static map for clients to associate inventories with corresponding characters (or even other entities, like chests), when it seems natural that an inventory should be replicated together with whatever it’s parented to (while still maintaining separate replication settings).
I can see using WriteLib as another potential solution to my problem, but then it would lead to necessarily dealing with inventories being represented as deep nested tables within the Data field of my character Replicas, which doesn’t really seem ideal either.
Thank you for reading, and sorry for the word wall! I really appreciate you for making ReplicaService (and ProfileService!). I have been using ReplicaService for almost half a year now, and it’s been super super helpful in letting me abstract away most of the networking logic I needed to previously painstakingly deal with by hand!
There aren’t that many scenarios where individual replication settings for nested replicas would win a significant amount of saved resources - Just replicate user-related state to everyone! You’re gonna save yourself from unnecessary work.
Child removal signals might be added in the future
Updated signal module with GoodSignal coroutine recycling / Added yield-safety to the maid module.
IMPORTANT:
Moved the RateLimiter.lua module from src/ServerScriptService to src/ReplicatedStorage - When you’re updating the ReplicaService module, you’ll have to make sure the rate limiter module is in the right place. You should get proper warnings notifying about the missing module.
Update ReplicaService and ReplicaController modules from GitHub or Roblox library!
Ok so I am confused a little. I understand that the Instance you want to replicate to players has to be in a replicated container. So when I am replicating something I need to clone the instance and then pass that as a replica if I am understanding correctly. (Replicating completely works for me by the way). I just want to know how is this better for performance using this module rather than just using a Remote to tell clients to load in that map from ReplicatedStorage, and then hooking a maid to it?
How I am using your Replica for a map:
-- Server
local map_model = ReplicatedStorage.Map:Clone() -- If I don't clone when I destroy it completely destroys the map instance.
local Replica = ReplicaService.NewReplica({
ClassToken = MapClassToken,
Tags = { Model = map_model },
Replication = "All",
})
Replica:AddCleanupTask(map_model)
-- Client
ReplicaController.RequestData() -- Initialize
ReplicaController.ReplicaOfClassCreated(MapClassToken, function(replica)
replica.Tags.Model.Parent = workspace -- load that cloned replicated map into workspace
end)
Is this a proper method of replicating an Instance?
Yes it is the proper way of sending the client a reference to an instance using ReplicaService. However it would not be compatible with StreamingEnabled - the client might receive nil instead of the instance reference.
The primary superpower of ReplicaService is state replication by mutation - clients receive only changes to a state instead of receiving the whole updated state every time. Besides that, ReplicaService manages automatic replication of public replicas (Replicating to “All”) whenever a player joins and provides chronological guarantees by replicating replicas in the order they were created server-side - even for newly joined players!
Simple priblems can obviously be solved with just RemoteEvents - that’s what ReplicaService is built upon anyways. ReplicaService just “extends” RemoteEvents to create long-lasting state similar to Roblox Instances.
Oh ok that clears it up for sure. Thank you! So in my code when I am choosing a map. I create a new replica each time. Should I be doing that or should I be doing something more along the lines of: