Replicating table's value across scripts

So basically, I have a table and I want to assign a key to a value (Specifically a data from another script). Normally this would automatically gets replicated but I have no idea why it isn’t (I’m presuming the cause is due to it being wrapped in a table)

    local statsTbl
	repeat statsTbl = plrStats:returnTbl(plr) until statsTbl
	
	local stats = statsTbl.plrStats
	local data = statsTbl.data
	
	skillStats[plr] = {
		DMG = stats.currentDMG,
	}

    coroutine.wrap(function()
		while wait(1) do
            print(stats.currentDMG) -- print out 10, 15, 20, 25, etc..
		end		
	end)()

It’s printing out the following numbers because I’m also changing the value in another script in a while loop, however, this data doesn’t seem to replicate into the table, when I reference it from another script, it would just print out 10 - which is the initial value.

Any help is appreciated!

1 Like

Are you requiring the module on a server script and local script? If so, they’re completely independent of each other and don’t have their values replicated.

Yep although it is on different sides (The module is on the client). I have set up my own replicator so that any data that gets changed also go through the client

As you can see it still prints out the current DMG value, it just doesn’t replicate to the table

1 Like

Can you give us the code for the replication? You’ll need to update the table itself as well as just the stats table

yeah sure here’s the code for it: (Keep in mind this code replicates the statsTbl, not the skillStats table
[/quote]

local plrConst = {}

local activeTbl = {}

local RunService = game:GetService("RunService")
local transferEvent = script.transfer

function constructMetatbl(originalTbl, callback)
	local events = {}
	
	local changedEvent = Instance.new("BindableEvent")
	
	local proxy = setmetatable({}, {
		__index = function(self, key)
			return rawget(originalTbl, key)
		end,
		__newindex = function(self, key, v)
			if callback then
				callback(key, v)				
			end
			changedEvent:Fire(key, v)
					
			if events[key] then
				for i, bindable in pairs(events[key]) do
				 	bindable:Fire(v)
				end				
			end
			
			return rawset(originalTbl, key, v)
		end,
	})
	
	rawset(proxy, "Changed",changedEvent.Event ) -- rawset to prevent data from being changed
	--proxy.Changed = changedEvent.Event
	
	local function getPropertyChangedSignal(key)
		local properyChangedEvent = Instance.new("BindableEvent")
		events[key] = events[key] or {}
		table.insert(events[key], properyChangedEvent)

		return properyChangedEvent.Event
	end
	
	rawset(proxy, "getPropertyChangedSignal", getPropertyChangedSignal)
	
	return proxy	
end

function plrConst:addNewPlr(plr, dataTbl)
	if not activeTbl[plr] then
		local plrStatsProxy = constructMetatbl(plrStatsTbl, function(key, v)
			transferEvent:FireClient(plr, {tab = "plrStats", Key = key, Val = v})
		end)
		
		local dataProxy = constructMetatbl(dataTbl, function(key, v)
			transferEvent:FireClient(plr, {tab = "data", Key = key, Val = v})
		end)
		
		local newTbl = {
			plrStats = plrStatsProxy,
			data = dataProxy,
		}

		activeTbl[plr] = newTbl

		transferEvent:FireClient(plr, {newTbl = { -- send non-metatables cuz client can't recieve metatables
			plrStats = plrStatsTbl,
			data = dataTbl,
		}})
		
		return newTbl
	end
end

function plrConst:returnTbl(plr, key)
	if activeTbl[plr] then
		return activeTbl[plr][key] or activeTbl[plr]
	end
end

function plrConst:updateKeyInStats(plr, key, val)
	if activeTbl[plr] then
		activeTbl[plr].plrStats[key] = val
	end
end

function plrConst:updateStats(plr, newStats)
	activeTbl[plr].plrStats = newStats
	transferEvent:FireClient(plr, {stats = newStats})
end

function plrConst:updateKeyInData(plr, key, val)
	activeTbl[plr].data[key] = val
end

if RunService:IsClient() then
	local plr = game.Players.LocalPlayer
	
	transferEvent.OnClientEvent:Connect(function(args)
		if args.newTbl then -- construct
			args.newTbl = {
				plrStats = constructMetatbl(args.newTbl.plrStats),
				data = constructMetatbl(args.newTbl.data),
			}		
			
			activeTbl[plr] = args.newTbl or activeTbl[plr]
		end
		
		--printTable(args, "")
		if args.Key and args.tab then
			activeTbl[plr][args.tab][args.Key] = args.Val
 		end
	end)
	
	
end

return plrConst

Although binding a changed event and update the table does work, I’m trying to avoid this to get maximum efficiency

The most efficient way for you to do this would be via some kind of Changed signal so I don’t think avoiding it is going to work. For clarity is this on the server or client?

local statsTbl
repeat statsTbl = plrStats:returnTbl(plr) until statsTbl

local stats = statsTbl.plrStats
local data = statsTbl.data

skillStats[plr] = {
	DMG = stats.currentDMG,
}

coroutine.wrap(function()
	while wait(1) do
        print(stats.currentDMG) -- print out 10, 15, 20, 25, etc..
	end		
end)()

That’s on the client, I’m still trying to find alternatives to the Changed method as I believe this is pretty inefficient

Have you tried the Changed method and benchmarked it? There is no point restricting yourself to another method if you don’t have to. From a readability PoV there’s a few ways you could abstract away from the Changed event.

Native Lua values have never replicated across the client-server boundary.