DataStore2: How to access the datastore in other scripts

Hello!
So, I’m working on data saving with DataStore2.

I followed this tutorial: https://www.youtube.com/watch?v=hmRBvZD1pRw

How would I access some data in other scripts and update it?
I have like time value which gives you +1 every 60 seconds.
Or when you finish a stage, it gives you +1 for stage value.
etc.

How would I do that?
Thank you!

DataStore2 is player-based so every time you have a reference to the player you can do local player_data = DataStore2("name", player)

What about a specific value in a table?

Get their data and do whatever you want with it.

You should look into documentation of data store 2, specifically into :GetTable.

Documentation starts here. API - DataStore2

You can do something like this.

local Players = game:GetService("Players")
local DataStore2 = require("DataStore2")

-- Always combine!
DataStore2.Combine("MainData", "DataTable")

local DEFAULT = {
	TimePlayed = 0;
	Points = 0;
}

local function PlayerAdded(Player)
	if not Player:FindFirstChild("leaderstats") then
		local DataTableStore = DataStore2("DataTable", Player)

		local Leaderstats = Instance.new("Folder")
		Leaderstats.Name = "leaderstats"

		for Key, Value in next, DataTableStore:GetTable(DEFAULT) do
			local TypeOf = typeof(Value)
			if TypeOf == "boolean" then
				TypeOf = "bool"
			end

			local ClassName = string.gsub(TypeOf, "^.", string.upper) .. "Value"
			local Success, Object = pcall(Instance.new, ClassName)
			if Success then
				Object.Name = Key
				Object.Value = Value
				Object.Parent = Leaderstats
			end
		end

		DataTableStore:OnUpdate(function(NewData)
			for Key, Value in next, NewData do
				local CurrentObject = Leaderstats:FindFirstChild(Key)
				if CurrentObject then
					CurrentObject.Value = Value
				else
					local TypeOf = typeof(Value)
					if TypeOf == "boolean" then
						TypeOf = "bool"
					end

					local ClassName = string.gsub(TypeOf, "^.", string.upper) .. "Value"
					local Success, Object = pcall(Instance.new, ClassName)
					if Success then
						Object.Name = Key
						Object.Value = Value
						Object.Parent = Leaderstats
					end
				end
			end
		end)

		Leaderstats.Parent = Player
	end
end

Players.PlayerAdded:Connect(PlayerAdded)
for _, Player in ipairs(Players:GetPlayers()) do
	PlayerAdded(Player)
end
-- This is a different script.
local Players = game:GetService("Players")
local DataStore2 = require("DataStore2")

local CurrentPlayers = Players:GetPlayers()
local Length = #CurrentPlayers

Players.PlayerAdded:Connect(function(Player)
	Length = Length + 1
	CurrentPlayers[Length] = Player
end)

Players.PlayerRemoving:Connect(function(Player)
	local Index = table.find(CurrentPlayers, Player)
	if Index then
		CurrentPlayers[Index] = CurrentPlayers[Length]
		CurrentPlayers[Length] = nil
		Length = Length - 1
	end
end)

while true do
	wait(1)
	for _, Player in ipairs(CurrentPlayers) do
		local DataTableStore = DataStore2("DataTable", Player)
		DataTableStore:Update(function(CurrentData)
			local NewTimePlayed = CurrentData.TimePlayed + 1
			CurrentData.TimePlayed = NewTimePlayed

			-- Every 60 seconds played, award a point.
			if NewTimePlayed % 60 == 0 then
				CurrentData.Points = CurrentData.Points + 1
			end

			-- DataStore2 deep clones the table so you don't have to mess with Cryo or whatnot.
			return CurrentData
		end)
	end
end

This might not work as I haven’t tested it, but I’m 99% confident that it will.

As long as DataStore2 is required, you can access the data in it from any server script / module required by a server script.

Thank you so much for that script!
I’ll try it, but I already have my table.

			local PlayerData = {
				Stats = {
					["Stage"] = 0, --stage.Value;
					["Rebirths"] = 0, --rebirths.Value;
					["Cash"] = 10 --cash.Value;
				},
				OtherStats = {
					["Time"] = 0, --timing.Value;
					["BetaTester"] = true --betaStat.Value;
					}
			}
			return PlayerData
		end

Is there a specific thing to set data in tables? Like idk DataStore2:Set(“RandomTable”, …)?

If you want to changed Rebirths using Update, you’d just do:

PlayerDataStore:Update(function(CurrentData)
	CurrentData.Stats.Rebirths = CurrentData.Stats.Rebirths + 1
	return CurrentData
end)

Here’s what Kampf said about it when I asked a few days ago.

Yeah, but what about for another script?
If possible, can you put also variables I need?

Same thing, you just GetTable it, and you’d use the same code.

DataStore2("PlayerData", Player):Update(function(...) ... end)

2 Likes

Okay.
How would I put that in that script?

local DataStore2 = require(game.ServerScriptService.DataStore2)
local MainKey = “MainDataStore”
DataStore2.Combine(MainKey, “Stats”, “OtherStats”)

local DataStore2 = require(game.ServerScriptService.DataStore2)
local MainKey = "MainDataStore"
DataStore2.Combine(MainKey, "Stats", "OtherStats")

local addCash = function()
	for i,v in pairs(game.Players:GetPlayers()) do
		if v:FindFirstChild("leaderstats") then
			if v.leaderstats:FindFirstChild("leaderstats") then
				if v.leaderstats:FindFirstChild("Cash") then
					--[[local PlayerData = DataStore2(MainKey,v)
					PlayerData.Cash:Increment(1)
					v.leaderstats.Cash.Value = v.leaderstats.Time.Value + 1]]
					--[[DataStore2("PlayerData", v):Update(function(givesCash)
						DataStore2.Stats.Rebirths = DataStore2.Stats.Rebirths + 1
					end)]]
				end
			end
		end
	end
end

while true do
	addCash()
	wait(5)
end

So if Stats is where your Cash value is, you don’t want to update the actual Value itself. You would want to have ::OnUpdate do that for you.

local DataStore2 = require(game.ServerScriptService.DataStore2)
local MainKey = "MainDataStore"
DataStore2.Combine(MainKey, "Stats", "OtherStats")

local addCash = function()
	for i,v in pairs(game.Players:GetPlayers()) do
		if v:FindFirstChild("leaderstats") then
			if v.leaderstats:FindFirstChild("leaderstats") then
				if v.leaderstats:FindFirstChild("Cash") then
					local statsStore = DataStore2("Stats", v)
					statsStore:Update(function(currentStats)
						currentStats.Cash = currentStats.Cash + 1
						return currentStats
					end)
				end
			end
		end
	end
end

while true do
	addCash()
	wait(5)
end

And as for setting up ::OnUpdate for use with a table, you’d want to iterate through the table, check if the value exists, if it does, update the value, if it doesn’t, create it and set the value.

It doesn’t give cash for some reason :frowning:

You can use _G. or shared. These two things create different user datas for other scripts of the same class name to see.
Here’s a quick example :

There is no difference between shared and _G.

That’s looks interesting. I’ll take a look at it once I have time (tomorrow).

Not needed and not recommended at all. And as for it not updating, I’ll be home in around an hour so I can help more then.

You likely forgot to set :OnUpdate, which I did explicitly mention a few times before, but using it with a table is a bit more complicated than the docs show.

Ok, it’s really cool too. This can make data storage much easier. Lets say I have a data script and a event script.

image

Script Data looks like this :

shared.data = {}

game.Players.PlayerAdded:Connect(function(Player)
	shared.data[Player.Name] = {Coins = 0}
	script.TriggerSend:Fire(Player)
end)

Script Event looks like this :

script.Parent.TriggerSend.Event:Connect(function(Player)
	shared.data[Player.Name].Coins = shared.data[Player.Name].Coins + math.random(0,8000)
	print(Player.Name, ':', shared.data[Player.Name].Coins)
end)

Script event gets the player data by doing
shared.data[Player.Name]
and gets the coins with
shared.data[Player.Name].Coins

It also works perfectly with _G.

Script Data looks like this :

_G.data = {}

game.Players.PlayerAdded:Connect(function(Player)
	_G.data[Player.Name] = {Coins = 0}
	script.TriggerSend:Fire(Player)
end)

Script Event looks like this :

script.Parent.TriggerSend.Event:Connect(function(Player)
	_G.data[Player.Name].Coins = _G.data[Player.Name].Coins + math.random(0,8000)
	print(Player.Name, ':', _G.data[Player.Name].Coins)
end)

But keep in mind,

Is there actually a way to make it like the default datastore to save only value like every 30 seconds and on player exit?

I’m gonna probably be a little rude here, but not only is that not going to fix the problem, but it’s asinine to use shared or _G. DataStore2 already caches the data in the module. What Wizertex needs to do is set the :OnUpdate function wherever they’re setting up the stats initially.

Using the global tables is unsafe and they take longer to get anyway. There’s not a single reason to be using it, and there’s not a reason to even suggest it.

2 Likes
game.Players.PlayerRemoving:Connect(function(Player)
local coinStore = DataStore2("Coins", Player)
coinStore:Save()
-- I think
end)

DataStore2 already does that for you. That’s why you use :OnUpdate. Kampf says to not even use PlayerRemoving with DataStore2, and it’s for good reason.

You can read more here. Please read the basic simulator example as well, as it’ll be helpful to you.