字典帮助/数据存储

问题描述 投票:1回答:2

问题是我有一个字典,其中存放了我所有的数据,应该能够将其转换为复制存储中的目录,并且所有值均为字符串,然后在播放器离开时变为具有所有键的字典。但是,我无法弄清楚如何变成字典(带键)。

我花了几个小时进行测试,但是在第一层值之后,我无法弄清楚将更深的值和键输入表中的方法

local DataTable = 
{
    ["DontSave_Values"] =
    {
        ["Stamina"] = 100;
    };
    ["DontSave_Debounces"] = 
    {

    };
    ["TestData"] = 1;
    ["Ship"] = 
    {
        ["Hull"] = "Large_Ship";
        ["Mast"] = "Iron_Tall";
        ["Crew"] = 
        {
            ["Joe One"] = 
            {
                ["Shirt"] = "Blue";
                ["Pants"] = "Green"
            };
            ["Joe Two"] = 
            {
                ["Shirt"] = "Silver";
                ["Pants"] = "Brown";
                ["Kids"] = 
                {
                    ["Joe Mama1"] =
                    {
                        ["Age"] = 5
                    };
                    ["Joe Mama2"]=
                    {
                        ["Age"] = 6
                    };
                }
            };
        }
    };
    ["Level"] = 
    {
    };
    ["Exp"] = 
    {
    };
}
------Test to see if its an array
function isArray(Variable)
    local Test = pcall(function() 
        local VarBreak = (Variable.." ")
    end)
    if Test == false then
        return true
    else 
        return false
    end
end

------TURNS INTO FOLDERS 
function CreateGameDirectory(Player, Data)
    local mainFolder = Instance.new("Folder")
    mainFolder.Parent = game.ReplicatedStorage
    mainFolder.Name = Player.UserId
    local function IterateDictionary(Array, mainFolder)
        local CurrentDirectory = mainFolder
        for i,v in pairs(Array) do
            if isArray(v) then
                CurrentDirectory = Instance.new("Folder", mainFolder)
                CurrentDirectory.Name = i
                for o,p in pairs(v) do
                    if isArray(p) then
                        local TemporaryDir = Instance.new("Folder", CurrentDirectory)
                        TemporaryDir.Name = o
                        IterateDictionary(p, TemporaryDir)
                    else
                        local NewValue = Instance.new("StringValue", CurrentDirectory)
                        NewValue.Name = o
                        NewValue.Value = p
                    end
                end
            else
                local value = Instance.new("StringValue", mainFolder)
                value.Name = i
                value.Value = v
            end
        end
    end
    IterateDictionary(Data, mainFolder)
end


------To turn it back into a table
function CreateTable(Player)
    local NewDataTable = {}
    local Data = RS:FindFirstChild(Player.UserId)
    local function DigDeep(newData, pData, ...)
        local CurrentDir = newData
        for i,v in pairs(pData:GetChildren()) do
            if string.sub(v.Name,1,8) ~= "DontSave" then

            end
        end
    end
    DigDeep(NewDataTable, Data)
    return NewDataTable
end

我希望玩家离开时可以运行createtable函数,并将复制存储中的所有实例转回到带有键的字典中。

lua roblox
2个回答
0
投票
为什么不只在数据表中存储额外信息,以帮助轻松地来回转换。例如,为什么不让您的数据如下所示:

local ExampleData = { -- hold onto your special "DON'T SAVE" values as simple keys in the table. DONTSAVE_Values = { Stamina = 0, }, -- but every element under ReplicatedStorage will be used to represent an actual Instance. ReplicatedStorage = { -- store an array of Child elements rather than another map. -- This is because Roblox allows you to have multiple children with the same name. Name = "ReplicatedStorage", Class = "ReplicatedStorage", Properties = {}, Children = { { Name = "Level", Class = "NumberValue", Properties = { Value = 0, }, Children = {}, }, { Name = "Ship", Class = "Model", Properties = {}, Children = { { -- add all of the other instances following the same pattern : -- Name, Class, Properties, Children }, }, }, }, -- end list of Children }, -- end ReplicatedStorage element };

您可以使用简单的递归函数创建此表:

-- when given a Roblox instance, generate the dataTable for that element local function getElementData(targetInstance) local element = { Name = targetInstance.Name, Class = targetInstance.ClassName, Properties = {}, Children = {}, } -- add special case logic to pull out specific properties for certain classes local c = targetInstance.ClassName if c == "StringValue" then element.Properties = { Value = targetInstance.Value } -- elseif c == "ADD MORE CASES HERE" then else warn(string.format("Not sure how to parse information for %s", c)) end -- iterate over the children and populate their data for i, childInstance in ipairs(targetInstance:GetChildren()) do table.insert( element.Children, getElementData(childInstance)) end -- give the data back to the caller return element end -- populate the table local Data = { ReplicatedStorage = getElementData(game.ReplicatedStorage) }

现在Data.ReplicatedStorage.Children应该具有整个文件夹的数据表示。您甚至可以将整个表保存为字符串,方法是将其传递给HttpService:JSONEncode()

准备将它们转换回实例时,请使用存储的数据为您提供有关如何重新创建元素的足够信息:

local function recreateElement(tableData, parent) -- special case ReplicatedStorage if tableData.Class == "ReplicatedStorage" then -- skip right to the children for i, child in ipairs(tableData.Children) do recreateElement(child, parent) end -- quick escape from this node return end -- otherwise, just create elements from their data local element = Instance.new(tableData.Class) element.Name = tableData.Name -- set all the saved properties for k, v in pairs(tableData.Properties) do element[k] = v end -- recreate all of the children of this element for i, child in ipairs(tableData.Children) do recreateElement(child, element) end -- put the element into the workspace element.Parent = parent end -- populate the ReplicatedStorage from the stored data recreateElement( Data.ReplicatedStorage, game.ReplicatedStorage)

您应谨慎选择如何以及何时选择保存此数据。如果您正在玩多人游戏,则应注意这种逻辑只会为第一个加入服务器的玩家更新ReplicatedStorage。否则,您将冒着玩家加入并覆盖其他所有人所做的一切的风险。 

由于无法迭代Roblox实例的属性,因此,您必须手动更新getElementData函数以正确存储每种对象类型所需的信息。希望这会有所帮助!


0
投票
[如果其他人遇到此问题,我使用的解决方案只是将实例海峡转换为JSON格式(我使用名称作为键)。这样我就可以保存它,然后当播放器重新加入时,我只是使用JSONDecode将其转换为所需的字典。

function DirToJSON(Player) local NewData = RS:FindFirstChild(Player.UserId) local JSONstring="{" local function Recurse(Data) for i, v in pairs(Data:GetChildren()) do if v:IsA("Folder") then if #v:GetChildren() < 1 then if i == #Data:GetChildren()then JSONstring=JSONstring..'"'..v.Name..'":[]' else JSONstring=JSONstring..'"'..v.Name..'":[],' end else JSONstring=JSONstring..'"'..v.Name..'":{' Recurse(v) if i == #Data:GetChildren()then JSONstring=JSONstring..'}' else JSONstring=JSONstring..'},' end end else if i == #Data:GetChildren()then JSONstring=JSONstring..'"'..v.Name..'":"'..v.Value..'"' else JSONstring=JSONstring..'"'..v.Name..'":"'..v.Value..'",' end end end end Recurse(NewData) JSONstring = JSONstring.."}" return(JSONstring) end

© www.soinside.com 2019 - 2024. All rights reserved.