Occasionally a game may have an update which messes with peoples data in an unintended way and as a result leads to players having data loss or some sort of corruption. Then as a response the game usually does a “rollback” where they set everyone’s data back to a previous date before the incident happened. My question is how do these games have their datastores set in a way they are able to do rollbacks like this?
For example, in my game I save timestamps to an ordered datastore which is essentially the key to the players actual data, similar to how datastore2 does it (I think). But I don’t actually have a good way to just simply rollback everyone’s data back to a certain point in time which basically makes this method useless for me. How do you guys accomplish this or how can this be done?
I don’t know how datastore2 does it, but I’d setup my backups like this:
also, this is like half pseudo code since I’m on my phone
-- some date to roll back to and from
-- this could be stored in some datastore or hardcoded
rollback_day0 = some date and time where any saves before this time is rolled back
rollback_day1 = the date to roll back to
-- loads data after finding the date of the previous save
function load_data(some player id)
-- this stores and sorts the dates that the player has saved data by the second or minute if you have some cache
dates_datastore = datastoreService:GetOrderedDataStore(player's userid)
-- this stores each rollback and the current data
data_datastore = datastoreService:GetDataStore(player's userid)
-- get the first page sorted descending so the first item is the most recent save
pages = dates_datastore:GetSortedAsync(descending, 10)
page = pages:GetCurrentPage()
-- checks if there is any saved data
if page[1] == nil then -- I havent used orderedDatastores in a while, not sure if this is right
initialize the player's data, they're a new player
return the new data
end
-- there is saved data, so we use the most recent date, page[1].key as the id in data_datastore as for the most recent save
-- you could also use .value, but since we're using dates, the keys should be sorted anyways
-- check if the most recent date is to be rolled back
if page[1].key is before rollback_date0 then
do some loop to check [2], [3], [4], ... etc until you find a date before rollback_date1
if you're done with this page
wait(some arbitrary time) -- so you don't use the datastore too fast
page = pages:AdvanceToNextPageAsync()
repeat whatever happened above
end
-- you'll probably want a better syntax, for that 👆, a while loop with a for loop inside might work
end
-- page[N] is the date you found that is before rollback_date1 or after rollback_date0
data = data_datastore:GetAsync( page[N].key )
return data
end
-- saves the new data in data_datastore as the current date
function save(some player id, data to save)
today_date = get today or this week's date
dates_datastore = datastoreService:GetOrderedDataStore(player's userid)
data_datastore = datastoreService:GetDataStore(player's userid)
previous_date = do what we did in load() to get the previous_date
-- note, we're saving by the minute, so you can't just do == here
-- maybe something like (date modulo seconds in a day) should work to get the day
if today_date is the same day as previous_date then
-- if today is a day with a save already
don't do anything to dates_datastore since we'll be overwriting this save
else
-- if today is a day with no save, mark today in the ordered datastore
dates_datastore:SetAsync(today_date, true)
end
-- save the data under today's date
data_datastore:SetAsync(today_date, the data to save)
end