The code they provided won’t work, DataStore2 never returns nil and if it did that code would set the variable to 0, not to a store.
Use the second argument of Increment if you can’t guarantee the data will exist by then.
MassStore:Increment(1, 0)
The code they provided won’t work, DataStore2 never returns nil and if it did that code would set the variable to 0, not to a store.
Use the second argument of Increment if you can’t guarantee the data will exist by then.
MassStore:Increment(1, 0)
Thanks for correcting me. Not to argue, but would it be more valid to do MassStore:Set(0)
so that it is still a DataStore2?
Also @sebi210:
Curious, when specifically are you printing and getting a nil value, since DataStore never return nil?
:Get() can return nil. DataStore2() can not.
Yes.
So, I’ve been kind of against using DataStore2 because of the fact I feel like it’s somewhat inefficient. I put together something, and I was curious If this could be a fix for that.
local DataStore2 = require(...)
local Players = game:GetService("Players")
local MarketPlaceService = game:GetService("MarketPlaceService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Data = {
Coins = 0,
Inventory = {},
XP = 0,
Level = 1
}
function recurseTable(tbl, func) -- just a for loop, originally used as a means of easily recursing nested tables but changed it because i have no use for that
for index, value in next, tbl do
--if typeof(value) == 'table' then -- realised i don’t need this, typing this quickly.
--recurseTable(value, func)
--else
func(index, value)
--end
end
end
local DataList = {}
recurseTable(Data, function(index, value)
table.insert(DataList, index)
end)
DataStore2.Combine("DATA", unpack(DataList))
local function playerAdded(player)
recurseTable(Data, function(index, value)
local DataThingy = DataStore2(player, index)
local function callRemote(value)
ReplicatedStorage.Events:FindFirstChild(index):FireClient(player, value)
end
callRemote(DataThingy:Get(value))
DataThingy:OnUpdate(callRemote)
end)
end
Players.PlayerAdded:Connect(playerAdded)
for _, player in next, Players:GetPlayers() do
playerAdded(player)
end
-- marketplace example
local CashProducts = {}
CashProducts[123123] = 100
function MarketPlaceService.ProcessReceipt(receipt)
local playerId = receipt.PlayerId
local player = Players:GetPlayerByUserId(playerId)
if CashProducts[receipt.ProductId] then
local coins = DataStore2('Coins', player)
coins:Increment(CashProducts[receipt.ProductId])
return Enum.ProductPurchaseDecision.PurchaseGranted
end
end
ReplicatedStorage.BuyProduct.OnServerEvent:connect(function(player, productName)
if not Products[productName] then -- product doesn't exist
return -- end it here
end -- goo goo gaga
local coinStore = DataStore2("Coins", player)
local productPrice = Products[productName].Price
if coinStore:Get(Data.Coins) >= productPrice then
print("Buying product", productName)
coinStore:Increment(-productPrice)
end
end)
Yeah it’s a little messy, but I’m just giving a general idea of what I’d do. Obviously I’d use, OOP and stuff but I feel like this could be a fix.
What exactly is this fixing? This just looks like mostly normal DataStore2 usage to me.
The fact that DataStore2 is inefficient.
Where is DataStore2 inefficient that your code “fixes”?
I must’ve misunderstood how datastore2 actually works, So it doesn’t fix anything, it just is a way of using datastore2.
The way I want to save and update a table is by using :GetTable() → modify table → Set()
Is it possible that when this is done by 2 scripts simultaneously, the data from one of the scripts won’t be saved because the other script overwrites the data? If so, are there any alternatives to save a table simultaneously without risking data-loss?
example picking up Gold and Silver from the ground at exactly the same time
script1: (gives gold)
GetTable() → tablename[gold] = tablename[gold] + 1
script2: (gives silver)
GetTable() → tablename[silver] = tablename[silver] + 1
script1:
:Set(tablename)
script2:
:Set(tablename)
does this example means that the data which script 1 is trying to update, is not being saved? since script2 is overwriting the data with his own data, which did not include the data script 1 was about to :Set() because script 2 used GetTable() before script1 Set() its data?
Roblox is single threaded, so you won’t have real multithreading issues. I’ve never had this issue and I regularly use several scripts handling data. You could have your own issues though if you have yields.
Take for instance, this pseudo code:
local currenciesStore = DataStore2("Currencies", player)
local currencies = currenciesStore:GetTable({ Gold = 0, Silver = 0 })
-- do some number crunching to determine currencies
currenciesStore:Set(currencies)
If our crunching doesn’t yield, then here’s the process:
This is so far so good. But if our crunching yields, everything breaks!
Be wary and keep this in mind.
I think I’m missing some basic understanding about what single threaded means.
Doesn’t roblox run multiple threads at once? like multiple while loops? If so, why won’t script2 get a chance to run if script1 is not yielding? Is the interval between :get and :set just too small for script2 to use old data? Or does the thread “pause” whenever it is yielding giving script2 a chance to run it’s thread untill the yielding (pause) is over?
Since :Get() is called when a player is joining the game, it will not yield because script1 and script2 will be ran while the player is playing the game, and since Set() never yields, yielding won’t be a problem for me.
No. Roblox uses green threading, meaning that your code looks like it is using multiple threads but it’s actually just very intelligently swapping whenever you yield.
:Get() (after the first time) and :Set() never yield, so the threads aren’t switched while it’s still running.
Okay, I edited my previous post a bit too late I see,
I added the the question whether yielding “pauses” the thread, giving the other script a chance to run while it is paused. You gave me the answer anyway!
Thank you.
Can I use global data stores for this?
Not sure what you mean by this? Do you mean with non-player keys? If so, no.
If I save data in place1 then teleport the player into a branch-place can I still get the same saved data from place1?
Yes, DataStore2 works fine and keeps data between places of the same game.
I am planning on using this instead of the default datastore in my game, i am saving with tables.
if and how would this be possible? would i do it the same as if i was doing a normal datastore
tables are the only way i can save as my data needs large amounts of info such as level, xp, skins etc.
if i can’t do this, how would i do it?
Ok, so… i roughly understand how it’s supposed to work, but what i’m wondering is what does this imply? How does this affect throttling?
How do i go about setting the data? Do i still have to do ~ 3 min. intervals between saving, and if so, does it mean both of them, or just one?
My intuition says that i shouldn’t care about the regular data store causing trouble, if the keys are different, i’m not overwriting then, but i should have the ordered data store at intervals, is this true?