Registers the table into the module so that it is subject to replication signals from the other side (or deregisters a table so that it is no longer subject to replication signals from the other side, if tbl is passed as nil).
If a filter is specified, if a specific change does not pass the filter it is rejected (aka when the filter returns false). (This is on a per key-value pair basis.)
If the change should be accepted, the filter should return true.
Note that if the change was sent from the server, sender is always nil.
Sends all changes (since SendChanges/SetTable was last called) to the side specified by replicationMode.
If replicationMode is “ToClient”, then the player argument is required.
If unreliable is passed as true, then the function will replicate changes via the unreliable changed remote event instead of the normal one.
Sets a callback function to be called when a replication signal for the registerKey is sent to this side.
Returns a function to disconnect the callback.
A server-side function to set the filter for ReplicatedRegistry.RequestTable calls.
By default, this filter only accepts RequestTable requests if the key matches/is the player’s UserId.
However, the purpose of this function is so you can change that.
Returns a composite filter containing all filters specified within nameToArgs.
The returned filter can be used in ReplicatedRegistry.SetTable()
Examples
The following example demonstrates simple player data replication between clients and the server.
Server:
local ReplicatedRegistry = require(path.to.module)
local setTbl = ReplicatedRegistry.SetTable
local replicate = ReplicatedRegistry.SendChanges
local filters = ReplicatedRegistry.Filters
-- A filter that rejects all replication requests from the client
local norecv = filters.NoReceive(true)
game.Players.PlayerAdded:Connect(function(plr)
local tbl = {
JoinTime = os.time(),
Kills = 0
}
setTbl(plr.UserId, tbl, norecv)
tbl.Kills = 10
replicate("ToClient", plr.UserId, plr)
end)
Client:
local player = game.Players.LocalPlayer
local ReplicatedRegistry = require(path.to.module)
local setTbl = ReplicatedRegistry.SetTable
local request = ReplicatedRegistry.RequestTable
local filter = ReplicatedRegistry.GetFilter {
DontAcceptIfNil = true,
RateLimit = 10
}
local tbl = setTbl(player.UserId, request(player.UserId), filter)
while task.wait(1) do
print(tbl.Kills) -- 10
print(tbl.JoinTime) -- Some big number
end
Look at how easy it is to set up server → client data replication!
It’s so simple to use, it’s just a table!
I wouldn’t even know where to begin to do this with Replica
ReplicatedRegistry is also FAR more optimized than the likes of Replica, ReplicaService and charm-sync as it does not attempt to do any state management, only replication of table changes.
It also is far, far simpler, so you can modify it to your hearts content!
Removed the seperate dict tables for callbacks and values, combining it into 1 dict mapping register key to Registrees which contain all data (such as filters, the actual table reference, callbacks, etc)
Added InvokeRequestCallback (a callback to be called on the server when a client calls .RequestTable) and Registrees (Where all registered tables are stored) as members of the ReplicatedRegistry return table, the exposing of Registrees allows you to replicate multiple tables at once
Note that theres a good chance i broke something in this update so please, PLEASE let me know
fire module , i look forward to future resources from you as i may or may not use a quite amount of modules you’ve created like actorgroup2, bufferconverter, and including this one
Bufferconverter isnt really good (nor is the second one :V), nowadays I use the rewrite of bufferconverter2 only for communicating between actors
ActorGroup2 is still pretty good tho yeah, but preferably you should make whatever you’re trying to do not need to send a response back so everything can be done async (which is much faster) :V
Feel free to use my “Simple{name}” stuff tho, I’ve heard many of them r pretty good :0
So im trying to create a NPC but having an accurate position on ALL clients is VERY important for this specific NPC.
I want to know if it would be viable to use this module to keep his position the same on the server and all clients by updating his position using the server and retrieving that value from the client and adjusting his position.
The REASON its so important is because he goes VERY fast and has modified physics.
hello! I’m trying to use your module in order to sync up changes in a player’s table with their UI but I’m getting an odd “tables cannot be cyclic” error that I’m not sure how to fix.
ah, gotcha! I think I get the problem now so I’ll roll around back to this when I’ve fixed it. Going to try just replicating part of the table (the important stuff like current stats and stuff, no need to send everything over) and hopefully that’ll fix things
How could i detect changes from the server? , Iv’e tried doing OnKeyChanged from the server but, it just won’t detect
local function OnProfileLoaded(Profile)
local Player = Profile.Player
local character = Player.Character
if not Profile or not Player then end
Profile.Profile.OnSave:Connect(function()
print("saved")
end)
local char = Player.Character
local leaderstats = nil
if Player:FindFirstChild("leaderstats") then
leaderstats = Player:WaitForChild("leaderstats")
end
for _, values in pairs(leaderstats:GetChildren()) do
for statName, statValue in pairs(Profile.Profile.Data.Stats_) do
if values.Name == statName then
values.Value = statValue
local new_Changed = values:GetPropertyChangedSignal("Value"):Connect(function()
Profile.Profile.Data.Stats_[statName] = values.Value
replicate("ToClient", Player.UserId, Player)
warn(statValue.." :", Profile.Profile.Data.Stats_[statName])
end)
end
end
end
local newplayerdata = setTable(Player.UserId, Profile.Profile.Data)
local OnRequest = ReplicatedRegistry.SetOnRequest(function(player, registerKey)
warn(player, registerKey)
end)
replicate("ToClient", Player.UserId, Player)
warn(newplayerdata)
end
I am using this with ProfileStore and my table looks like this
Hi, you need to call the SendChanges() (or in your case replicate()) function repeatedly in a time interval if you want it to constantly replicate, here you are only calling it once
SendChanges sends all changes since the last time SendChanges was called, so if you want you can send changes every like 1 second
What i usually do is loop through all currently active sessions (or in your case profiles) and SendChanges them all at once in a loop
Hello I am having problems with this module. I am trying to create a table on the server and when a player joins it logs him into the table.
When the player joins in his localscript it requests the table and gives positive, but when printing it prints an empty table
its not until moments later that the server changes one of its values that the player receives a table but only with those changed values, as if the others did not exist.
My question is, how can I make a player receive a complete table when joining even if there are no changed values? I have tried many things but it never ends up working right, I would like that when a player joins I can get the full table correctly and not just defined as you change the values.
An example of how is the game working rn:
Server:
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ReplicatedRegistry = require(ReplicatedStorage:WaitForChild("ReplicatedRegistry"))
local sendChanges = ReplicatedRegistry.SendChanges
local filters = ReplicatedRegistry.Filters.NoReceive
ReplicatedRegistry.SetTable("playersinfo",{}, ReplicatedRegistry.Filters.NoReceive(true))
local playersinfo = ReplicatedRegistry.GetTable("playersinfo")
game.Players.PlayerAdded:Connect(function(player)
playersinfo[player.UserId] = nil
ReplicatedRegistry.SendChanges("ToAllClients", "playersinfo")
playersinfo[player.UserId] = {
currentHealth = 300,
status = "offline"
}
print(playersinfo)
-- Will print the table correctly ( {UserId} -> [currentHealth = 300, status = “offline”])
ReplicatedRegistry.SendChanges("ToAllClients","playersinfo")
task.wait(5)
playersinfo[player.UserId] = {
currentHealth = 300,
status = "playing"
}
ReplicatedRegistry.SendChanges("ToAllClients","playersinfo")
print(playersinfo)
--Will print the table correctly ( {UserId} -> [currentHealth = 300, status = “playing”])
task.wait(5)
playersinfo[player.UserId] = {
currentHealth = 200,
status = "playing"
}
ReplicatedRegistry.SendChanges("ToAllClients","playersinfo")
print(playersinfo)
--Will print the table correctly ( {UserId} -> [currentHealth = 200, status = “playing”])
end)
Local:
local ReplicatedRegistry = require(game.ReplicatedStorage:WaitForChild("ReplicatedRegistry"))
playersinfo = ReplicatedRegistry.SetTable("playersinfo", ReplicatedRegistry.RequestTable("playersinfo"))
print("Recibed")
print(playersinfo)
-- Just print {}
task.wait(6) -- Example of waiting after the first change
print(playersinfo)
-- Prints ( {UserId} -> [status = «playing»]) but currentHealth does not exist
task.wait(6) -- Example of waiting after the second change
print(playersinfo)
-- Will print the table correctly ( {UserId} -> [currentHealth = 200, status = “playing”]), but just because all the values were changed