Table Acting as Copy Instead of Reference / Values Not Updating in Original Table

Hello. I am working with a modularized system where I have a script that handles all the data functions. I’ve implemented this for several systems in the game and haven’t run into any issues so far. I’m currently running into an issue with changes to the table not replicating to the original table.

-- Assign key (typically a tool)
function PlayerService.AssignKey(player : Player, key : table) : boolean
    local data = PlayerService.GetPlayerData(player)
    if data["key"] then return false end
    data["key"] = key
    print(PlayerService.GetPlayerData(player)) -- for testing only
    return true
end

This is the code I have. How can I alter the table value in the original table. I could think to return the entire table and save it I don’t know why it’s not returning as a reference.

Also, this is GetPlayerData(player):

-- Get table of player data
function PlayerService.GetPlayerData(player : Player) : table 
    return if isServer then PlayerEvents.GetServerPlayerData:Invoke(player) else PlayerEvents.GetPlayerData:InvokeServer(player)
end

//PlayerController.server.luau

PlayerEvents.GetServerPlayerData.OnInvoke = function(player : Player)
    return PlayerData[player]
end

When a table is passed from server to client it gets copied, the server and the client don’t have the same table reference. This is due to security reasons.

If you want to update the server-sided version of the table, you need to do it on the server. For example you can have a remote that sends to the server a property of the table and the new value to be set(you need to take safety measures so exploiters can’t mess with the table in any non-supposed way possible).

as explained in the BindableFunction’s limitations
Tables passed as arguments to bindable events and callbacks are copied
If you don’t want this you could only return the changes and manually add the changes again
something like this

-- script1
bindableFunction.OnInvoke = function(t)
	return {cash = t.cash - 10}
end

-- script2
local t = {
	cash = 100,
	gems = 200
}

local changes = bindableFunction:Invoke(t)

for key, value in changes do
	t[key] = value
end

print(t)
2 Likes

All code shown is occurring on the server. I’m using a bindable function to retrieve the value. :confused:

-- Assign key (typically a tool)
function PlayerService.AssignKey(player : Player, key : table) : boolean
    print(isServer)
    local data = PlayerService.GetPlayerData(player)
    if data["key"] then return false end
    data["key"] = key
    print(PlayerService.GetPlayerData(player)) -- for testing only
    return true
end

The same is true for bindable events

Ah, okay. Thank you. I was suspecting it had something to do with return limitations but couldn’t narrow it down to the BindableFunction.

I wanted to avoid passing it back, but seems that’s the best solution. :smiling_face:

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.