Datastore Script not working

Hello

I’m pretty new to Datastores and recently started experimenting with them a bit. I always was working with same script. At the beginning it worked fine. But when i added the most recent data to store, it stopped working. I’ve already asked my friends but noone got a clue. I’ve also gone trough the forum and not really found an answer.

(its not saving all 3, getting the data is no problem)

the script is following:

local Player = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local StationsDS = DataStoreService:GetDataStore("Stations")
local MoneyDS = DataStoreService:GetDataStore("Money")

local PLAYERS_LEFT = 0
local BindableEvent = Instance.new("BindableEvent")

local function CreateLeaderBoard(player)
	PLAYERS_LEFT += 1
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player


	local points = Instance.new("IntValue")
	points.Name = "Stations"
	points.Value = 0
	points.Parent = leaderstats

	local money = Instance.new("IntValue")
	money.Name = "Money"
	money.Value = 0
	money.Parent = leaderstats
	
	local MetroLiveryBought = Instance.new("BoolValue")
	MetroLiveryBought.Parent = game.Players:FindFirstChild(player.name)
	MetroLiveryBought.Name = "MetroLiveryBought"
	
	-- get Data
	local StationsValue = game.Players:FindFirstChild(player.Name).leaderstats.Stations
	local StationsFromDS

	local success, errormessage = pcall(function()

		StationsFromDS = StationsDS:GetAsync(player.UserId .. "-Stations")

	end)

	if success then

		StationsValue.Value = StationsFromDS
		print("Playerdata for Stations from ".. player.name .. " successfully recovered.")

	else

		warn("There has been an error while getting Stations data for ".. player.name .. " " .. errormessage)

	end

	-- get money

	success = nil
	errormessage = nil

	local MoneyValue = game.Players:FindFirstChild(player.name).leaderstats.Money
	local MoneyFromDS

	local success, errormessage = pcall(function()

		MoneyFromDS = MoneyDS:GetAsync(player.UserId .. "-Money")

	end)

	if success then

		MoneyValue.Value = MoneyFromDS
		print("Playerdata for Money from ".. player.name .. " successfully recovered.")
	else

		warn("There has been an error while getting Money data for ".. player.name .. " " .. errormessage)

	end
	
	-- get if it has been bought (Metro Livery)
	
	success = nil
	errormessage = nil

	local MetroLiveryBought = game.Players:FindFirstChild(player.name).MetroLiveryBought
	local MetroLiveryFromDS

	local success, errormessage = pcall(function()

		MetroLiveryFromDS = MoneyDS:GetAsync(player.UserId .. "-MetroLivery")

	end)

	if success then

		MetroLiveryBought.Value = MetroLiveryFromDS
		print("Playerdata for Metro Livery from ".. player.name .. " successfully recovered.")
	else

		warn("There has been an error while getting Metro Livery data for ".. player.name .. " " .. errormessage)

	end


end

local function SaveData(player)

	-- save Data
	local StationsValue = game.Players:FindFirstChild(player.Name).leaderstats.Stations
	local MoneyValue = game.Players:FindFirstChild(player.name).leaderstats.Money
	local StationsFromDS

	local success, errormessage = pcall(function()

		StationsFromDS = StationsDS:SetAsync(player.UserId .. "-Stations", StationsValue.Value)

	end)

	if success then

		print("Playerdata from ".. player.name .. " successfully saved.")

	else

		warn("There has been an error while saving data for ".. player.name .. " " .. errormessage)

	end

	success = nil
	errormessage = nil


	-- save Money
	local MoneyFromDS

	local success, errormessage = pcall(function()

		MoneyFromDS = MoneyDS:SetAsync(player.UserId .. "-Money", MoneyValue.Value)

	end)

	if success then

		print("Playerdata from ".. player.name .. " successfully saved.")

	else

		warn("There has been an error while saving data for ".. player.name .. " " .. errormessage)

	end
	
	-- save Metro livery
	
	success = nil
	errormessage = nil

	local MetroLiveryBought = player.MetroLiveryBought
	local MetroLiveryFromDS

	local success, errormessage = pcall(function()

		MetroLiveryFromDS = MoneyDS:SetAsync(player.UserId .. "-MetroLivery", MetroLiveryBought.Value)

	end)

	if success then

		MetroLiveryBought.Value = MetroLiveryFromDS
		print("Playerdata for Metro Livery from ".. player.name .. " successfully saved.")
	else

		warn("There has been an error while saving Metro Livery data for ".. player.name .. " " .. errormessage)

	end
	
	
	PLAYERS_LEFT -= 1
	BindableEvent:Fire()
end


-- When joining

Player.PlayerAdded:connect(CreateLeaderBoard)
Player.PlayerRemoving:connect(SaveData)

game:BindToClose(function()
	while PLAYERS_LEFT > 0 do
		BindableEvent.Event:Wait()
	end
end)

I’ve just tested it and there appears to be no problem. Did you maybe update the values via the client?

always updating them over the server sided console or the explorer in studio

could it be that i shut down the game in studio too fast then?

It could be, because setasync fails for me most of the time if I close the game to quickly or have a script open and leave the game. btw you should really summarise your code you have a lot of unnecessary code.

i’ll do that somewhen when i’ll be more experienced :joy:

anyways thanks for your help

I could quickly summarise your code for you if you want.

i’ll first try to find out what is going wrong and why the value which defines if the user owns the livery don’t get saved

but you i’m all ear if can tell me what i can improve

local function PlayerAdded(Player) -- the player you don't have to say game.Players:FindFirstChild(Player.Name)
      local leaderstats = Instance.new("Folder", Player)
      leaderstats.Name = "leaderstats"
end
game.Players.PlayerAdded(PlayerAdded)

That are a few very intriguing changed, i’ll make sure to implement them in my future projects, thanks

A good way to fix this is to put it in the BindToClose instead of player removing. Sometimes on studio the server shuts down but that code executes. Another way is to switch to server mode when hitting stop. Then it would work as well.

He already has a BindToClose function? also BindToClose shouldn’t be used in studio.

can you explain more the second method?

I disagree. Maybe I misread the code but he only saves the data here: Player.PlayerRemoving:connect(SaveData). Bind to close works best in studio because you can then see the data save as well as make it save. In a real game it would work fine, but in studio there can be some errors. Similar to here maybe. Why does SetAsync break the code?

So basically you are calling the save data function in the bind to close as well, because on studio, the game is shutting down because you are the last person in that server

Even on the BindToClose api it says if RunService:IsStudio() then return end

Also there is no point in saving data twice. Per say PlayerRemoving does save the data then bindtoclose will do the same.

https://developer.roblox.com/en-us/api-reference/function/DataModel/BindToClose

This is what I do in my game

game:BindToClose(function()
	
	if RunService:IsStudio() then 
		return 
	end
	
	task.wait(5) -- Per say you shutdown all your servers it will wait 5 seconds before actually shutting down the server
	
end)

Well it could be that i get that wrong, but i’m not worried about the datastores also working in Studio, its more that the last value of the 3 which should get saved donesn’t get saved

Are you really updating the value, because I’ve copied your whole code and pasted it into a script and then I changed all the values and they successfully saved.

Edit 1: yes all the values including the boolvalue

Edit 2: go to game settings - security. Do you have Enable Studio Access to API Services enabled? @Agusta0002