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

I’m having an issue with my upgrades script, I’m not sure if its me or DataStore2.

Here is the localscript which fires a remoteEvent to start a server script function.

ClickingDeviceUpgrade.OnServerEvent:Connect(function(player)
	
	local circleStore = DataStore2("circles", player)
	local deviceUpgradeStore = DataStore2("deviceUpgrade", player)
	
	local bought = false
	local cost = 10000
	
	if player.leaderstats.Circles.Value >= cost then
		
		circleStore:Increment(-cost, 0)
		deviceUpgradeStore:Increment(1)
		bought = true
		ClickingDeviceUpdate:FireClient(player, bought)
	else
		bought = false
		ClickingDeviceUpdate:FireClient(player, bought)
	end
	
end)

Then my main script which handles the upgrade itself is here:

ClickingDeviceUpgrade.OnServerEvent:Connect(function(player)
	
	local circleStore = DataStore2("circles", player)
	local deviceUpgradeStore = DataStore2("deviceUpgrade", player)
	
	local bought = false
	local cost = 10000
	
	if player.leaderstats.Circles.Value >= cost then
		
		circleStore:Increment(-cost, 0)
		deviceUpgradeStore:Increment(1)
		bought = true
		ClickingDeviceUpdate:FireClient(player, bought)
	else
		bought = false
		ClickingDeviceUpdate:FireClient(player, bought)
	end
	
end)

What is my issue?

Maybe you forgot to :Get() the DataStore

player.leaderstats.Circles.Value = circleStore:Get()

You can use :GetTable() and :Set() to store the inventory table. To get that table, just follow a tutorial on YouTube or some other source and when it comes to the data storage just use the methods mentioned above.

I know I’m being pretty vague here, that’s mostly because I want you to be able to learn for yourself. If you need any help, don’t be afraid to ask for it. :slightly_smiling_face:

1 Like

Whenever I want to increase a person’s stats by killing an NPC. Do I put the increment line inside of the main script or is it okay to use another script?

Sorry if this is a dumb question since I’m kind of bad at scripting

Hi! I really like the DataStore2 module, and it is really easy to use! However, I have a quick question. What benefits do we get for using Promises with :SetAsync(), :GetAsync(), :GetTableAsync() etc…?

You can read a post describing the benefits of promises here: Promises and Why You Should Use Them

1 Like

I’ve recently noticed that a lot of players are losing their Pet Data in my game, so I created a new save mode that doesn’t force the server so much and doesn’t pass lag information, but for some reason DataStore2 doesn’t seem to save anything when I activate this script to change the players’ data table if anyone has any idea what the problem might be, let me know, this error has been a headache.

local DataStore2 = require(5159892169)
local GetNewTable = require(script.GetNewTablePets)

DataStore2.Combine("MyGameData_Version_1","test124324t53")

local Players = game:GetService("Players")
local RS = game:GetService("ReplicatedStorage")

function getLevel(totalXP)
local Increment = 0
local RequiredXP = 100
for i = 0, RS.Pets.Settings.MaxPetLevel.Value do
	RequiredXP = 100 + (25*i)
	if totalXP >= (100*i) + Increment then
		if i ~= RS.Pets.Settings.MaxPetLevel.Value then
			if totalXP < ((100*i) + Increment) + RequiredXP then
				return i
			end
		else
			return i
		end
	end
	Increment = Increment+(i*25)
end
end


function GrabData(Player) -- Grabs data for the player.
local Data = DataStore2("NewPetDataStoreMode_v1",Player)
Data:SetBackup(5)
local GrabData = Data:GetTable(GetNewTable:GetNewTable(Player)) -- the default table will be the old pet table modified for the new table method
if Data:IsBackup() then
	Player:Kick("Sorry, but your data did not load correctly. Try rejoining to fix this problem...")
end
return GrabData
end


Players.PlayerAdded:Connect(function(plr)
local Pets = Instance.new("Folder")
local Data = Instance.new("Folder")

Pets.Name = "Pets"
Data.Name = "Data"

local DataPets = GrabData(plr)

for PetID,PetInfo in pairs(DataPets) do
	if RS.Pets.Models:FindFirstChild(PetInfo.Name) then
		local PetObject = RS.Pets.PetFolderTemplate:Clone()
		local Settings = RS.Pets.Models:FindFirstChild(PetInfo.Name).Settings
		local TypeNumber = RS.Pets.CraftingTiers:FindFirstChild(PetInfo.Type).Value
		local Level = getLevel(PetInfo.TotalXP)
		PetObject.Name = PetInfo.Name
		PetObject.Equipped.Value = PetInfo.Equipped
		PetObject.TotalXP.Value = PetInfo.TotalXP
		PetObject.Multiplier1.Value = Settings.Multiplier1.Value * (RS.Pets.Settings.CraftMultiplier.Value ^ TypeNumber) + (Settings.LevelIncrement.Value * Level)
		PetObject.Multiplier2.Value = Settings.Multiplier2.Value * (RS.Pets.Settings.CraftMultiplier.Value ^ TypeNumber) + (Settings.LevelIncrement.Value * Level)
		PetObject.PetID.Value = PetID
		PetObject.Type.Value = PetInfo.Type
		PetObject.Parent = Pets
	end
end

for i,v in pairs(script.Data:GetChildren()) do
	local DataValue = v:Clone()
	DataValue.Parent = Data
	if DataValue.Name == "MaxStorage" or v.Name == "MaxEquip" then
		DataValue.Value = RS.Pets.Settings:FindFirstChild("Default".. DataValue.Name).Value
	end
end

Pets.Parent = plr
Data.Parent = plr

script.Parent.SavePetFolder.Event:Connect(function(Player,PetFolder,args)
	if plr ~= Player then return end
	local DataStorePet = DataStore2("NewPetDataStoreMode_v1",plr)
	local TableToSave = DataStorePet:Get({})
	if PetFolder.Parent then
		TableToSave[PetFolder.PetID.Value] = nil
		table.insert(TableToSave,PetFolder.PetID.Value,{
			Name = PetFolder.Name,
			Equipped = PetFolder.Equipped.Value,
			TotalXP = PetFolder.TotalXP.Value,
			Type = PetFolder.Type.Value,
		})
		print(Player,"Salved",PetFolder)
	else
		TableToSave[args.PetID] = nil
		print(Player,"Removed",PetFolder)
	end
	DataStorePet:Set(TableToSave)
end)

wait(5)

game.ReplicatedStorage.RemoteEvents.VerifyPlayerPetsNow:FireClient(plr)
end)
1 Like

Hello, how can I use Disconnect() on: OnUpdate(function())

local Connections = {}
local Connection = MainStore:OnUpdate(function()end)
table.insert(Connections,Connection)

this does not work (

The documentation explicitly says not to do this.

You do not appear to combine this key anywhere.

I didn’t read anything else from it, but it is important to read the documentation closely.

There is no way, because there’s not really any point.

Just have a true/false value that you check inside OnUpdate.

2 Likes

Can this system store tables? I am making a ban system and I am going to use DataStore2 for it.

1 Like
  1. Is it dangerous to make several MainKeys ?
  2. Is it possible to increment numbers for tables without overwriting ?
1 Like

yes it can, i’m using this module myself and idk why it shouldn’t be able to as it’s just a module built around roblox’s datastore but with more secure methods of saving already done

1 Like

It’s pointless. Don’t do it.

Just :Get() and :Set().

1 Like

How would I go about restoring a previous version of data? Let’s say an update was released that broke peoples data, how would I go about restoring it to an older version- say a day old?

1 Like

Can you also save tables with this? Or is there any other way to save, for example, what tools the player has bought? Also, how do you check if the player who joined is new?

1 Like

Yes, by using the :GetTable() and :Set functions (saving tables is not limited to these functions)

Heavily depends on how your system is set up, but as a quick reminder you can’t directly save Instances (or instances in tables) to datastores with traditional datastorage calls such as SetAsync, UpdateAsync, or IncrementAsync

You could check for a value (that is saved onto a datastore) when a player joins, if they have said value, they’ve played before, and if they don’t, then you can set the value, and do whatever you want for anyone who is new. (if you’re planning on doing this for tutorials, I suggest you don’t set said value until they’ve completed the tutorial, just in case)

2 Likes

You could try using @sleitnick’s plugin DataStoreEditor and this post that shows you how to use it with DS2, obviously this isn’t ideal for massive player counts, but it’s a start (I personally don’t really know either)

Can I turn datastore.combine into a table somehow since I’m gonna have tones of data and can I use datastore.combine multiple times in different lines?

1 Like

Three Questions:
1: Am I able to use DataStore2.Combine more than once? if so how is that benefitable?

2: Is there a way to make a stat that is already in existence, instead of making an instance?

3: Is there a way to assign a dataStore to a Value that is inside a UI element, but that element is cloned many times, like an Upgrade system that has a “CurrentUpgrade” value inside the UI, And I don’t want my datastore to interfere with other instances of the “CurrentUpgarde”?

1 Like