Issue with Datastore Script

Hello,

I am currently using the script below to save a player’s leaderstats, which are Credits, Playtime, and Prizes Won. The script also checks to see if a player has data from a previous datastore, and transfers it over if they do.

However, if the player has data from the previous datastore, it fails to load and their data is set to (0, 0, 0). What is causing the issue?

Thank You! :slight_smile:

local DataStoreService = game:GetService("DataStoreService")
local newDataStore = DataStoreService:GetDataStore("LeaderstatsData") -- New DataStore
local oldDataStoreA = DataStoreService:GetDataStore("LeaderstatsData") -- Old Credits
local oldDataStoreB = DataStoreService:GetDataStore("LeaderstatsData2") -- Old Playtime
local oldDataStoreC = DataStoreService:GetDataStore("LeaderstatsData3") -- Old Prizes Won

-- Default player data
local function getDefaultData()
	return {
		Credits = 300,
		Playtime = 0,
		PrizesWon = 0
	}
end

-- Load player data
local function loadPlayerData(player)
	local success, playerData = pcall(function()
		return newDataStore:GetAsync("GameNamee_" .. player.UserId)
	end)

	if success and playerData then
		return playerData -- Data found in new DataStore
	else
		if not success then
			warn("Failed to load data for player", player.UserId)
		end

		-- Attempt to load from old DataStores
		local oldCredits, oldPlaytime, oldPrizesWon

		local successA = pcall(function()
			oldCredits = oldDataStoreA:GetAsync(player.UserId)
		end)

		local successB = pcall(function()
			oldPlaytime = oldDataStoreB:GetAsync(player.UserId)
		end)

		local successC = pcall(function()
			oldPrizesWon = oldDataStoreC:GetAsync(player.UserId)
		end)

		-- Check if any old data exists and migrate it
		if successA or successB or successC then
			warn("Migrating old data for player", player.UserId)
			local migratedData = {
				Credits = oldCredits or 300,
				Playtime = oldPlaytime or 0,
				PrizesWon = oldPrizesWon or 0
			}

			-- Save migrated data to the new DataStore
			pcall(function()
				newDataStore:SetAsync("GameNamee_" .. player.UserId, migratedData)
			end)

			return migratedData
		else
			-- No data found in old DataStores, apply defaults
			return getDefaultData()
		end
	end
end
-- Save player data
local function savePlayerData(player)
	local playerData = {
		Credits = player.leaderstats.Credits.Value,
		Playtime = player.leaderstats.Playtime.Value,
		PrizesWon = player.leaderstats["Prizes Won"].Value
	}

	local success, errorMessage = pcall(function()
		newDataStore:SetAsync("GameNamee_" .. player.UserId, playerData)
	end)

	if not success then
		warn("Failed to save data for player", player.UserId, errorMessage)
	end
end

-- Player added event
game.Players.PlayerAdded:Connect(function(player)
	-- Create leaderstats folder
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player

	-- Create leaderstats values
	local credits = Instance.new("IntValue", leaderstats)
	credits.Name = "Credits"

	local playtime = Instance.new("IntValue", leaderstats)
	playtime.Name = "Playtime"

	local prizesWon = Instance.new("IntValue", leaderstats)
	prizesWon.Name = "Prizes Won"

	-- Load and apply player data
	local playerData = loadPlayerData(player)
	credits.Value = playerData.Credits
	playtime.Value = playerData.Playtime
	prizesWon.Value = playerData.PrizesWon
end)

-- Player removing event
game.Players.PlayerRemoving:Connect(savePlayerData)

-- Periodic autosave
task.spawn(function()
	while task.wait(60) do
		for _, player in pairs(game.Players:GetPlayers()) do
			savePlayerData(player)
		end
	end
end)
4 Likes

Does it actually get into the if statement where it checks for loaded old data? And you are sure the values are 0,0,0?? if it is all 0,0,0 and not 300,0,0 then maybe it is loading old data where everything is 0,0,0?

2 Likes

this should work (i haven’t got time to test it rn)

local DataStoreService = game:GetService("DataStoreService")
--                Different Name Here
local DataStoreName = "NameGame_"

local newDataStore = DataStoreService:GetDataStore("LeaderstatsData") -- New DataStore
local oldDataStoreA = DataStoreService:GetDataStore("LeaderstatsData") -- Old Credits
local oldDataStoreB = DataStoreService:GetDataStore("LeaderstatsData2") -- Old Playtime
local oldDataStoreC = DataStoreService:GetDataStore("LeaderstatsData3") -- Old Prizes Won

-- Default player data
local function getDefaultData()
	return {
		Credits = 300,
		Playtime = 0,
		PrizesWon = 0
	}
end

local function NoPlayerData(UserId)
	warn("No Data Found For", UserId)

	-- Attempt to load from old DataStores
	local oldCredits, oldPlaytime, oldPrizesWon

	local successA = pcall(function()
		oldCredits = oldDataStoreA:GetAsync(UserId)
	end)

	local successB = pcall(function()
		oldPlaytime = oldDataStoreB:GetAsync(UserId)
	end)

	local successC = pcall(function()
		oldPrizesWon = oldDataStoreC:GetAsync(UserId)
	end)

	-- Check if any old data exists and migrate it
	local migratedData = getDefaultData()

	
	if successA and oldCredits then
		warn("Migrating old data A for player", UserId)
		migratedData["Credits"] = oldCredits
	end

	if successB and oldPlaytime then
		warn("Migrating old data B for player", UserId)
		migratedData["Playtime"] = oldPlaytime
	end

	if successC and oldPrizesWon then
		warn("Migrating old data C for player", UserId)
		migratedData["PrizesWon"] = oldPrizesWon
	end

	-- Save migrated data to the new DataStore
	pcall(function()
		newDataStore:SetAsync(DataStoreName .. UserId, migratedData)
	end)

	return migratedData
end

-- Load player data
local function loadPlayerData(player)
	local success, playerData = pcall(function()
		return newDataStore:GetAsync(DataStoreName .. player.UserId)
	end)

	if not success then
		warn("Failed to load data for player", player.UserId)
		playerData = NoPlayerData(player.UserId)
	else
		if not playerData then
			playerData = NoPlayerData(player.UserId)
		else
			if not (#playerData > 0) then
				playerData = NoPlayerData(player.UserId)
			end
		end

		return playerData
	end
end
-- Save player data
local function savePlayerData(player)
	local playerData = {
		Credits = player.leaderstats.Credits.Value,
		Playtime = player.leaderstats.Playtime.Value,
		PrizesWon = player.leaderstats["Prizes Won"].Value
	}

	local success, errorMessage = pcall(function()
		newDataStore:SetAsync(DataStoreName .. player.UserId, playerData)
	end)

	if not success then
		warn("Failed to save data for player", player.UserId, errorMessage)
	end
end

-- Player added event
game.Players.PlayerAdded:Connect(function(player)
	-- Create leaderstats folder
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player

	-- Create leaderstats values
	local credits = Instance.new("IntValue", leaderstats)
	credits.Name = "Credits"

	local playtime = Instance.new("IntValue", leaderstats)
	playtime.Name = "Playtime"

	local prizesWon = Instance.new("IntValue", leaderstats)
	prizesWon.Name = "Prizes Won"

	-- Load and apply player data
	local playerData = loadPlayerData(player)
	credits.Value = playerData.Credits
	playtime.Value = playerData.Playtime
	prizesWon.Value = playerData.PrizesWon
end)

-- Player removing event
game.Players.PlayerRemoving:Connect(savePlayerData)

-- Periodic autosave
task.spawn(function()
	while task.wait(60) do
		for _, player in pairs(game.Players:GetPlayers()) do
			savePlayerData(player)
		end
	end
end)

I’ll implement it and report whether it works or not, thanks! ( I can’t test right now either)

The output says that the old data is being migrated, but then gives an error: “value of type table cannot be converted to a number”

From what I am understanding, the returned data from the old datastore is a table and not a direct number value. So you would have to set it like oldData[“number”] or whatever you used before.

How can I check what values are currently stored in the old datastore?

Simply print out the returned key using GetAsync, example:

local success, key = pcall(function()
      return DataStore:GetAsync("KEYNAME")
end)
print(key)

Here is where the error is:

	-- Load and apply player data
	local playerData = loadPlayerData(player)
	credits.Value = playerData.Credits
	print(playerData.Credits)
	playtime.Value = playerData.Playtime
	prizesWon.Value = playerData.PrizesWon

I printed the value for playerData.Credits and got back the value of the player’s old credits (the number 28380 in this case). Is there an issue applying the data to the leaderstats?

*This is using jedi_minecraft1’s modified script.

The output:

{
[“Credits”] = 28380
} - Server - SaveScript:122

Ah, that is where the error is coming from try: playerData.Credits[“Credits”]

That fixes that problem, thanks! I now need to check if the original issue was resolved.