Table replication issues

I am making a system where a table needs to be sent from the server to the client. I have successfully connection the remote function on either end, however there is a really frustrating problem with the replication.

The server side code:
Screenshot 2024-08-07 182901

The client side code:
image

The output:
image

The only thing being sent over is the 1st value. The tables being sent over only have a Color3 and a number inside of them, so I don’t understand why they aren’t being replicated, since Color3 and numbers should be fine to send over the client-server boundary.

Assuming no instances are in there, a temporary fix is to use HttpService functions to send the table over as a string:

--for returning
return game.HttpService:JSONEncode(stages)
--for decoding
local stages = game.HttpService:JSONDecode(response)

Both of these functions are utility functions often used for understanding HTTP responses and don’t require you to enable http requests in order to work.

2 Likes

The Color3 key gets removed when I use this method

REFERENCING THE QUOTED REPLY. There may always be a better solution, but HttpService is the easiest one to my knowledge.

To fix this, you can implement the concept of Serialization / Deserialization. This block of code (courtesy of @starmaq via the ‘How to save parts, and the idea of Serialization’ Devforum post) can convert incompatible datatypes into compatible datatypes. You can use this concept while iterating through each piece of information stored in your tables when you want to send them between the clients and the server. Really recommend you skim through the entire post though, as it gives you a lot of useful information.

local function Serialize(prop) --prop will be the property's value type
 	local type = typeof(prop) --the type of the value
	local r --the returned value afterwards
	if type == "BrickColor" then --if it's a brickcolor
		r = tostring(prop)
	elseif type == "CFrame" then --if it's a cframe
		r = {pos = Serialize(prop.Position), rX = Serialize(prop.rightVector), rY = Serialize(prop.upVector), rZ = Serialize(-prop.lookVector)}
	elseif type == "Vector3" then --if it was a vector3, this would apply for .Position or .Size property
		r = {X = prop.X, Y = prop.Y, Z = prop.Z}
	elseif type == "Color3" then --color3
		r = {Color3.toHSV(prop)}
	elseif type == "EnumItem" then --or an enum, like .Material or .Face property
		r = {string.split(tostring(prop), ".")[2], string.split(tostring(prop), ".")[3]} 
	else --if it's a normal property, like a string or a number, return it
		r = prop
	end
	return r 
end

local function Deserialize(prop, value)
	local r --this will be the returned deserialized property
	if prop == "Position" or prop == "Size" then
		r = Vector3.new(value.X, value.Y, value.Z)
	elseif prop == "CFrame" then
		r = CFrame.fromMatrix(Deserialize("Position", value.pos), Deserialize("Position", value.rX), Deserialize("Position", value.rY), Deserialize("Position", value.rZ))
	elseif prop == "BrickColor" then
		r = BrickColor.new(value)
	elseif prop == "Color" or prop == "Color3" then
		r = Color3.fromHSV(unpack(value))
	elseif prop == "Material" or prop == "Face" or prop == "Shape" then --you probably have to fill this one depending on the properties you're saving!
		r = Enum[value[1]][value[2]]
	else
		r = value --it gets here if the property 
	end
	return r --return it
end

If you are to use these functions, all I’d recommend is that you put them in a module script that you can reference across multiple scripts, as you may find yourself needing them for more than one piece of your game.

TLDR: user data isn’t really handled well with JSON encoding and you need to convert these pieces of information into encodable data

EDIT: simple wording changes

1 Like

In combination with what everyone else said:

In this case, your table has missing indices between 1 → 21 (and so on), so only the first index was sent

2 Likes

That’s very useful info, thanks!

That’s probably the issue here, nice catch! It can probably be fixed by converting the keys to strings instead, so:

local t = GetStageSizes()
local stages = {}
for k, v in pairs(t) do
	stages[tostring(k)] = v
end
print(stages)
return stages
1 Like

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