Is it bad to have multiple datastores?

In my script I have around 13 datastores, is there anything bad that can come from that, and if so how could I improve on it?

local DataStore = game:GetService("DataStoreService")
local ds = DataStore:GetDataStore("RaceSave")


local RankData = DataStore:GetDataStore("SpecData")

local HumansEatenData = DataStore:GetDataStore("HumansEaten")
local ReiatsuTrainingData = DataStore:GetDataStore("ReiatsuTrainingData")

local MaskData = DataStore:GetDataStore("MaskData")
local HollowMaskTrainingData = DataStore:GetDataStore("HollowMaskTraining")

local MukenDataData = DataStore:GetDataStore("MukenData")

local SPData = DataStore:GetDataStore("SpiritPressureData")


local SpecialRankData = DataStore:GetDataStore("SpecialRankData")

local NameData = DataStore:GetDataStore("NameData1")


local ShikaiNameData = DataStore:GetDataStore("ShikaiNameData1")
local ShikaiCallData = DataStore:GetDataStore("ShikaiCallData")


local ShikaiUnlockedData = DataStore:GetDataStore("ShikaiUnlockedData")
4 Likes

you shouldn’t be using that much datastores, it’s not efficient as it will lead to multiple datastore calls and i believe there’s a quota on that

instead, create a player data structure with a table and save in only a single datastore

How would I create a table in a datastore and save it/load it?

you can use JSONEncode from HTTPService and JSONDecode

tables can be stored and loaded just like any other type of value.

-- Loading Data
game.Players.PlayerAdded:Connect(function(plr)
    -- Example DataStore
    local key = plr.UserId
    local success, data = pcall(function()
        return DataStore:GetAsync(key)
    end)
    -- Accessing variable.
    local RankData = data.Rank
end)

-- Saving Data
game.Players.PlayerRemoving:Connect(function(plr)
    local key = plr.UserId
    local data
    for _, value in pairs(plr.leaderstats:GetChildren()) do
        table.insert(data,value.Value)
    end
    local success,err = pcall(function()
        DataStore:SetAsync(key,data)
    end)
end)

but like

local ShikaiData = {
	["Unlocked"] = "NotUnlocked",
	["Call"] = "Locked",
	["ShikaiName"] = "Locked",
	["WhatSword"] = "None",
}

How would I get all of this because I only know of getting data like this

local ShikaiUnlockedData = DataStore:GetDataStore("ShikaiUnlockedData")

and so on

Look at my example above and imagine instead of DataStore I wrote ShikaiUnlockedData. I only used ‘DataStore’ as an example.

local HttpService = game:GetService("HttpService")
local ShikaiUnlockedData = DataStore:GetDataStore("ShikaiUnlockedData")

local Data = {
    Key1 = "Value",
    Key2 = 123
}

-- Example of saving a table
local serialized = HttpService:JSONEncode(Data)
ShikaiUnlockedData:SetAsync('PlayerKey',serialized)

-- Now we get the data

local serialized_data = ShikaiUnlockedData:GetAsync('PlayerKey')

Data = HttpService:JSONDecode(serialized_data)

you can substitute “PlayerKey” for the player’s UserId

Serialization is not required for tables in datastores anymore. (Only learned this recently)

1 Like

When I load the data I put it as a value under the player in a folder, when they leave I save it so how would I save it back to the table from the value

image

i.e when I leave how do I change shikai name in the data to “Test” instead of “Locked”

local Data = {
	["Unlocked"] = "NotUnlocked",
	["Call"] = "Locked",
	["ShikaiName"] = "Locked",
	["WhatSword"] = "None",
}

you can index the Data table with the name of the StringValue to load the data there and to save back

So would I do it somewhat like this?

local Folder = Instance.new("Folder",leader)
	Folder.Name = "ShikaiInfo"
	
	
	local ShikaiName = Instance.new("StringValue",Folder)
	ShikaiName.Name = "ShikaiName"
	
	
	local serialized = HttpService:JSONEncode(Data)
	ShikaiUnlockedData:SetAsync(player.UserId,serialized)
	
	
	local serialized_data = ShikaiUnlockedData:GetAsync(player.UserId)
	
	Data = HttpService:JSONDecode(serialized_data)
	warn(Data)
	
	
	ShikaiName.Value = Data.ShikaiName
	
	
	ShikaiName.Changed:Connect(function()
		Data.ShikaiName = ShikaiName.Value

		local serialized = HttpService:JSONEncode(Data)
		ShikaiUnlockedData:SetAsync(player.UserId,serialized)
	end)

yep and also

	ShikaiName.Changed:Connect(function()
		Data.ShikaiName = ShikaiName.Value

		local serialized = HttpService:JSONEncode(Data)
		ShikaiUnlockedData:SetAsync(player.UserId,serialized)
	end)

try to avoid setting the datastore multiple times unless you really need to
it would be best to either periodically save the data (5 - 10 minutes) or save the data when the player leaves

Thank you, one last thing. I tried changing my data, all the prints went through, I changed ShikaiName to test,

ShikaiName.Changed:Connect(function()
		Data.ShikaiName = ShikaiName.Value
		warn(Data)
		local serialized = HttpService:JSONEncode(Data)
		ShikaiUnlockedData:SetAsync(player.UserId,serialized)
		print("SAVED")
	end)

Saved was printed but when I joined back shikainame was “Locked” again and not “Test”

you’re changing the value locally, it will not replicate to the server

Screenshot_2023-08-02_20-42-34

you’d need to click Current: Client to switch to Current: Server in order to change the value

Thats what I tried doing maybe because Roblox is going through some issues right now

Edit: I just tried changing one of my other datastores and it saved and loaded perfectly fine does the encode/decode method need roblox to be up?

does the encode/decode method need roblox to be up?

no it’s done locally

Hm, Can you tell me if I made any errors in my script then?

local HttpService = game:GetService("HttpService")

local DataStore = game:GetService("DataStoreService")

local ShikaiUnlockedData = DataStore:GetDataStore("ShikaiUnlockedData")


local Data = {
	["Unlocked"] = "NotUnlocked",
	["Call"] = "Locked",
	["ShikaiName"] = "Locked",
	["WhatSword"] = "None",
}

game.Players.PlayerAdded:connect(function(player)
	local leader = Instance.new("Folder",player)
	leader.Name = "Data"

	
	
	
	local Folder = Instance.new("Folder",leader)
	Folder.Name = "ShikaiInfo"
	
	
	local ShikaiName = Instance.new("StringValue",Folder)
	ShikaiName.Name = "ShikaiName"
	
	
	local serialized = HttpService:JSONEncode(Data)
	ShikaiUnlockedData:SetAsync(player.UserId,serialized)
	
	
	local serialized_data = ShikaiUnlockedData:GetAsync(player.UserId)
	
	Data = HttpService:JSONDecode(serialized_data)
	warn(Data)
	
	
	ShikaiName.Value = Data.ShikaiName
	
	
	ShikaiName.Changed:Connect(function()
		Data.ShikaiName = ShikaiName.Value
		warn(Data)
		local serialized = HttpService:JSONEncode(Data)
		ShikaiUnlockedData:SetAsync(player.UserId,serialized)
		print("SAVED")
	end)
end)

late into this i notice a couple of flaws

1st you’re actually saving the Data table when the player joins

	local serialized = HttpService:JSONEncode(Data)
	ShikaiUnlockedData:SetAsync(player.UserId,serialized)

it’ll overwrite what was saved previously

you can check if the player previously had data by doing:

local serialized_data = ShikaiUnlockedData:GetAsync(player.UserId)

if serialized_data then
  -- load the player data in
else
  -- do something else
end

2nd, you’re overwriting the Data templete with the players data

you can return a copy by doing

local function ReturnTemplete()
      return  {
	["Unlocked"] = "NotUnlocked",
	["Call"] = "Locked",
	["ShikaiName"] = "Locked",
	["WhatSword"] = "None",
}
end

Where would I use

local function ReturnTemplete()
      return  {
	["Unlocked"] = "NotUnlocked",
	["Call"] = "Locked",
	["ShikaiName"] = "Locked",
	["WhatSword"] = "None",
}
end

In my script?