Hello developers! In my quest to become much better with datastores there is a question I often ponder, and that question is: Can you save multiple tables in a datastore to a single key?
Now, the reason I would like to do this is so I can I reduce the usage of :GetAsync() and :SetAsync() so I don’t put too much pressure on the datastore. I wanna be efficient with how I am saving the data. If using embedded tables is inefficient/a very horrible idea, then I am fine with that. That is after all why I am asking that question right now.
So, my problem would be wondering if multiple tables can be saved to a single key of a datastore to be more efficient with how often I am using :GetAsnyc() and :SetAsync().
To try and solve this problem I took to the Dev Forum initially. I searched to try and find any posts about the topic, and from what Is searched there appears to be nothing.
I also decided to try making my own script seeing if I could do it on my own.
Here is my very scuffed script:
local dataStoreService = game:GetService("DataStoreService")
local players = game:GetService("Players")
local dataStore = dataStoreService:GetDataStore("TestData")
local data = {
leaderstats = {
["ValueType"] = "NumberValue",
["ParentFolder"] = "leaderstats",
["Strength"] = 0,
["Coins"] = 0,
["Gems"] = 0,
["Rebirths"] = 0
},
MultiplierData = {
["ValueType"] = "NumberValue",
["ParentFolder"] = "MultiplierData",
["RebirthStrengthMultiplier"] = 1,
["RebirthCoinsMultiplier"] = 1,
["RebirthGemMultiplier"] = 1,
["PetStrengthMultiplier"] = 0,
["PetCoinsMultiplier"] = 0,
["PetGemMultiplier"] = 0
},
EquippedItems = {
["ValueType"] = "StringValue",
["EquippedSword"] = "SwordName",
["ParentFolder"] = "EquippedItems",
["PetSlot1"] = "",
["PetSlot2"] = "",
["PetSlot3"] = "",
["PetSlot4"] = "",
["PetSlot5"] = "",
["PetSlot6"] = "",
["PetSlot7"] = "",
["PetSlot8"] = "",
["PetSlot9"] = "",
["PetSlot10"] = ""
},
PurchasedSwords = {
["ValueType"] = "BoolValue",
["ParentFolder"] = "PurchasedSwords",
["Sword1"] = true,
["Sword2"] = false,
["Sword3"] = false
}
}
game.Players.PlayerAdded:Connect(function(player)
local dataFromStore = nil
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local multiplierData = Instance.new("Folder")
multiplierData.Name = "MultiplierData"
multiplierData.Parent = player
local equippedItems = Instance.new("Folder")
equippedItems.Name = "EquippedItems"
equippedItems.Parent = player
local purchasedSwords = Instance.new("Folder")
purchasedSwords.Name = "PurchasedSwords"
purchasedSwords.Parent = player
--If this becomes a hassel I will separate it into 4 different tables to assign data to. Let's hope this loop ages like wine and not milk -Exodia
for _, embeddedTable in pairs(data) do
for name, value in pairs(embeddedTable) do
if name ~= "ValueType" and name ~= "ParentFolder" then
local valueToMake = embeddedTable.ValueType
local new = Instance.new(tostring(valueToMake))
new.Name = name
new.Value = value
new.Parent = player:FindFirstChild(embeddedTable.ParentFolder)
end
end
end
local success, err = pcall(function()
print("Retrieving Data")
dataFromStore = dataStore:GetAsync("uid-".. player.UserId)
end)
if success then
print("Getting PlayerData for: ".. player.Name ..", ID: ".. player.UserId)
if dataFromStore then
for _, folder in pairs(player:GetChildren()) do
for name, value in pairs(dataFromStore) do
if folder[name] ~= nil then
folder[name].Value = value --This feels scuffed AF but it will hopefully work
end
end
end
print("Data (Hopefully) Loaded for: ".. player.Name ..", ID: ".. player.UserId)
else
print("Creating new PlayerData for: ".. player.Name ..", ID: ".. player.UserId)
end
else
warn("An error occurred while loading PlayerData. Please Contact a Developer incase data is lost.")
end
end)
game.Players.PlayerRemoving:Connect(function(player)
local dataForStore = {
leaderstats = {},
MultiplierData = {},
EquippedItems = {},
PurchasedItems = {}
}
--I am doing separate loops for each table of data to be safe
for name, value in pairs(player.leaderstats:GetChildren()) do
dataForStore.leaderstats[value.Name] = value.Value
end
for name, value in pairs(player.MultiplierData:GetChildren()) do
dataForStore.MultiplierData[value.Name] = value.Value
end
for name, value in pairs(player.EquippedItems:GetChildren()) do
dataForStore.EquippedItems[value.Name] = value.Value
end
for name, value in pairs(player.PurchasedSwords:GetChildren()) do
dataForStore.PurchasedItems[value.Name] = value.Value
end
local success, err = pcall(dataStore.SetAsync, dataStore, "uid-".. player.UserId, dataForStore)
if success then
print("Successfully Saved Data for: "..player.Name)
end
end)
I am using some sample data from a simulator game I am currently scripting. I wanted to test out the idea of using embedded tables to see if I could make an efficient method of saving data for my group’s game. Feel free to judge and critique however you’d like.