What Other Ways Are There Of Saving A Players Data

Hello, I’ve been trying to make a script that saves a player’s values

This is where the values are located under player (each folder, Chloe, KEKI, Radley and Sabaku have 3 values in them)

Annotation 2020-08-01 134710

I’ve tried to save the values by looping through each of the folders and adding the values to a table specific to that folder, and then saving the table to the player.

Like this

  game.Players.PlayerRemoving:Connect(function(plr)
	local succ, msg = pcall(function()
		local Chloe = {}
		for _, v in pairs (plr.Cards:GetChildren()) do
			local card = v 
			for _, v in pairs (card:GetChildren()) do
				if card.Name == "Chloe" then
					table.insert(Chloe,{v.Name, v.Value})
				end
			end
		end
		ds:SetAsync("Chloe"..plr.UserId, Chloe)
		ds:SetAsync("KEKI"..plr.UserId, KEKI)
		ds:SetAsync("Radley"..plr.UserId, Radley)
		ds:SetAsync("Sabaku"..plr.UserId, Sabaku)
	end)
	
	if not succ then
		warn("Problem with saving data "..msg)
	end
end)

Is there a different way to do this because saving it to a table like the way I’m doing isn’t working for me. (I don’t get any errors in the output)

In the future, please use correct indentation when quoting your code.

There are some redundancy issues on your code, instead of always using v for a for iteration, put a different variable name.

local Chloe = {}
for _, playerCards in pairs (plr.Cards:GetChildren()) do
    if(playerCards.Name == "Chloe") then
        for _, v in pairs (playerCards:GetChildren()) do
            table.insert(Chloe, { [v.Name] = v.Value })
        end
    end
end

Try something like that.

1 Like

It’s still not working. Is there a problem with the way I’m getting the player’s data?

local Chloe = ds:GetAsync("Chloe".. plr.UserId)

if v.Name == "Chloe" and Chloe ~= nil then
			local succ, msg = pcall(function()
					lvl.Value = Chloe
					cardAmount.Value = Chloe
					cardOwned.Value = Chloe
			end)
				if not succ then
					warn("Problem with getting and setting data "..msg)
			end
end

Are you ever creating the value instances for the cards?

Also, I’d probably use a dictionary for this as the timeout for datastores is 6 per minute. I can help with that if you’d like.

1 Like

Yeah, I’m doing it like this

local ds = game:GetService("DataStoreService"):GetDataStore("CardSaving")
local cards_folder = game.ServerStorage.Cards

game.Players.PlayerAdded:Connect(function(plr)
  local cards_fold = Instance.new("Folder")
	  	cards_fold.Name = "Cards"
  	  	cards_fold.Parent = plr
	
	for _, v in pairs (cards_folder:GetChildren()) do
		
		local card = Instance.new("Folder")
		card.Name = v.Name
		card.Parent = cards_fold
		
		local cardOwned = Instance.new("BoolValue")
		cardOwned.Name = "CardOwned"
		cardOwned.Parent = card
		
		local cardAmount = Instance.new("IntValue")
		cardAmount.Name = "CardAmount"
		cardAmount.Parent = card
		
		local lvl = Instance.new("IntValue")
		lvl.Name = "Level" 
		lvl.Parent = card
		
		local Chloe = ds:GetAsync("Chloe".. plr.UserId)
		local KEKI = ds:GetAsync("KEKI".. plr.UserId)
		local Radley = ds:GetAsync("Radley".. plr.UserId)
		local Sabaku = ds:GetAsync("Sabaku".. plr.UserId)
		if v.Name == "Chloe" and Chloe ~= nil then
			local succ, msg = pcall(function()
					lvl.Value = Chloe
					cardAmount.Value = Chloe
					cardOwned.Value = Chloe
1 Like

Yes please! I don’t know too much about dictionaries.

I wouldn’t recommend using values in your datastore. Tables are much more flexible when it comes to storing different types of data. For example, if you are making an inventory system using a table to store the slots will be much more efficient and easier to store then using values. Hopefully this helped! :3

1 Like

So, you’re going to need one datastore per player instead of the 4 you are using, you can totally add more values if you need to in the future.

For this, I would do something like this, I also recommend you save the type of value to create:

For loading:

local succ, errormsg = pcall(function()
    data = Datastore:GetAsync(yourKey)
end

if succ and data ~= nil then -- if it succeeded and the player has played before (checking if the data is nil or not)
    for i,v in pairs(data) do
        local currentCards = Instance.new("Folder", yourFolder)
        currentCards.Name = i -- This will be the index, let's say it's Chloe for example.

        local cardOwned = Instance.new("BoolValue", currentCards) -- Create all of the values that go into Chloe's folder.
        cardOwned.Name = "CardOwned"
        cardOwned.Value = v.CardOwned
        
        local cardAmount = Instance.new("IntValue", currentCards)
        cardAmount.Name = "CardAmount"
        cardAmount.Value = v.CardAmount
        
        local level = Instance.new("IntValue", currentCards)
        level.Name = "Level"
        level.Value = v.Level
    else -- if it succeeded but the data is nil, so the player hasn't joined before, same as above basically. Keep in mind that the values should be default. You are going to have to create your own folders for this though.
        local availableCards = {"Chloe", "KEKI", "Radley", "Sabaku"} -- just to determine what cards you can get
        for i,v in pairs(availableCards) do
            local currentCards = Instance.new("Folder", yourFolder)
            currentCards.Name = i -- makes a folder called "Chloe" for example.

            local cardOwned = Instance.new("BoolValue", currentCards) 
            cardOwned.Name = "CardOwned"
            cardOwned.Value = false
        
            local cardAmount = Instance.new("IntValue", currentCards)
            cardAmount.Name = "CardAmount"
            cardAmount.Value = 0
        
            local level = Instance.new("IntValue", currentCards)
            level.Name = "Level"
            level.Value = 0
        end
    end
else
    warn("Error retrieving data for "..player.Name..": "..errormsg
end

For saving:

local dataToSave = {}
local myFolder = --[[wherever the player's data folder is]]

for i,v in pairs(myFolder:GetChildren()) do
    dataToSave[v.Name] = { -- ["Chloe"] = {
       ["CardOwned"] = v:FindFirstChild("CardOwned").Value,
       ["CardAmount"] = v:FindFirstChild("CardAmount").Value,
       ["Level"] = v:FindFirstChild("Level").Value
    }
end

local succ, errormsg = pcall(function()
    DS:SetAsync(myKey, dataToSave)
end

To better visualize, here’s an example of how the data’s table looks:

local data = {
   ["Chloe"] = {
        ["CardOwned"] = true,
        ["CardAmount"] = 12345,
        ["Level"] = 123
        },
    ["KEKI"] = {
        ["CardOwned"] = true,
        ["CardAmount"] = 12345,
        ["Level"] = 123
    },
    ["Radley"] = {
        ["CardOwned"] = true,
        ["CardAmount"] = 12345,
        ["Level"] = 123
        },
    ["Sabaku"] = {
        ["CardOwned"] = true,
        ["CardAmount"] = 12345,
        ["Level"] = 123
    }
}
1 Like