How would I get all keys in a datastore or a scope? [Datastore backup system]

To our new member and non-member friends out there… (tell me if you don’t want this public)

10 Likes

Oh wow, that’s actually a good solution!

Thanks my dude.

1 Like

So how I understand it is instead of doing “player_1234” or whatever you’d put in the os.time? But if multiple people save at the same os.time wouldn’t that overwrite their data?

image

Every single player has their own OrderedDataStore

image

1 Like

I was talking about the regular datastore.

Every single player has their own regular datastore too

(this is why web hates me)

5 Likes

Okay, so I took this example from the wiki:

local DataStoreService = game:GetService("DataStoreService")
local playerExperienceStore = DataStoreService:GetDataStore("PlayerExperience")
 
local playerExperience = 0
pcall(function()
	playerExperience = playerExperienceStore:GetAsync("player_1234")
end)

“player_1234” is the key, if I were to replace it with os.time as the key, wouldn’t it overwrite the datastore if two players tried to save at the same os.time?

1 Like

I don’t think you read his post correctly.

Each player gets their own datastore, meaning there isn’t a single datastore where all player data is stored.

Would I do it like this then?

local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")
 
Players.PlayerAdded:Connect(function(player)
	local scope = "player_" .. player.UserId
	local lastSave = DataStoreService:GetDataStore(osTimeFromOrderedDatastore, scope)
end)

I do it like this

local DataStore = DataStoreService:GetDataStore("PlayerData"..tostring(Player.userId)) 

But yes, using scope should work too.

5 Likes

If you switched to scopes, the web team might not hate you as much. :stuck_out_tongue_winking_eye:

I think it has more to do with the terabytes of data that I’m probably hoarding and less with the organization, but yeah

3 Likes

How well does this prevent users from losing their data and how could I make data restores? I was thinking if I allowed players to revert their data to an older version, they could exploit it by trading some items, rejoining and reverting to before they traded their items, or something like that.

1 Like

Oooohhh, very very good point.

I literally did not think of that.

It looks like I won’t be allowing users to manually restore their data, but a backup system is still useful to have. I simply won’t add in the “restore your data” menu.

1 Like

I get around this by making my backup tool a little obscure to get to (so I can direct players to it when they lose their data, but so they won’t find it on their own) and by only allowing them to use it once (which I reset whenever I accidently break someone’s data)

2 Likes

A little off topic, but I noted you in my code for your backup algorithm.

image

1 Like

Since we’re off-topic, I’m curious what is this meant to do?

image

So my game is ran on my engine, “Dragon Engine”.

Basically, each service module is loaded into the engine, and the engine exposes itself to the service so the service can call engine methods inside of itsself, such as self:DebugLog().

Each service has server methods and client methods.

Client holds all the client-callable methods.
DataService.Client.Server=DataService basically gives the DataService.Client table access to the server methods.

It’s also used to prevent stack overflows from the __index metamethod.

Both server and client methods are ran server sided, but client methods can be called by clients via remotefunctions.

EDIT : For more info, you can view the framework by @Crazyman32 : GitHub - Sleitnick/AeroGameFramework: AeroGameFramework is a Roblox game framework that makes development easy and fun. The framework is designed to simplify the communication between modules and seamlessly bridge the gap between the server and client.

I took inspiration from this framework and wrote my engine from scratch based on the structure of the aeroframework.

4 Likes

Ooh. I’m also making a backup/restore data option for my game right now which was part of a trigger for the creation of an earlier post. I can tell you what I’m doing.

local DataStoreName = "GameData_Build100"

local DataStoreService = game:GetService("DataStoreService")
local PrimaryDataStore = DataStoreService:GetDataStore(DataStoreName)
local BackupDataStore = DataStoreService:GetDataStore(DataStoreName, "Backup")
  • To backup, users must enter the recovery screen and upload a copy of their main data. I don’t want to automate the process because I fear throttling which is currently a major issue in my game, despite there being no reason why it is. From there, they can use it (which then flushes the backup store for them) or update it. Once per time they use the menu to prevent throttles as far as the menu goes.
  • When the user chooses to use their backup, I call GetAsync on the backup store (provided I don’t cache the result when they join to prevent using GetAsync again in the future). I then call SetAsync on the main store and use whatever was returned from the backup GetAsync as the value for the set.
1 Like

If anyone wants an implemented version of @berezaa’s method, I have put it into my DataStore2 module (which also handles caching and player leave saving for you).

5 Likes