Has anyone used this in conjunction with Roact? Thinking about diving into Roact on my next project and this might be a good fit?
I’ll need to ask just a bit of questions:
- Can I not put this inside ReplicatedStorage?
- This is just intended to update if something has changed but can we get it like
ReplicaState:Get("State_ Name_Here")
? - Is this just for values or is it for everything?
- You can put it elsewhere, you’ll just need to change the references. CTRL + F to find where ReplicatedStorage is located and just adjust it to be wherever you want to put it.
- Yes, you can get things. If you check out the examples here you’ll see that you can get the value like
print("TestReplica received! Value:", replica.Data.Value)
- Everything (although there might be some limitations - I haven’t ran into any yet
Why does Replica:ArraySet()
require the index to already exist?
It would be nice if this were adjusted so that tables with specific indexes (even if they are numerical) can also be affected by the handy event of Replica:ListenToArraySet()
since, as it stands, you can only insert, remove, or set pre-existing indexes.
I’ve said it before - but amazing module
The term “array” is not interchangeable with the terms “table” or “dictionary” - Arrays in lua MUST be numeric and have no gaps between element at index 1 all the way to index n.
Creating a table with numeric indexes that has gaps between those indexes and index 1 (e.g. UserIds as indexes) will make that table not replicate properly - It’s listed as a limitation in the documentation and is also why Replica:ArraySet()
prevents you from setting indexes beyond existing ones. Consider using a dictionary with numbers converted to strings as indexes if you run into this problem.
In any case, the built-in array modifiers exist purely for sanity purposes and can be entirely replaced by Replica:SetValue()
or Replica:Write()
.
Would it be Ideal to create a replica for each player?
since I want their Profile to only replicate to them
You assumption is correct - You can create as many Replicas as you like! Replicas themselves are passive when you’re not changing data or sending signals, so a great amount of replicas should not have a performance impact.
If I for loop the data inside of a replica in PostSimulation or Stepped will it throttle? since I use Roact and it renders my ui like Stepped so if it’s a no i’ll just have to find another way
ReplicaService doesn’t drop any state updates even when you change the state rapidly (within reason), but it’s designed for event-triggered updates, not constant streams of data every frame - you should consider not using these kind of streams in your games due to them using lots of bandwidth and usually being redundant data, but if you have to then just use a RemoteEvent without anything fancy wrapping them.
I tried implementing this to Roact and it worked but the problem is that I have to wait atleast a second for the RequestData()
to load in, is their a way to yield until the Replica is not nil?
Replica capturing is “event-based” - your codebase shouldn’t be yielding until a replica is received since you can simply include the code you want to run when you get the replica inside the .ReplicaOfClassCreated()
callback function. To implement exactly what you asked for, though:
local RunService = game:GetService("RunService")
local Replica
ReplicaController.ReplicaOfClassCreated("TestReplica", function(replica)
Replica = replica
end))
while Replica == nil do
RunService.Heartbeat:Wait()
end
print("Replica received:", Replica:Identify())
It would really make more sense to just add the print into the function that handles the replica in .ReplicaOfClassCreated()
.
For some weird reason I think this would have flaws but whatever.
Great project btw I hope to use this further on.
does it detect when a table value has been changed? sorry for the edit but it does not detect changes but If any value or table was changed inside the replica, will
Replica.Data
be changed?
You have to use :SetValue()
It says on the API, “after wrapping a table with a Replica you may no longer write directly to that table”
It also says I can replicate Profile.Data
(profile service), but I have many Scripts
that are constantly writing to Profile.Data
.
I want the client to know everytime Profile.Data.Inventory
changes so I can update the UI, how would I do that with ReplicaService?
You’re going to have to use (both or one of) these methods:
Great module! Question though
function PlayerProfile:GiveCash(cash_amount)
if self:IsActive() == false then
return
end
self.Replica:SetValue({"Cash"}, self.Replica.Data.Cash + cash_amount)
end
Thats the server- side,
local SETTINGS = {
}
----- Module Table -----
local ReplicaTestClient = {
}
----- Loaded Modules -----
local ReplicaController = require(game:GetService("ReplicatedStorage"):WaitForChild("ReplicaController"))
----- Private Variables -----
local Players = game:GetService("Players")
local LocalPlayer = Players.LocalPlayer
----- Private functions -----
----- Public functions -----
----- Initialize -----
ReplicaController.RequestData()
----- Connections -----
ReplicaController.ReplicaOfClassCreated("PlayerProfile", function(replica)
local is_local = replica.Tags.Player == LocalPlayer
local player_name = is_local and "your" or replica.Tags.Player.Name .. "'s"
local replica_data = replica.Data
print("Received " .. player_name .. " player profile; Cash:", replica_data.Cash)
replica:ListenToChange({"Cash"}, function(new_value)
LocalPlayer.PlayerGui.UI.HUD.Cash.Text = replica_data.Cash
end)
end)
Thats the client side, the issue is that its making that cash value for 2 people. As in its showing my cash for another player, how can I fix this?
Thanks! Ill use that!
Instead of “All” I replaced it with player, didn’t work. Any ideas?
Edit: I replaced it with “Profiles[player]” and it seemed to work.