Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
COMMUNITY QUESTION

*Followup* dictionary in datastore?

So I took some advice and made some changes, but am facing another problem; the else statement on line 9 is firing. So my question is, am I saving the datastore incorrectly? When a player leaves the game it prints all the saving messages as it should, so im perplexed as to why its not getting anything when a player joins. Any and all help is greatly appreciated! :)

local Data = game:GetService("DataStoreService"):GetDataStore("Data123")

game.Players.PlayerAdded:Connect(function(Player)
	pcall(function()
		local PlayerData = Data:GetAsync(Player.UserId)
		if PlayerData then
			setStats(Player, PlayerData.Stats)
			setBackpack(Player, PlayerData.Backpack)
		else
			defaultStats(Player)
			game.ReplicatedStorage.Weapons.StarterSword:Clone().Parent = Player:WaitForChild("Backpack")
		end
		local CanSave = Instance.new("BoolValue", Player)
		CanSave.Name = "CanSave"
		CanSave.Value = true
	end)
end)

--Stats Portion

function setStats(Player, SavedStats)
	local Stats = createStats(Player)
	if SavedStats then
		print("Got SavedStats")
		Stats.Level.Value = SavedStats.Level
		Stats.Exp.Value = SavedStats.Exp
		Stats.Gold.Value = SavedStats.Gold
	end
end

function defaultStats(Player)
	print("Defaulting stats for " .. Player.Name)
	local Stats = createStats(Player)
	Stats.Level.Value = 1
	Stats.Exp.Value = 0
	Stats.Gold.Value = 25
end

function createStats(Player)
	local Stats = Instance.new("Folder", Player)
	Stats.Name = "Stats"
	
	local Level = Instance.new("IntValue", Stats)
	Level.Name = "Level"	
	
	local Exp = Instance.new("IntValue", Stats)
	Exp.Name = "Exp"
	
	local Gold = Instance.new("IntValue", Stats)
	Gold.Name = "Gold"
	
	return Stats
end

function getStats(Player)
	local PlayerStats = {}
	if Player:FindFirstChild("Stats") then
		for _, Stat in pairs(Player.Stats:GetChildren()) do
			print("Saving " .. Player.Name .. "'s " .. Stat.Name .. " = " .. Stat.Value)
			PlayerStats[Stat.Name] = Stat.Value
		end
	end
	return PlayerStats
end

--Backpack Portion

function setBackpack(Player, SavedWeapons)
	if SavedWeapons then
		print("Got SavedWeapons")
		for _, WeaponName in pairs(SavedWeapons) do
			print("Weapon for loop")
			local Weapon = game.ReplicatedStorage.Weapons:FindFirstChild(WeaponName)
			if Weapon then
				print("Loading " .. Weapon.Name)
				Weapon:Clone().Parent = Player:WaitForChild("Backpack")
				Weapon:Clone().Parent = Player:WaitForChild("StarterGear")
			end
		end
	else
		print("SavedWeapons else fired")
	end	
end

function getBackpack(Player)
	local WeaponsTable = {}
	local EquippedWeapon = getEquippedWeapon(Player)
	if EquippedWeapon then
		print("Saving " .. Player.Name .. "'s " .. EquippedWeapon.Name)
		table.insert(WeaponsTable, EquippedWeapon.Name)
	end
	for _, Weapon in pairs(Player.Backpack:GetChildren()) do
		print("Saving " .. Player.Name .. "'s " .. Weapon.Name)
		table.insert(WeaponsTable, Weapon.Name)
	end
	return WeaponsTable
end

function getEquippedWeapon(Player)
	local Character = game.Workspace:FindFirstChild(Player.Name)
	if Character then
		for _, Item in pairs(Character:GetChildren()) do
			if Item:IsA("Tool") then
				return Item
			end
		end	
	end
	return
end

game.Players.PlayerRemoving:Connect(function(Player)
	pcall(function()
		print("Player Removing")
		if Player.CanSave then
			print(Player.Name .. " is saving")
			local DataDictionary = {
				Stats = getStats(Player),
				Backpack = getBackpack(Player)
			}
			Data:SetAsync(Player.UserId, DataDictionary)	
		else
			print(Player.Name .. " can't save")
		end
	end)
end)

1 answer

(Assuming you've been testing in studio)

Unless you have the setting labelled Enable Studio Access to API Services set to true (can be found in the game settings), the data won't actually save between test sessions. You can turn this setting on (don't recommend if this game is live or planning to go live) or just test on the roblox client itself. Everything you are doing looks right and there is no immediate problem. One thing that I'd like to point out though is your misuse of pcall.

Your call to pcall should only wrap the call to the datastore and that's it. It shouldn't include the rest of the logic because that breaks the whole point of protected call. Instead, I would do something like this:

local success , result = pcall(function()
	return Data:GetAsync(Player.UserId)
end)
if success then
	--results would be the data retrieved in this case
	--normal stuff
else
	--handle error
	--results would be the error object in this case
	warn(result)
end

3 comments

1

pcall(Data.GetAsync, Data, Player.UserId) works the same

0

Yes I have API Services enabled, thanks for the suggestion. And thanks for clearing up the pcall thing, I wasn't too sure of how it was to be used.

0

np

This discussion is preserved as it was. New answers, comments, and votes are closed.