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

This wouldn’t work since:

If statvalue is a userdata, then it’s not a table of RGB values.

yeah, so i should just do a basic else because its not a data type? I mean, if a table is a data type like number or string, id like to know… or if its just “Table” XD

Just this last part is important
you can ignore everything else

for statname, statvalue in pairs(CharInfoInStore) do
	
	if type(statvalue) == 'number' then
		local intvalue = Instance.new("NumberValue")
		intvalue.Name = statname
		intvalue.Value = statvalue
		intvalue.Parent = CharacterStats
	elseif type(statvalue) == 'boolean' then
		local boolvalue = Instance.new("BoolValue")
		boolvalue.Name = statname
		boolvalue.Value = statvalue
		boolvalue.Parent =  CharacterStats
	elseif type(statvalue) == 'string' then
		local stringvalue = Instance.new("StringValue")
		stringvalue.Name = statname
		stringvalue.Value = statvalue
		stringvalue.Parent = CharacterStats
	else
		local stringvalue = Instance.new("Color3Value")**
		stringvalue.Name = statname**
		stringvalue.Value = Color3.new(statvalue[1],statvalue[2],statvalue[3])**
		stringvalue.Parent = CharacterStats**
	end
end

It’s just “table”, yes.

type({ 1, 2, 3 }) == "table"

2 Likes

I want to use orderedDatastores to make a global leaderboard, but I’m not sure if the way I want to do it is right because I am using ordered datastores next to DataStore2.

The way I do it:

--ServerScript
local Cash= game:GetService("DataStoreService"):GetOrderedDataStore("Cash")

local succes, error = pcall(function()
    local Data = CashODS:GetSortedAsync(false,24)
    --do something with the data given.
end)

if not Success then
    print("error")
end

while true do
    for _, player in pairs(game.Players:Getplayers()) do
        Cash:SetAsync(player.Name, player.leaderstats.Cash)
    end
    
     --filling the leaderboard with Gui(s)

    wait(20)
end

Can I use orderedDatastores this way without throttling Datastore2?

With DataStore2 I use .Combine to have everything stored into one Datastore.

If you combine all into one store, then you shouldn’t have issues, though if you want to be safe (and don’t care about the current data) you can switch the saving method to Standard.

2 Likes

let’s say I do this:

DataStore2.Combine("DATA", "points", "Cash", "Boosts")

Is it possible to use setbackup for the datastore “DATA” too since all datastores get together in one big datastore called “DATA”? Or do I have to call SetBackup() for each key individual?

If I would get the datastore “points” which is one of the keys that is combined, I would just do:

pointsDataStore = DataStore2("points", "player")
pointsDataStore:SetBackup(5)

--if  pointsDataStore:IsBackup then...

If you call :SetBackup on any key, it’ll affect the whole combined data store. It’s just a bit confusing with semantics, and will be changed in the future.

1 Like

So if I want to use .combined, I shouldn’t be using SetBackup() at all? Since there is not way to SetBackup() for the key to which everything is combined (which is “DATA” from my previous post)

Not sure where you got this impression, I said the opposite in what you’re replying to?

1 Like

Yep, I was a bit fast with replying. I thought you ment it would affect the whole combined data store in a negative way.

Is this valid with DataStore2?

DataStore2.combine( "Master", "Points", "Coins" )
DataStore2.combine( "Points", "Kills", "Deaths" )

Will the structure end up being Master>Points>Kills? Or is a new Points table setup at the root of the datastore.

Also, do dashes “-” in the DataStore name matter? I’m trying to debug some code.

That is not valid code, no.

Yes.

You can’t combine multiple keys under another key?

Dashes will screw up my stores? How so?

You can–but you can’t do this:

image

This doesn’t make sense. If you do DataStore2("Points", player), what is DataStore2 meant to use? I know what you’re trying to do, but I’d be surprised if this did anything reasonable, and whatever it does do is unguaranteed.

I misread–they don’t matter.

1 Like

I thought it was used to access subtables but I think you’re right.

My hope would be that a :Get() would load the data under Points and store it in Master.

Edit:

I think I figured out my problem.

Does .Combine() expect all keys to be tables? What about nested Combines, it seems like it’s expecting everything to be a table. This isn’t noted anywhere in the documentation.

Also, does :GetTable() call the BeforeInitialGet event? It seems like my serialization is not running on load, but is working fine on save.

1 Like

I’m finally playing with serialization and deserialization. First question because the github is a tad unclear and i just wana be sure i’m using this correctly, i litteraly just create a dictionary with only the Names of the things i’m saving, right? Like this:

local InitialDictionary = {
	"CharName",
	"CharDesc",
	"Aires",
	"CurrentLand",
	"Gender",
	"Skin Tone",
	"Face",
	"Full_Set",
	"Upper",
	"Lower",
	"Hair",
	"Head Wear",
	"Back",
	"BodyTypeScale",
	"DepthScale",
	"HeadScale",
	"HeightScale",
	"WidthScale",
}

Second question, What if you have a large dictionary such as this:

Apparel_Store:GetTable({
--Full Sets----------------------------------------------
--Simple Velvet Robes--
	["Black Velvet Robes"] = {["Type"] = "Apparel",["Description"] = "A Robe for the common Witch or Wizard", ["Item_Count"] = 5,["Equippable_Type"] = "Full_Set",  ["Icon"] = "rbxassetid://3882850634", ["Effect"] = 25, ["Worth"] = 50, ["Equipped_To_Toolbar"] = false, ["Equipped"] = false, ["Toolbar_Binding"] = "Unequipped", ["Character_Slot"] = "Unequipped",["SlotNum"] = ""};
	["Blue Velvet Robes"] = {["Type"] = "Apparel",["Description"] = "A Robe for the common Witch or Wizard", ["Item_Count"] = 5,["Equippable_Type"] = "Full_Set",  ["Icon"] = "rbxassetid://3882850634", ["Effect"] = 25, ["Worth"] = 50, ["Equipped_To_Toolbar"] = false, ["Equipped"] = false, ["Toolbar_Binding"] = "Unequipped", ["Character_Slot"] = "Unequipped",["SlotNum"] = ""};
	["Gold Velvet Robes"] = {["Type"] = "Apparel",["Description"] = "A Robe for the common Witch or Wizard", ["Item_Count"] = 5,["Equippable_Type"] = "Full_Set",  ["Icon"] = "rbxassetid://3882850634", ["Effect"] = 25, ["Worth"] = 50, ["Equipped_To_Toolbar"] = false, ["Equipped"] = false, ["Toolbar_Binding"] = "Unequipped", ["Character_Slot"] = "Unequipped",["SlotNum"] = ""};
	["Green Velvet Robes"] = {["Type"] = "Apparel",["Description"] = "A Robe for the common Witch or Wizard", ["Item_Count"] = 2,["Equippable_Type"] = "Full_Set",  ["Icon"] = "rbxassetid://3882850634", ["Effect"] = 25, ["Worth"] = 50, ["Equipped_To_Toolbar"] = false, ["Equipped"] = false, ["Toolbar_Binding"] = "Unequipped", ["Character_Slot"] = "Unequipped",["SlotNum"] = ""};
	["Lavender Velvet Robes"] = {["Type"] = "Apparel",["Description"] = "A Robe for the common Witch or Wizard", ["Item_Count"] = 1,["Equippable_Type"] = "Full_Set",  ["Icon"] = "rbxassetid://3882850634", ["Effect"] = 25, ["Worth"] = 50, ["Equipped_To_Toolbar"] = false, ["Equipped"] = false, ["Toolbar_Binding"] = "Unequipped", ["Character_Slot"] = "Unequipped",["SlotNum"] = ""};
	["Pink Velvet Robes"] = {["Type"] = "Apparel",["Description"] = "A Robe for the common Witch or Wizard", ["Item_Count"] = 5,["Equippable_Type"] = "Full_Set",  ["Icon"] = "rbxassetid://3882850634", ["Effect"] = 25, ["Worth"] = 50, ["Equipped_To_Toolbar"] = false, ["Equipped"] = false, ["Toolbar_Binding"] = "Unequipped", ["Character_Slot"] = "Unequipped",["SlotNum"] = ""};
	["Red Velvet Robes"] = {["Type"] = "Apparel",["Description"] = "A Robe for the common Witch or Wizard", ["Item_Count"] = 5,["Equippable_Type"] = "Full_Set",  ["Icon"] = "rbxassetid://3882850634", ["Effect"] = 25, ["Worth"] = 50, ["Equipped_To_Toolbar"] = false, ["Equipped"] = false, ["Toolbar_Binding"] = "Unequipped", ["Character_Slot"] = "Unequipped",["SlotNum"] = ""};
	["Violet Velvet Robes"] = {["Type"] = "Apparel",["Description"] = "A Robe for the common Witch or Wizard", ["Item_Count"] = 5,["Equippable_Type"] = "Full_Set",  ["Icon"] = "rbxassetid://3882850634", ["Effect"] = 25, ["Worth"] = 50, ["Equipped_To_Toolbar"] = false, ["Equipped"] = true, ["Toolbar_Binding"] = "Unequipped", ["Character_Slot"] = "Upper",["SlotNum"] = ""}; -- Equipped right now
	["White Velvet Robes"] = {["Type"] = "Apparel",["Description"] = "A Robe for the common Witch or Wizard", ["Item_Count"] = 5,["Equippable_Type"] = "Full_Set",  ["Icon"] = "rbxassetid://3882850634", ["Effect"] = 25, ["Worth"] = 50, ["Equipped_To_Toolbar"] = false, ["Equipped"] = false, ["Toolbar_Binding"] = "Unequipped", ["Character_Slot"] = "Unequipped",["SlotNum"] = ""};		
	["Yellow Velvet Robes"] = {["Type"] = "Apparel",["Description"] = "A Robe for the common Witch or Wizard", ["Item_Count"] = 2,["Equippable_Type"] = "Full_Set", ["Icon"] = "rbxassetid://3882851079", ["Effect"] = 25, ["Worth"] = 50, ["Equipped_To_Toolbar"] = false, ["Equipped"] = false, ["Toolbar_Binding"] = "Unequipped", ["Character_Slot"] = "Unequipped",["SlotNum"] = ""};
--Upper Body-----------------------------------------

--Lower Body--------------------------------------------
--Peasant--
	["Peasent Pants"] = {["Type"] = "Apparel",["Description"] = "~Speaks for itself~", ["Item_Count"] = 3,["Equippable_Type"] = "Lower", ["Icon"] = "rbxassetid://3891589519", ["Effect"] = 1, ["Worth"] = 50, ["Equipped_To_Toolbar"] = false, ["Equipped"] = false, ["Toolbar_Binding"] = "Unequipped", ["Character_Slot"] = "Unequipped", ["SlotNum"] = ""};
--Head Wear--------------------------------------------------------
	["Pointed Hat"] = {["Type"] = "Apparel",["Description"] = "A hat for the truest Witch or Wizard, simple, yet iconic", ["Item_Count"] = 1,["Equippable_Type"] = "Head Wear", ["Icon"] = "rbxassetid://3891589519", ["Effect"] = 60, ["Worth"] = 100, ["Equipped_To_Toolbar"] = false, ["Equipped"] = false, ["Toolbar_Binding"] = "Unequipped", ["Character_Slot"] = "Unequipped",["SlotNum"] = ""};
})

How would do i create the initial dictionary for this particular store? Do i just do the same exact thing only without the values in them?

Thx @Kampfkarren

The way you do serialization/deserialization is completely up to you–whatever the documentation shows (which is I assume what you are referring to) is just an example to help you understand the concept better.

1 Like

Alright, i suppose i’m just trying to understand exactly how it works because for instance one of the problems i’m having is for the character information store, its loading the physical values after i deserialize it, but not into the right places, for instance i have a vector 3 value, the “Skin Tone” as shown in the first initial dictionary i sent in the last message, and when i just reentered the game after having my info saved, it is not able to run the functions i need because its detecting a bool value in the skin tone for some reason.

I’m storing mountains of data in total in the compilation of a bunch of different stores, and i’m getting yellow warnings in the output after others who are helping me test leave saying that certain stores are did not update… which i think means it didn’t save when the player left, my thinking is maybe its because it had a lot to save in a short amount of time, and it wasn’t able to get all of the info in? Either way i’m trying to serialize a lot of data for the convenience, much of the data is of different kinds, from bools to strings to vector 3’s (i’m just using a table with 3 values in it for those).

Some of these are saving others are not, and the only one that has serialization right now is the CharInfoStore25 because thats what i’m experimenting with first.

I think i have figured out the problem, see i’m just starting to understand serialization, ok… so the deserializing and serializing code is from the github, and it sets the value it fetches to true, thats where i am getting the bool value. My new issue is figuring out how to get the value of the serialized things and load that… i’m not quite sure what to do with that though…

does the deserialzing in the beforeinitialget work just like the normal :Get()? Only turning the data back into strings? So that if the data is new it will do a default value of in the case of your example of beforeinitialget:() the value is true.

That’s the job of :BeforeInitialGet. When you :Get() for the first time, the data store will hold serialized data. BeforeInitialGet is ran to deserialize it, so the only thing you ever receive with :Get is the deserialized data.