I have the same issue, it’s gone when I switch to a different place very weird.
I’m a bit confused, why is it necessary to not add on more listeners once you have requested data? It is making it a lot more hard to use for my states system, where when each player joins they get assigned a state. Sorry for the trouble, otherwise great module though!
I second this. It makes it a lot harder to build ReplicaService as a dependency for one of my game system’s modules because I’m not guaranteed that any of the scripts will definitely call the ‘Request’ function on the controller module. This means that even if I wanted to, I can’t create portable modules to use across multiple games.
Makes sense. I suggest waiting for my future remake of ReplicaService which will be based around extendable classes with replicated state
I have a question about the efficiency of an application of this module.
I have a stat called “Time Played” in my game, which goes up one for every player in game every second. I also have a custom player list, which is sorted in descending order by Time Played.
I have other stats that don't go up every second, but go up fairly often for each player. Currently I'm replicating data to the client for use in the player list like this:
Would creating a Replica for every player to store their data, and having each replica replicate to every client be more efficient? Or would it be less efficient?
Most of these data points you speak of will have negligible impact to memory and network bandwidth use - you’ll have a hard time even seeing them show up in the performance stats.
In your game The Mad Murderer X how are you handling map replication? I’m assuming you are using ReplicaService.
Replicas don’t replace instances but can be used to complement them.
Oh. How are you complementing them? Are the maps still being loaded from ServerStorage, and only certain components are Replicated such as Lighting properties, etc.?
Rigging dynamic state to certain parts of the map i.e. doors, displays, buttons, etc.
Oh, makes sense. For some reason I thought the entire map gets replicated, but I see it’s just little interactables almost. With that being said the doors and etc. did you Replicate them to reduce server load for animating them opening and etc.?
Hi loleris,
Is there any event triggered to the client when a Replica is destroyed? This is my only current solution and I’m not sure if it’s good for production. Also note that this is scramble code.
ReplicaController.ReplicaOfClassCreated("MarkerPositions", function(replica)
local marker = createMarker(replica.Tags.Player)
replica:ListenToChange({"Location"}, function(new_value)
marker.Position = new_value
end)
-- Current Solution
game.ReplicatedStorage.ReplicaRemoteEvents.Replica_ReplicaDestroy.OnClientEvent:Connect(function(replica_id)
if replica_id == replica.Id then
marker:Destroy()
end
end)
end)
Thank you!
For some reason I thought that that function was only for the server. Thank you!
Hey, looks great!
Just want to understand what is the benefit of using the Write method with WriteLib instead of just SetValue/s without WriteLib? @loleris
Instead of sending a whole table path with :SetValue()
or other built-in mutators Write()
will only send the serialized id representing the function name in a WriteLib module following the function arguments - there are scenarios where this could help achieve much greater network efficiency when altering state (e.g altering 100’s of values with one function call), though in most cases there’s always a workaround to make it relatively efficient with built-in mutators as well.
WriteLibs can help create efficient state that is more unpacked / unserialized as soon as it’s replicated because in a way a WriteLib is a serialization / packing tool that can lump multiple mutations together.
Still, I actually recommend relying on built-in mutators more and make mostly 1-dimensional state (no deep tables).
Gotcha!
Many thanks for the detailed explanation.
I have integrated your modules into my project and so far it is great.
Keep up the great work!
Could this be used for cross-server networking? Ie, global events?
Hey, @loleris
Great job with the service.
Could you elaborate on the use-cases of parenting replicas to other replicas?
In what cases should I use this feature?
What is the difference between using 2 unrelated Replicas to using nested Replicas(Parent->Child)?
Many thanks!
I came across a concern. I spent a while trying to figure out why my listener for ListenToChange wasn’t firing. Eventually I realized I had 2 listeners for the same path, one in two scripts on the client, and I disconnected the other one expecting them to be two different connections.
Apparently ReplicaService shares the same connection for the same path, regardless of the form, at least that’s how I interpret it. I’m pretty clueless as to how this works internally. The docs state that I shouldn’t need to disconnect individual connections since it’ll be handled when the Replica is destroyed, but in my case this player data replica stays alive until the player leaves.
I create a new ListenToChange listener for each time an ‘item’ is added in my player data table. This item can be removed and obtained again by the same player infinitely. Currently, I have to make sure that I add extra code so it doesn’t stack listeners and only go by the first one. This would get trickier if I needed to actually access something only in the scope of PerKey and make sure I always access the latest one.
local ReplicaReceiver = require(ReplicatedStorage.Modules.Client.ReplicaReceiver)
local DataReplica = ReplicaReceiver:Get("PlayerData", Player)
local ListenersMade = {}
local function PerKey(Key)
if not ListenersMade[Key] then
ListenersMade[Key] = true
DataReplica:ListenToChange({"Items", "Ammunition", Key}, function(NewValue)
if NewValue == nil then
if Slots[Key] then
Slots[Key].SlotObject:Destroy()
Slots[Key] = nil
end
end
end)
end
end
DataReplica:ListenToNewKey({"Items", "Ammunition"}, function(Value, Key)
SortSlots()
PerKey(Key)
end)
for Key in pairs(DataReplica.Data.Items.Ammunition) do
PerKey(Key)
end
Is there any chance this future rewrite could have separate connections that I can disconnect, like how regular RBXScriptConnections work? Or is there something I don’t quite understand about how this works? I use these server-sided a lot as well (wouldn’t be the same without them for my use case), and it would be horrid if I ran into server memory leak issues (unless if this won’t actually cause memory leak problems, but instead stacking as a result)?
Thank you, hopefully this could be cleared up on how it actually works and if there’s any preferred way to go about solving this without throwing in a solution like this every time.