I’m very new to backend programming and I have an issue that I can’t seem to get my head around.
In my game, I have 3 developer products that gives players a speed boost. The difference between the products are the timers. Meaning the first product can have a 30 seconds timer, second product can have 1 minute timer and the third can have a 2 minute timer.
The point of me trying to save these products in a datastore is so players can purchase the developer products and use them whenever they feel like it. (so the timer doesn’t active instantely)
I do have a setup when players join the game:
if not DataStore:GetAsync(Plr.UserId) then
DataStore:SetAsync(Plr.UserId, {})
end
Using SetAsync overrides the previous save, but how would I go on and save multiple values in the same datastore so when players use one of the developer products, I can just remove it from the datastore?
There are probably more efficient ways to pull the saving methods off but I am still trying to get my head around on how all of this works.
DataStore:SetAsync(Plr.UserId, table) --saves “table” to the player’s data
data = DataStore:GetAsync(Plr.UserId, table) --retrieves the table and sets it to “data”
then you can do:
data[1] --retrieves first value in the saved table
data[2] --retrieves second value
etc
What I like doing is to use attributes when saving/loading data, so for example when someone leaves the server it takes all their attributes, saves it to a table, and then saves that table to the player’s data. Then when they join the game again it takes that tables, and you can do:
Datastore saving is all about giving a table to roblox server. And loading is to get the table you have saved before. A table is container that can store multiple values, but you can’t store objects(Instances). Also, you will have to make your table readable. Or the table will just look like a messy list and don’t know what each data stands for.
This is a table(Dictionary) that shows you how to make a readable table data:
local Data =
{Score = 0,
Lifes = 0,
HighScore = 0}
This is a unreadable table data that will make you go crazy to find what does each value stand for.
local Data = {0,0,0}
The readable table(Dictionary) data allows you to find the exact data you need directly.
If you want to read the Score data you just need to write:
local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetDataStore("DataStoreValues")
local Players = game:GetService("Players")
Players.PlayerAdded:Connect(function(Player)
local leaderstats = Instance.new("Folder", Player) --making leaderstats
leaderstats.Name = "leaderstats"
local Value1 = Instance.new("NumberValue", leaderstats) --making value1
Value1.Name = "Value1"
local Value2 = Instance.new("NumberValue", leaderstats) --making value2
Value2.Name = "Value2"
local value1Data --giving them a variable
local value2Data --giving them a variable
local s, e = pcall(function()
value1Data = DataStore:GetAsync(Player.UserId.."-Value1") or 0 --check if they have data, if not it'll be "0"
value2Data = DataStore:GetAsync(Player.UserId.."-Value2") or 0--check if they have data, if not it'll be "0"
end)
if s then
Value1.Value = value1Data --setting data if its success
Value2.Value = value2Data --setting data if its success
else
game:GetService("TestService"):Error(e) --if not success then we error it to the console
end
end)
Players.PlayerRemoving:Connect(function(Player)
local s, e = pcall(function()
DataStore:SetAsync(Player.UserId.."-Value1", Player.leaderstats.Value1.Value) --setting data
DataStore:SetAsync(Player.UserId.."-Value2", Player.leaderstats.Value2.Value) --setting data
end)
if not s then game:GetService("TestService"):Error(e) end --if not success then error
end)
local function SaveV9(Plr,Item)
local Data = V9DataStore:GetAsync(Plr.UserId)
local s,e = pcall(function()
Data[Item.Name] = Data[Item.Value]
V9DataStore:SetAsync(Plr.UserId,Data)
end)
if not s then
TestService:Error(e)
else
print("Success!")
end
end
local function CreateV9Item(Plr,Time)
local v9Value = CreateValue("V9",Time)
local v9Folder = Plr:WaitForChild("PlayerStats"):WaitForChild("V9")
v9Value.Parent = v9Folder
SaveV9(Plr,v9Value)
end
What I do is I create IntValues in the CreateV9Item function, place them in a folder and then go on with the saving process. So pretty much I give the table the Value name and the actual value from the IntValue
For clarification, V9 is just the name of the IntValue.
Have you enabled Studio Access to API Services in game settings? If your code is written correctly, this might be the cause when you try to test the datastore in studio.
If you want to try your datastore in studio, you have to enabled Studio Access to API Services in game settings.
Here is the full code.
What I am trying to do is whenever a product is purchased, an IntValue gets added to the player.
Name of the intValue is the product name and the value is the actual timer since each product have different timers.
function CreateValue(Name,Value) -- I create the actual IntValue
local intValue = Instance.new("IntValue")
intValue.Name = Name
intValue.Value = Value
return intValue
end
local function SetData(Plr,Value) -- I apply the IntValue name & value to the Datastore
local Data = V9DataStore:GetAsync(Plr.UserId)
Data[Value.Name] = Value.Value
V9DataStore:SetAsync(Plr.UserId,Data)
end
local function ValueSetup(Plr,Value) -- This happens when a product is purchased. Value = time of the product (the timer)
local v9Value = CreateValue("V9",Value)
local playerStats = Plr:WaitForChild("PlayerStats")
v9Value.Parent = playerStats:WaitForChild("V9")
SetData(Plr,v9Value)
end
Now what the issue is that, the latest saved data overwrites by the new data. So when I use SetAsync, whatever previous data was there before gets swapped out by the new data.