I have no idea why this keeps happening. Players keep complaining about their data being reverted but i see no issues in the script. I thought that maybe that there were too many datastore request. But even after i increased the wait time it still happens.
Here’s the script:
local DataStoreService = game:GetService("DataStoreService")
local playerDataStore = DataStoreService:GetDataStore("BlockDataFR")
local statslist = {
playerstats = {
{ Name = "Xp", Class = "NumberValue" },
{ Name = "Level", Class = "NumberValue" },
{ Name = "HighestLevel", Class = "NumberValue" },
{ Name = "Perks", Class = "NumberValue" },
{ Name = "Blocks", Class = "NumberValue" },
{ Name = "PBlocks", Class = "NumberValue" },
{ Name = "Gems", Class = "NumberValue" },
{ Name = "Steel", Class = "NumberValue" },
{ Name = "Clicks", Class = "NumberValue" },
{ Name = "ClicksTier", Class = "NumberValue" },
{ Name = "ClicksT", Class = "NumberValue" },
{ Name = "Crystalizes", Class = "NumberValue" },
{ Name = "Playtime", Class = "NumberValue" },
{ Name = "TotalCollected", Class = "IntValue" },
{ Name = "HighestTier", Class = "IntValue" },
{ Name = "Robux", Class = "IntValue" }
},
shopstats = {
block_shop = {
{ Name = "BlockShopUPGR1", Class = "IntValue" },
{ Name = "BlockShopUPGR2", Class = "IntValue" },
{ Name = "BlockShopUPGR3", Class = "IntValue" }
},
gem_shop = {
{ Name = "GemShopUPGR1", Class = "IntValue" },
{ Name = "GemShopUPGR2", Class = "IntValue" },
{ Name = "GemShopUPGR3", Class = "IntValue" },
{ Name = "GemShopUPGR4", Class = "IntValue" },
{ Name = "GemShopUPGR5", Class = "IntValue" },
{ Name = "GemShopUPGR6", Class = "IntValue" },
{ Name = "GemShopUPGR7", Class = "IntValue" },
},
steel_shop = {
{ Name = "SteelShopUPGR1", Class = "IntValue" },
{ Name = "SteelShopUPGR2", Class = "IntValue" },
{ Name = "SteelShopUPGR3", Class = "IntValue" }
},
prestige_shop = {
{ Name = "PrestigeShopUPGR1", Class = "IntValue" },
{ Name = "PrestigeShopUPGR2", Class = "IntValue" },
{ Name = "PrestigeShopUPGR3", Class = "IntValue" },
{ Name = "PrestigeShopUPGR4", Class = "IntValue" },
{ Name = "PrestigeShopUPGR5", Class = "IntValue" },
},
click_shop = {
{ Name = "ClickShopUPGR1", Class = "IntValue" },
{ Name = "ClickShopUPGR2", Class = "IntValue" },
{ Name = "ClickShopUPGR3", Class = "IntValue" },
{ Name = "ClickShopUPGR4", Class = "IntValue" },
},
},
unlockstats = {
{ Name = "steel_unlock", Class = "BoolValue" },
{ Name = "prestige_unlock", Class = "BoolValue" },
{ Name = "gem_unlock", Class = "BoolValue" },
{ Name = "achievement_unlock", Class = "BoolValue" },
{ Name = "click_unlock", Class = "BoolValue" },
{ Name = "crystalize_unlock", Class = "BoolValue" },
},
achievements = {
{ Name = "Achievement1", Class = "IntValue" },
{ Name = "Achievement2", Class = "IntValue" },
{ Name = "Achievement3", Class = "IntValue" },
},
leaderboard = {
{ Name = "Placement", Class = "IntValue" }
},
gamepassesstats = {
{ Name = "Gamepass1", Class = "BoolValue" },
{ Name = "Gamepass2", Class = "BoolValue" },
{ Name = "Gamepass3", Class = "BoolValue" },
{ Name = "Gamepass4", Class = "BoolValue" },
{ Name = "Premium", Class = "BoolValue" }
}
}
local playersPendingSave = {}
-- Helper function to save player data
local function savePlayerData(plr)
playersPendingSave[plr.UserId] = true -- Add player to pending save list
local playerstats = plr:FindFirstChild('playerstats')
local shopstats = playerstats:FindFirstChild('shopstats')
local unlockstats = playerstats:FindFirstChild('unlockstats')
local gamepassesstats = playerstats:FindFirstChild('gamepassesstats')
local achievements = playerstats:FindFirstChild('achievements')
local leaderboard = playerstats:FindFirstChild('leaderboard')
-- Helper function to save values
local function saveValues(statsTable, parent)
local savedData = {}
for _, stat in ipairs(statsTable) do
savedData[stat.Name] = parent[stat.Name].Value
end
return savedData
end
local dataToSave = {}
-- Save player stats
for key, value in pairs(saveValues(statslist.playerstats, playerstats)) do
dataToSave[key] = value
end
-- Save shop stats
for shopName, shopValues in pairs(statslist.shopstats) do
dataToSave[shopName] = saveValues(shopValues, shopstats[shopName])
for key, value in pairs(dataToSave[shopName]) do
dataToSave[key] = value
end
end
-- Save unlock stats
for key, value in pairs(saveValues(statslist.unlockstats, unlockstats)) do
dataToSave[key] = value
end
for key, value in pairs(saveValues(statslist.leaderboard, leaderboard)) do
dataToSave[key] = value
end
-- Save gamepasses stats
for key, value in pairs(saveValues(statslist.gamepassesstats, gamepassesstats)) do
dataToSave[key] = value
end
-- Save achievements stats
for key, value in pairs(saveValues(statslist.achievements, achievements)) do
dataToSave[key] = value
end
local success, errorMessage = pcall(function()
playerDataStore:SetAsync(plr.UserId, dataToSave)
end)
if not success then
warn("Failed to save data: " .. errorMessage)
else
playersPendingSave[plr.UserId] = nil -- Remove player from pending save list
end
end
game.Players.PlayerAdded:Connect(function(plr)
local leaderstats = Instance.new('Folder')
leaderstats.Name = 'leaderstats'
leaderstats.Parent = plr
local playerstats = Instance.new('Folder')
playerstats.Name = 'playerstats'
playerstats.Parent = plr
local shopstats = Instance.new('Folder')
shopstats.Name = 'shopstats'
shopstats.Parent = playerstats
local unlockstats = Instance.new('Folder')
unlockstats.Name = 'unlockstats'
unlockstats.Parent = playerstats
local leaderboard = Instance.new('Folder')
leaderboard.Name = 'leaderboard'
leaderboard.Parent = playerstats
local gamepassesstats = Instance.new('Folder')
gamepassesstats.Name = 'gamepassesstats'
gamepassesstats.Parent = playerstats
local achievements = Instance.new('Folder')
achievements.Name = 'achievements'
achievements.Parent = playerstats
-- Define all stats in tables
-- Helper function to create values
local function createValues(parent, values)
for _, value in ipairs(values) do
local newValue = Instance.new(value.Class)
newValue.Name = value.Name
newValue.Parent = parent
end
end
-- Create player stats
createValues(playerstats, statslist.playerstats)
-- Create shop stats
for shopName, shopValues in pairs(statslist.shopstats) do
local shopFolder = Instance.new('Folder')
shopFolder.Name = shopName
shopFolder.Parent = shopstats
createValues(shopFolder, shopValues)
end
-- Create unlock stats
createValues(unlockstats, statslist.unlockstats)
createValues(leaderboard, statslist.leaderboard)
-- Create gamepasses stats
createValues(gamepassesstats, statslist.gamepassesstats)
createValues(achievements, statslist.achievements)
-- Load the player data
local success, data = pcall(function()
return playerDataStore:GetAsync(plr.UserId)
end)
if success and data then
for _, stat in ipairs(statslist.playerstats) do
playerstats[stat.Name].Value = data[stat.Name] or '0'
end
for shopName, shopValues in pairs(statslist.shopstats) do
for _, shopValue in ipairs(shopValues) do
shopstats[shopName][shopValue.Name].Value = data[shopValue.Name] or 0
end
end
for _, stat in ipairs(statslist.unlockstats) do
unlockstats[stat.Name].Value = data[stat.Name] or false
end
for _, stat in ipairs(statslist.gamepassesstats) do
gamepassesstats[stat.Name].Value = data[stat.Name] or false
end
for _, stat in ipairs(statslist.achievements) do
achievements[stat.Name].Value = data[stat.Name] or 0
end
end
-- Increment playtime every second
coroutine.wrap(function()
while wait(1) do
playerstats.Playtime.Value += 1
end
end)()
-- Automatic saving every 300 seconds
coroutine.wrap(function()
while wait(400) do
savePlayerData(plr)
end
end)()
end)
game.Players.PlayerRemoving:Connect(function(plr)
savePlayerData(plr)
end)
game:BindToClose(function()
-- Wait for all players' data to be saved
for _, plr in pairs(game.Players:GetPlayers()) do
if playersPendingSave[plr.UserId] then
repeat wait() until not playersPendingSave[plr.UserId]
end
end
-- Save all remaining players' data (in case they didn't trigger PlayerRemoving)
for _, plr in pairs(game.Players:GetPlayers()) do
savePlayerData(plr)
end
end)