How to use DataStore2 - Data Store caching and data loss prevention

Is there a way to store purchase history with this?

2 Likes

Per player? Easily, just save a table for them. Globally? No, and I probably wouldn’t recommend data stores for that anyway because of their finicky nature when multiple servers mutate the same key.

3 Likes

Thank you, you’re always so helpful.

Probably a dumb question but how should I detect if I’m running on backup data? If I do this, will it yield until it’s finished calling GetAsync 5 times and then print whether or not the datastore is a backup?

local plrDatastore = DataStore2(plr)
plrDatastore:SetBackup(5,funcs.defaultValue)
print(plrDatastore:IsBackup())

Your code is wrong (no key, you don’t call :Get()), but the general idea of this is correct, though it won’t try to call GetAsync until you actually call :Get().

1 Like

Oh I see, so to tell the player they’re running on a backup and their data won’t save, I should do something like this?

local plrDatastore = DataStore2('key',plr)
plrDatastore:SetBackup(5,funcs.defaultValue)
local plrData = plrDatastore:GetTable(funcs.defaultValue)

if plrDatastore:IsBackup() then
--notify player that their data will not save
end

Yeah, but the funcs.defaultValue in your SetBackup isn’t necessary–:Get() (and by extension :GetTable()) should use the default value you provide.

1 Like

Alright I see. Thank you for the help and quick responses.

2 Likes

Hey, You may of already said something about this but is there a way to reset a players data?
I was just wondering because of I’m making a story/adventure game where after you complete the story you can reset data and start over again like you are a new player.

2 Likes

You can just call :Set(nil) on all the keys you use, I believe.

4 Likes

There is documentation on datastore2 to make it work in studio. By default it does not.

2 Likes

First I just wanted to thank you for this - I’m using it for a game I’m working on and it works like a charm!

Is there any way to specify certain stats to save or indicate certain stats not to save? I’m sort of confused if all stats in the leaderstats are automatically added to the database.

This is my set up right now:

DataStore Set up

The script works, I just am confused where it knows to only save the “Shillings” leaderstat vs all leaderstats or whether it just saves all leaderstats unless explicitly told not to.

local DataStore2 = require(game.ServerScriptService:WaitForChild("MainModule"))
local FunctionModule = require(game.ServerScriptService:WaitForChild("FunctionModule"))
local DefaultValue = 0

game.Players.PlayerAdded:Connect(function(Player)
	local ShillingsDataStore = DataStore2("Shillings", Player)
	FunctionModule.LeaderstatsCreate(Player)
	FunctionModule.LeaderstatsCategory(Player,"Shillings","IntValue")
	local Shillings = Player.leaderstats.Shillings
	local function ShillingsUpdate(UpdatedValue)
		Shillings.Value = ShillingsDataStore:Get(UpdatedValue)
	end
	ShillingsUpdate(DefaultValue)
	ShillingsDataStore:OnUpdate(ShillingsUpdate)
end)

Sorry if this was already asked before and thank you again!!

1 Like

I am not sure but is it possible to use a player ID instead of a player instance for saving?

As answered several times before in this thread, DataStore2 only uses player instances for the time being.

1 Like

DataStore2 doesn’t know or care about what leaderstats a player has–what it saves is entirely up to you.

2 Likes

Where do you specify what it’s saving? I’m sure I’m making a super basic mistake here but I’m re-reading my code and I can’t figure out where I’m specifying the stat in question (called Shillings) as the one that I want saved as opposed to other leaderstats I might add.

Like in my set-up:

Set up
local DataStore2 = require(game.ServerScriptService:WaitForChild("MainModule"))
local FunctionModule = require(game.ServerScriptService:WaitForChild("FunctionModule"))
local DefaultValue = 0

game.Players.PlayerAdded:Connect(function(Player)
	local ShillingsDataStore = DataStore2("Shillings", Player)
	FunctionModule.LeaderstatsCreate(Player)
	FunctionModule.LeaderstatsCategory(Player,"Shillings","IntValue")
	local Shillings = Player.leaderstats.Shillings
	local function ShillingsUpdate(UpdatedValue)
		Shillings.Value = ShillingsDataStore:Get(UpdatedValue)
	end
	ShillingsUpdate(DefaultValue)
	ShillingsDataStore:OnUpdate(ShillingsUpdate)
end)

I’m pretty sure I’m understanding what it’s doing but I don’t specify that the leaderstat named Shillings is the one being saved by Datastore2. The only time I reference it at all is when I’m telling the Value to update by checking the Datastore for a more recent value. Other than that though, it’s not being referenced at all which is why I’m confused why Datastore2 knows that that is the leaderstat I want saved to the Database vs another leaderstat such as Kills, Deaths, Player Level, Group Rank, etc.

Again, I’m sorry if this is super painfully obvious but I’m not understanding which line in the set-up is specifying the leaderstat vs another one.

1 Like

I’m using this DS2 method which is working fantastically except for 1 thing.

When the first user joins a server, it loads their data just fine.
Then, the second/third/fourth user joins, and they throttle when loading - Really adds to loading times.
I’m really unsure if it’s my code or not. Saving data works just fine without throttles.

Is there something wrong with my code?

My code
local function loadUserData(Player)
	print("LOADING "..Player.Name.."'s DATA")
	if Player:FindFirstChild("leaderstats") == nil then
		DataSetup.SetupPlayer(Player)
	end
	if Player.Team == nil then
		Player:GetPropertyChangedSignal("Team"):Wait()
	end
	local EncodedDefaultMTable = HTTPSVC:JSONEncode(defaultMTable)
	local EncodedDefaultBadgeMTable = HTTPSVC:JSONEncode(defaultBadgeMTable)
	local PlayerBetaStatus = DS2(Player.userId.."BetaState", Player) -- Played during beta
	local PlayerMTable = DS2(Player.Team.Name.."ParlourPreRelease6", Player) -- Parlour
	local PlayerBadgeMTable = DS2(Player.userId.."GameBadgesPreRelease6", Player) -- Badges
	local PlayerCash = DS2(Player.Team.Name.."CashPreRelease5", Player) -- Cash
	local PlayerSettings = DS2(Player.userId.."Settings", Player) -- Settings
	local PlayerTutorialStatus = DS2("TutorialStatus7", Player)
	
local function setTutorialStatus(updatedValue)
	local tutorialState = PlayerTutorialStatus:Get(updatedValue)
	if tutorialState == false then
		tutorialState = true
		PlayerTutorialStatus:Set(tutorialState)
		game.ReplicatedStorage.StartTutorial:FireClient(Player)
	end
end
	
local function setBetaStatus(updatedValue)
	local betaState = PlayerBetaStatus:Get(updatedValue)
	if gameBeta.Value == true then
		PlayerBetaStatus:Set(gameBeta.Value)
	end
	Player.IsBetaTester.Value = betaState
end
	
local function setMTable(updatedValue, state)
	if state == "Load" then
		local mTable = PlayerMTable:Get(updatedValue)
		local DecodedMTable = HTTPSVC:JSONDecode(mTable)
		dataLine:FireClient(Player, DecodedMTable)
	end
end
	
local function setBadgeMTable(updatedValue, state)
	if state == "Load" then
		local mTable = PlayerBadgeMTable:Get(updatedValue)
		local DecodedMTable = HTTPSVC:JSONDecode(mTable)
		wait()
		badgeDataLine:FireClient(Player, DecodedMTable)
	end
end
	
local function setSettingsMtable(updatedValue, state)
	if state == "Load" then
		local mTable = PlayerSettings:Get(updatedValue)
		loadSettings:FireClient(Player, mTable)
	end
end

	
local function setCash(updatedValue)
	Player.leaderstats.Cash.Value = PlayerCash:Get(updatedValue)
	
	
end

	setTutorialStatus(false)

	setBetaStatus(defBetaValue)
	
	setSettingsMtable(defaultSettings, "Load")
	
	setCash(defaultCash)
	
	setMTable(EncodedDefaultMTable, "Load")
	
	setBadgeMTable(EncodedDefaultBadgeMTable, "Load")
	
	PlayerCash:OnUpdate(setCash)
	
end
1 Like

I’m not sure what to say other than read the thread–the entire OP is dedicated to answering that question! Call :Set when data changes (which your code sample doesn’t seem to be doing), call :Get() when you need the data.

You’re not using combined data stores–read the gotchas. Furthermore, do NOT put the player ID/information/whatever in the keys. The keys should preferably be completely static.

1 Like

sigh I forgot they say this. Cheers!

Edit: Combined DataStores are a GODSEND for this issue.

3 Likes