Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

Data deserialization and instance serialization problems?

Asked by
valchip 789 Moderation Voter
5 years ago
Edited 5 years ago

I am trying to make a script which saves the instances in the workspace after you leave. And the way I am doing this is:

Game runs. Game gets the data of the game from the datastore, a JSON encoded array. Data get JSON decoded into an array. Data (the array ) then gets deserialized by my own deserializer. For every new child added or removed the workspace array gets the elements of the workspace and their properties and adds them in the array, currently it only gets 5 properties and can only save parts which contain these properties, does not save the baseplate, camera, the terrain or my character. Basically here the serialization process occurs. Game shuts down. The workspace array gets JSON encoded. The workspace array gets saved in the datastore.

OK so the array should look like this:

local Workspace = {
    {
Position = {X,Y,Z};
Size= {x,y,z}, Name= {String};
ClassName = {String};
Anchored = {Boolean}
    }
}

And what my deserializer does is that it loops through every dictionary inside the workspace array and it looks for an index called ClassName, it creates a new instance based off the class name and after that its properties get assigned based on the other indexes. That is the function of the decoder. Code:

function DecodeDictionary(dic)
    local inst = nil
    for i, v in pairs(dic) do
        for a, b in pairs(v) do
            if a == "ClassName" then
                inst = Instance.new(b[1])
            end
        end
        for a, b in pairs(v) do
            if a == "Size" then
                inst.Size = Vector3.new(b[1], b[2], b[3])
            elseif a == "Position" then
                inst.Position = Vector3.new(b[1],b[2],b[3])
            elseif a == "Name" then
                inst.Name = b[1]
            elseif a == "Anchored" then
                inst.Anchored = b[1]
            end     
        end
            end
    inst.Parent = workspace
end

And now about my serializer, my serializer runs every time a workspace element gets added or removed. Every time it runs it doesn't save the baseplate camera or terrain, it doesn't save my character either. Code:

local Workspace = {}

local function updateDictionary()
    for i, v in pairs(workspace:GetChildren()) do
        if v.Name ~= "Camera" and v.Name ~= "Terrain" and v.Name ~= "Baseplate" and v.Name ~= "vamik64" then
            print(v.Name)
            local a = {}
            a.Position = {v.Position.X, v.Position.Y, v.Position.Z}
            a.Size = {v.Size.X, v.Size.Y, v.Size.Z}
            a.Name = {v.Name}
            a.Anchored = {v.Anchored}
            a.ClassName = {v.ClassName}
            table.insert(Workspace, a)
        else print("can't save: ".. v.Name) end 
end

    for i, v in pairs(Workspace) do
        print(v)
        for a, b in pairs(v) do
            print(a,b)
            for x,d in pairs(b) do
                print(x,d)
            end
        end
end
    dataTOsave = HttpService:JSONEncode(Workspace)
end

The problem is that when the game shuts down, every element in the workspace gets removed except camera, terrain and baseplate. The workspace array turns into an empty array and the empty array gets saved in my datastore.

Full code:

local DSS = game:GetService("DataStoreService")
local HttpService = game:GetService("HttpService")
local serverDSS = DSS:GetDataStore("serverDSS")
local Players = game:GetService("Players")

local Workspace = {}

local function updateDictionary()
    for i, v in pairs(workspace:GetChildren()) do
        if v.Name ~= "Camera" and v.Name ~= "Terrain" and v.Name ~= "Baseplate" and v.Name ~= "vamik64" then
            print(v.Name)
            local a = {}
            a.Position = {v.Position.X, v.Position.Y, v.Position.Z}
            a.Size = {v.Size.X, v.Size.Y, v.Size.Z}
            a.Name = {v.Name}
            a.Anchored = {v.Anchored}
            a.ClassName = {v.ClassName}
            table.insert(Workspace, a)
        else print("can't save: ".. v.Name) end 
end

    for i, v in pairs(Workspace) do
        print(v)
        for a, b in pairs(v) do
            print(a,b)
            for x,d in pairs(b) do
                print(x,d)
            end
        end
end
    dataTOsave = HttpService:JSONEncode(Workspace)
end

function DecodeDictionary(dic)
    local inst = nil
    for i, v in pairs(dic) do
        for a, b in pairs(v) do
            print(a, unpack(b))
            if a == "ClassName" then
                inst = Instance.new(b[1])
            end
        end
        for a, b in pairs(v) do
            print(a, unpack(b))
            if a == "Size" then
                inst.Size = Vector3.new(b[1], b[2], b[3])
            elseif a == "Position" then
                inst.Position = Vector3.new(b[1],b[2],b[3])
            elseif a == "Name" then
                inst.Name = b[1]
            elseif a == "Anchored" then
                inst.Anchored = b[1]
            end     
        end
            end
    inst.Parent = workspace
end

local JSONdata = serverDSS:GetAsync("server_key")
if JSONdata ~= nil and JSONdata ~= "[]" then
    local data = HttpService:JSONDecode(JSONdata)
    DecodeDictionary(data)
end


workspace.ChildAdded:Connect(function()
    updateDictionary()
end)

workspace.ChildRemoved:Connect(function()
    updateDictionary()
end)

game:BindToClose(function()
    print(dataTOsave)
    serverDSS:SetAsync("server_key", dataTOsave)
end)

The code is not well-written as I am making a game serializer and deserializer. These are the early stages of development.

P.S: I am aware that if there are 2 servers running at the same time this won't work properly

Answer this question