Created
August 25, 2024 05:35
-
-
Save MrChickenRocket/4162e68f5230fd6267c3bece413fbab1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local module = {} | |
local deltaTable = require(game.ReplicatedFirst.Modules.DeltaTable) | |
module.tables = {} | |
module.callbacks = {} | |
module.remoteEvent = nil | |
--Connect for a callback | |
-- function(currentTable, delta, oldTable) | |
function module:Connect(name, callback) | |
if (module.tables[name] == nil) then | |
warn("Table " .. name .. " not found") | |
return | |
end | |
local callbackList = module.callbacks[name] | |
if (callbackList == nil) then | |
callbackList = {} | |
module.callbacks[name]= callbackList | |
end | |
--Add it | |
callbackList[callback] = callback | |
end | |
function module:Setup() | |
if (module.remoteEvent == nil) then | |
module.remoteEvent = game.ReplicatedStorage:WaitForChild("ReplicatedTableRemoteEvent") | |
module.remoteEvent.OnClientEvent:Connect(function(event) | |
local oldTable = module.tables[event.name] | |
if (module.tables[event.name] == nil) then | |
module.tables[event.name] = deltaTable:DeepCopy(event.data) | |
else | |
module.tables[event.name] = deltaTable:MergeTable(module.tables[event.name], event.data) | |
end | |
--see if theres any callbacks | |
local callbackList = module.callbacks[event.name] | |
if (callbackList ~= nil) then | |
for funct,value in callbackList do | |
funct(module.tables[event.name], event.data, oldTable) | |
end | |
end | |
end) | |
end | |
end | |
module:Setup() | |
return module |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local module = {} | |
------------------------------------------------------------------------------------------------ | |
-- Helpers | |
local function RecursiveCall(old, new, key, count, res) | |
--its a table, recurse | |
-- predicate | |
if type(old[key]) ~= "table" then | |
count = count + 1 | |
res[key] = new[key] | |
return res, count | |
end | |
local newtable, num = module:DiffTable(old[key],new[key]) | |
if (num > 0) then | |
count = count + 1 | |
res[key] = newtable | |
end | |
return res, count | |
end | |
local function IfChangedSetCall(old, new, key, count, res) | |
local a = new[key] | |
local b = old[key] | |
--deletion | |
if (b ~= nil and a == nil) then | |
count = count + 1 | |
res[key] = "_" | |
return res, count | |
end | |
if (a ~= b) then | |
count = count + 1 | |
res[key] = a | |
end | |
return res, count | |
end | |
function module:DeepCopy(original) | |
local copy = {} | |
for k, v in original do | |
if type(v) == "table" then | |
v = module:DeepCopy(v) | |
end | |
copy[k] = v | |
end | |
return copy | |
end | |
function module:DiffTable(old, new) | |
local res = {} | |
local count = 0 | |
for var,data in new do | |
if (type(new[var]) == "table") then | |
res, count = RecursiveCall( old, new, var, count,res) | |
else | |
res, count = IfChangedSetCall(old, new, var, count, res) | |
end | |
end | |
return res,count | |
end | |
function module:MergeTable(old, diffTable) | |
local newTable = module:DeepCopy(old) | |
for key,value in diffTable do | |
-- If we signal a deletion then here we go | |
if diffTable[key] == "_" then | |
newTable[key] = nil | |
continue | |
end | |
if (type(diffTable[key])=="table") then | |
if type(old[key]) ~= "table" then | |
newTable[key] = diffTable[key] | |
else | |
newTable[key] = module:MergeTable(old[key], diffTable[key]) | |
end | |
else | |
--see if its a numerical key | |
local numberKey = tonumber(key) | |
if (numberKey == nil) then | |
numberKey = key | |
end | |
newTable[numberKey] = diffTable[key] | |
end | |
end | |
return newTable | |
end | |
return module |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--On the server | |
playerRecord.player = { | |
coins = 10, | |
} --Some random ass table | |
--Create the table, forget about it | |
--Remember to keep the handle around! Once tableHandle gets GC'd this cleans itself up | |
playerRecord.tableHandle = serverReplicatedTable:CreateReplicatedTable("runTimeData", playerRecord.runTimeData, playerRecord.player) | |
--On the client | |
--Event based access | |
clientReplicatedTableModule:Connect("runTimeData", function(current, delta, old) | |
print("runTimeData changed" ,delta) | |
end) | |
--or | |
--direct access | |
local runTimeData = clientReplicatedTableModule.tables["runTimeData"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local module = {} | |
local deltaTable = require(game.ReplicatedFirst.Modules.DeltaTable) | |
module.remote = nil | |
module.tables = {} | |
setmetatable(module.tables,{__mode = "v" }) | |
local function Map(sourceTable, fields) | |
local results = {} | |
results.fields = {} | |
results.numFields = 0 | |
results.tables = {} | |
results.numTables = 0 | |
for key,value in fields do | |
--see if it exists in the sourceTable | |
if (sourceTable[key] == nil) then | |
warn("Asked for a view of a field that doesnt exist:" .. key) | |
continue | |
end | |
if (typeof(value) == "table") then | |
--Recurse | |
local res = Map(sourceTable[key], value) | |
results.tables[key] = res | |
results.numTables += 1 | |
else | |
results.fields[key] = sourceTable | |
results.numFields += 1 | |
end | |
end | |
return results | |
end | |
local function Copy(data) | |
local result = {} | |
for key,value in data.fields do | |
local srcTable = value | |
local srcKey = key | |
local srcValue = srcTable[srcKey] | |
result[srcKey] = srcValue | |
end | |
--Do the tables now | |
for key,value in data.tables do | |
result[key] = Copy(value) | |
end | |
return result | |
end | |
function module:CreateReplicatedTable(tableName : string, sourceTable : any, player : Player) | |
return self:CreateReplicatedTableFiltered(tableName, sourceTable, player, nil) | |
end | |
function module:CreateReplicatedTableFiltered(tableName : string, sourceTable : any, player : Player, filter : any) | |
local record = {} | |
record.sourceTable = sourceTable | |
record.tableName = tableName | |
record.player = player | |
if (filter ~= nil) then | |
record.dataMapping = Map(sourceTable, filter) | |
else | |
record.dataMapping = nil | |
end | |
function record:Update() | |
local diff = nil | |
if (self.previous == nil) then | |
self.previous = {} | |
end | |
if (self.dataMapping) then | |
local result = Copy(record.dataMapping) | |
diff = deltaTable:DiffTable(self.previous, result) | |
self.previous = deltaTable:DeepCopy(result) | |
else | |
diff = deltaTable:DiffTable(self.previous, self.sourceTable) | |
self.previous = deltaTable:DeepCopy(self.sourceTable) | |
end | |
--has data? | |
if (next(diff) ~= nil) then | |
--send the diff | |
module.remote:FireClient(player, { id = "tableDelta", name = record.tableName, data = diff }) | |
end | |
end | |
table.insert(self.tables, record) | |
--Replicate it right away | |
record:Update() | |
return record | |
end | |
function module:Setup() | |
if (game.ReplicatedStorage:FindFirstChild("ReplicatedTableRemoteEvent") == nil) then | |
module.remote = Instance.new("RemoteEvent") | |
module.remote.Name = "ReplicatedTableRemoteEvent" | |
module.remote.Parent = game.ReplicatedStorage | |
game["Run Service"].Heartbeat:Connect(function(dt) | |
for _,record in module.tables do | |
record:Update() | |
end | |
end) | |
end | |
end | |
module:Setup() | |
return module |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment