Hi guys.
In short: I have system which sets data like that:
local Data = {}
local CurId = 1
while CurId < 100 do
Data[CurId] = "somedata"
CurId += 1
end
Data[23] = nil
Data[64] = nil
RemoteFunction.OnServerInvoke = function(
return Data
end)
When clients retireves the data with the RemoteFunction above, it gets only 1-22 elements, and no any other. Solutions I have found so far are:
Making Data[a]=“b” element which will never get erased
Make counter start from 2
But is there any better ways of doing this?
This is probably a really bad solution but if you want it to be sure to be treated as a dictionary you could make all the keys strings using tostring and then index it that way. Also, use a for loop (for CurId = 1, 100 do end) instead of a while loop for that.
In my case, I add values in completely diffirent way, this was just for example. Converting values to strings is ok until 9999th index, which in my case will be bad, when I’ll meet 100k-th index…
Each object is one Data index used, for health, Id, and such. Players can build islands up to 5k parts, and max server size is 49 players, so solely from islands I can get 245k indexes, not counting other generated objects.
Rn with fix which makes start index 2 instead of 1 it works. 10k index does nothing (in terms no errors specifically to it). Even 1000000th index does nothing bad.
Problem is EXACTLY if there’s present index 1
The documentation for remote events pretty clearly calls out that you should not be using nil values for any index, for exactly this reason. Under the hood, Roblox serializes data sent through events to be able to pass it through the C++ engine back end, and that serialization is unable to handle certain things, including holes in arrays like this. Since your table contains a numeric index starting with 1, it’s inferring that it should be treated like an array.
If you intend for your data to be stored as an array, you should avoid holes by using table.remove which closes the gap by shifting all the elements that come after the removed value.
If you intend for your data to be stored as a dictionary, you should avoid using numeric indexes that start with 1. You could either tostring() your keys, give them any other string names, or perhaps you might even try converting it to JSON via HttpService before sending it (I think that would work, but I haven’t tested it- this would also require converting back from JSON on the receiving side)
In my opinion, the simplest and best solution for you here (assuming you want it to be a dictionary) is to just tostring() your numeric keys so that all your keys are strings and it would correctly be treated as a dictionary.
They matter a lot, cuz indexes don’t change when assigned to object, but can be removed, if, for example, part is destroyed. New added indexes are always new one.
You can try encoding it into a format that the remote event can send. For example, you can change it from a dictionary into an array containing 2-item arrays, with the first item being the key and the second being the value. Then, you can simply decode them on the client end.
Here’s some code I wrote up that does that:
local Array = {
[1] = "1",
[2] = "2",
[3] = "3",
[5] = "5",
[10] = "10"
}
warn("Initial:")
print(Array)
function Encode(Input)
local New = {}
for key, val in Input do
table.insert(New, {key, val})
end
return New
end
function Decode(Encoded)
local Result = {}
for _, pair in Encoded do
Result[pair[1]] = pair[2]
end
return Result
end
local Encoded = Encode(Array)
warn("Encoded:")
print(Encoded)
local Decoded = Decode(Encoded)
warn("Decoded:")
print(Decoded)