Datastore wipe when you join the game, players will be angry if not fixed

I work for a game called You have to eat 2000 crawfish, this game has an active playerbase although small, and Prestige Datastores for the game have recently been wiped in the newest update. This is important because the community is really dedicated and Prestige a high amount of times, only very few members actually have data backed up for them. Anyway, here is the code:

local datastores = game:GetService("DataStoreService")
local datastore = datastores:GetDataStore("Save")

	local prestige ="NumberValue") -- prestige
	prestige.Name = "Prestige"
	prestige.Value = 0
	prestige.Parent = player
	local prestigeValue = datastore:GetAsync(player.UserId) or 0
	if prestigeValue then
		prestige.Value = prestigeValue
		print("could not get prestige saved data")

1 Like
  1. Why there are no pcalls?
  2. You need to use BindToClose too, in case your servers are being shut down, etc.
  3. It’s probably because you’re settings its value to 0 when it’s inserted, and you also have the or 0 thing, which as I can tell from your script, can cause to confusion and cause some people lose their Prestiges.
1 Like

Having pcalls made the Datastores not work last time, and for the second thing you said, can you elaborate on what BindToClose is? Player’s Prestiges are fine when they don’t join the game, I had checked that, but when they join the game it gets wiped. Edit: Found out what BindToClose was.

game:BindToClose will fire when the game is either shut down, or something like this.
It’s important to use it, simply because sometimes you can lose data when leaving.

I am not new to Datastores, this is not very useful.

…what? Whatever they mentioned above is useful and DEFINITELY the cause of data loss in your game.

:BindToClose() is VERY important as it makes sure that the server does not shut down before it has saved all player’s data.

pcall functions are to ensure that the data is actually saved. If the pcall fails, keep calling it again until it works, with increasing duration of 2, 4, 8, 16 with a max cap at 32. (just a suggestion)

STORE PLAYER’S DATA IN SERVER STORAGE! So that when the player leaves and the save fails, the server can keep on attempting to save it. Only when saved successfully, then remove all player’s data from the ServerStorage.

Your script is lacking ALL of these.

In the case that the pcall fails, DO NOT SETASYNC. Make a tag that tells the PlayerRemoving event to not saveasync if the data did not initally load.

1 Like

The data wipe happened because the values failed to load but your script didn’t detect it. So when the players left, the default values were saved.

There are 2 crucial updates you should apply to the script to prevent the data wipes.

  1. Use pcalls to determine if the values have been loaded:
local success, value = pcall(function()
  return ds:GetAsync(player.UserId)

if (not(success)) then
  return player:Kick('The data failed to load:\n' .. val)

This code will kick the player when DataStoreService encounters an error.

  1. Make sure the values have been already loaded before you save them

There are plenty of problems with the DataStores and they are not very stable.
Under certain circumstances the PlayerRemoving event may be called before the values have been fetched from the DataStore. It will cause the value to reset to default for affected player.

To prevent it, you should always check if the values are loaded:

  local loaded = {}

  local success, value = pcall(function()
    return ds:GetAsync(player.UserId)

  if (not(success)) then
    return player:Kick('The data failed to  load:\n' .. val)

  -- assign the value here

  loaded[player] = true

  if (loaded[player])
    -- perform SetAsync here

This is a basic version of data wipe prevention every game should have.