I need help with my players stats
When player rejoin they don’t earn +1 for joins (stuck in the same number) and minutes seem to work fine (I think) idk how to fix without a data reset
Script:
local DataStoreService = game:GetService("DataStoreService")
local TimeStatsStore = DataStoreService:GetDataStore("TimeStats")
local JoinStatsStore = DataStoreService:GetDataStore("JoinStats")
local function createLeaderstats(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local Joins = Instance.new("IntValue")
Joins.Name = "Joins"
Joins.Value = 1
Joins.Parent = leaderstats
local Minutes = Instance.new("IntValue")
Minutes.Name = "Minutes"
Minutes.Value = 0
Minutes.Parent = leaderstats
return leaderstats
end
local function updateMinutes(player)
while true do
wait(60)
player.leaderstats.Minutes.Value = player.leaderstats.Minutes.Value + 1
end
end
game.Players.PlayerAdded:Connect(function(player)
local leaderstats = createLeaderstats(player)
local success, data = pcall(TimeStatsStore.GetAsync, TimeStatsStore, player.UserId)
if success then
leaderstats.Minutes.Value = data or 0
end
coroutine.wrap(updateMinutes)(player)
local plrKey = "id_" .. player.UserId
local save2 = player.leaderstats.Joins
local success2, savedData = pcall(JoinStatsStore.GetAsync, JoinStatsStore, plrKey)
if success2 then
if savedData then
if type(savedData) == "table" then
save2.Value = savedData[1] + 1
else
save2.Value = savedData + 1
end
else
save2.Value = 1
end
end
end)
game.Players.PlayerRemoving:Connect(function(player)
TimeStatsStore:SetAsync(player.UserId, player.leaderstats.Minutes.Value)
JoinStatsStore:SetAsync("id_" .. player.UserId, player.leaderstats.Joins.Value)
end)
I’m so bad at scripting if you can help to understand the issue
The issue you’ve encountered might be the API service is not properly enabled. To enable the API service, you could check the following Roblox documentation.
Overall, there’s nothing wrong with the code relating to this problem. All I can say is to make sure that API Services are enabled in the game settings, and that you test your data in the game through the Roblox app. If you don’t know already, most of the time data won’t save if you change it on studio. You could try adding game:BindToClose(function() at the bottom of your script and see if it works:
local function SaveData(player)
TimeStatsStore:SetAsync(player.UserId, player.leaderstats.Minutes.Value)
JoinStatsStore:SetAsync("id_" .. player.UserId, player.leaderstats.Joins.Value)
end
game.Players.PlayerRemoving:Connect(SaveData)
game:BindToClose(function()
for _, player in game.Players:GetPlayers() do
SaveData(player)
end
end)
I do have some suggestions for your code:
There’s absolutely no need to check if the savedData is a table.
The loop in updateMinutes is a memory leak. If a player leaves, the while loop still runs and errors every time it tries to update that player’s data. Not game breaking, but will cause lag to compound overtime. I recommend having one loop running which updates all players’ minutes value.
there could be an error in JoinStatsStore.GetAsync(), try printing the error message if success2 is false (failed) then check the output
if success2 then
if savedData then
if type(savedData) == "table" then
save2.Value = savedData[1] + 1
else
save2.Value = savedData + 1
end
else
save2.Value = 1
end
else -- GetAsync failed
warn("Getting data from JoinStatsStore failed")
print(savedData) -- prints the error message
end
I find when using a pcall the way you did there, it doesn’t work sometimes (e.g. it doesn’t catch the error at all, it just errors as if the pcall isn’t there). Try doing something like this:
local success, data = pcall(TimeStatsStore.GetAsync, TimeStatsStore, Player.UserId)
(Also, SetAsync needs a pcall as well).
edit from months later:
yeah it was the way i was indexing it sorry thats mb i was a bit dumb xd
pcall(TimeStatsStore.GetAsync, TimeStatsStore, player.UserId) will basically execute TimeStatsStore.GetAsync(TimeStatsStore, player.UserId) (which is the same as TimeStatsStore:GetAsync(player.UserId)) and return if it executed successfully and the value the function returned (if execution failed, returns the error message instead)
I ran this code: local success, result = pcall(DataStore.GetAsync, DataStore, key)
And I forced it to error, just to double check.
In my error handling code, I made it warn the error and kick the player without saving data. It didn’t do that, the code just errored and execution halted, so the player’s data was lost. Only when I did it the other way, it worked. It might be a bug, but I don’t see the harm in making an anonymous function if it worked and the other didn’t.
ok so, I’ve fixed it
tell me if I need to do other change
local DataStoreService = game:GetService("DataStoreService")
local TimeStatsStore = DataStoreService:GetDataStore("TimeStats")
local JoinStatsStore = DataStoreService:GetDataStore("JoinStats")
local function createLeaderstats(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local Joins = Instance.new("IntValue", leaderstats)
Joins.Name = "Joins"
Joins.Value = 0
local Minutes = Instance.new("IntValue", leaderstats)
Minutes.Name = "Minutes"
Minutes.Value = 0
return leaderstats
end
local function updateMinutes(player)
while player.Parent do
task.wait(60)
player.leaderstats.Minutes.Value += 1
end
end
game.Players.PlayerAdded:Connect(function(player)
local leaderstats = createLeaderstats(player)
local success, data = pcall(TimeStatsStore.GetAsync, TimeStatsStore, player.UserId)
if success then
leaderstats.Minutes.Value = data or 0
end
local plrKey = "id_" .. player.UserId
local save2 = player.leaderstats.Joins
local success2, savedData = pcall(JoinStatsStore.GetAsync, JoinStatsStore, plrKey)
if success2 then
save2.Value = (savedData and type(savedData) == "table") and savedData[1] or savedData or 0
end
save2.Value += 1
JoinStatsStore:SetAsync(plrKey, save2.Value)
coroutine.wrap(updateMinutes)(player)
end)
game.Players.PlayerRemoving:Connect(function(player)
TimeStatsStore:SetAsync(player.UserId, player.leaderstats.Minutes.Value)
end)
game:BindToClose(function()
for _, player in ipairs(game.Players:GetPlayers()) do
TimeStatsStore:SetAsync(player.UserId, player.leaderstats.Minutes.Value)
end
end)