How to make a folder with saved owned cars instead of a datastore for each one?

I have a dealership UI to buy cars and it works, but there is a datastore for saving each of my 5 cars. I want to know how I can make a saved cars folder that has 1 datastore that has every car you own, so when I add more cars to the game, I don’t have 20 datastores for it. I guess I could add a folder in serverstorage and make it add the cars to it, but I don’t know how. This is my code now:

local players = game:GetService("Players")
local dataStore = game:GetService("DataStoreService")
local CarDataStore1 = dataStore:GetDataStore("CarDataStore1")
local CarDataStore2 = dataStore:GetDataStore("CarDataStore2")
local CarDataStore3 = dataStore:GetDataStore("CarDataStore3")
local CarDataStore4 = dataStore:GetDataStore("CarDataStore4")
local CarDataStore5 = dataStore:GetDataStore("CarDataStore5")


players.PlayerAdded:Connect(function(player)
	local folder = Instance.new("Folder")
	folder.Name = "OwnedCars"
	folder.Parent = player

	
	local car1 = Instance.new("BoolValue")
	car1.Name = "Basic sedan"
	car1.Parent = player.OwnedCars
	car1.Value = CarDataStore1:GetAsync(player.UserId) or false
	CarDataStore1:SetAsync(player.UserId, car1.Value)
	
	local car2 = Instance.new("BoolValue")
	car2.Name = "Basic SUV"
	car2.Parent = player.OwnedCars
	car2.Value = CarDataStore2:GetAsync(player.UserId) or false
	CarDataStore2:SetAsync(player.UserId, car2.Value)

	local car3 = Instance.new("BoolValue")
	car3.Name = "Basic truck"
	car3.Parent = player.OwnedCars
	car3.Value = CarDataStore3:GetAsync(player.UserId) or false
	CarDataStore3:SetAsync(player.UserId, car3.Value)
	
	local car4 = Instance.new("BoolValue")
	car4.Name = "Luxurious sedan"
	car4.Parent = player.OwnedCars
	car4.Value = CarDataStore4:GetAsync(player.UserId) or false
	CarDataStore4:SetAsync(player.UserId, car4.Value)
	
	local car5 = Instance.new("BoolValue")
	car5.Name = "Sporty coupe"
	car5.Parent = player.OwnedCars
	car5.Value = CarDataStore1:GetAsync(player.UserId) or false
	CarDataStore5:SetAsync(player.UserId, car5.Value)





	---

	car1.Changed:Connect(function()
		CarDataStore1:SetAsync(player.UserId, car1.Value)

		car2.Changed:Connect(function()
			CarDataStore2:SetAsync(player.UserId, car2.Value)
			
			car3.Changed:Connect(function()
				CarDataStore3:SetAsync(player.UserId, car3.Value)

				car4.Changed:Connect(function()
					CarDataStore4:SetAsync(player.UserId, car4.Value)

					car5.Changed:Connect(function()
						CarDataStore5:SetAsync(player.UserId, car5.Value)
					end)
				end)
			end)
		end)
	end)
	end)

Instead of having multiple different ones, you need to just make a table of owned cars. Then, you can check this table/list when the user joins the game.

So, instead of saving a boolean for each car, save a table to one DataStore.

local ownedCars = {'Sporty coupe', 'Luxurious sedan', 'Basic truck'}

Check the list and change your BooleanValues based on what’s inside.

1 Like

Hello @natty_boppin

I know something which will definitely solve this issue and you can definitely configure your code and you can use this for future reference if you were to make another game.

First of all for completely delete all your lines where you’ve defined many datastores

local CarDataStore1 = dataStore:GetDataStore("CarDataStore1")
local CarDataStore2 = dataStore:GetDataStore("CarDataStore2")
local CarDataStore3 = dataStore:GetDataStore("CarDataStore3")
local CarDataStore4 = dataStore:GetDataStore("CarDataStore4")
local CarDataStore5 = dataStore:GetDataStore("CarDataStore5")

You only need one datastore so just do this

local players = game:GetService("Players")
local dataStore = game:GetService("DataStoreService")
local CarDataStore = dataStore:GetDataStore("CarDatastore")

Where you’ve added the Changed:Connect function you have 5 events which you’ve nested which isn’t efficient. What you should do is when you’re saving the cars we’ll use a dictionary instead

local carData = {
	["car1"] = car1.Value,
	["car2"] = car2.Value
	["car3"] = car3.Value,
	["car4"] = car4.Value,
	["car5"] = car5.Value
}

Then we can save the entire table to the database

CarDataStore:SetAsync(player.UserId,carData)

If a user was to have a sixth car then you would just Get the car data and append another dictionary value to it. And when loading the data you would do a loop which will create an X amount of BoolValues in the car data.

I hope this helps.

3 Likes

Btw this is called a Dictionary and this is a perfect example of when it can be used.

1 Like

it works but its saying that too many datastore requests were made so I just want to ask if I can remove

CarDataStore:SetAsync(player.UserId, car1.Value)

for each car where I make the bool values because I still have all this for each car:

local car1 = Instance.new("BoolValue")
	car1.Name = "Basic sedan"
	car1.Parent = player.OwnedCars
	car1.Value = CarDataStore:GetAsync(player.UserId) or false
	CarDataStore:SetAsync(player.UserId, car1.Value)

I meant a dictionary, I’m half asleep today. Thanks for correcting me. :slightly_smiling_face:

Hi @natty_boppin you’ll have to change your entire code when you’re saving one value to the database. Instead you’ll need to detect when the value is changed and instead of saving one value, you’ll need to remove the existing index inside the dictionary and append the new value and save to the database. I’m willing to give you an example tomorrow when i’m on pc.

Okay im going to wait until tomorrow to fix this because now when you click the button to buy a car and you don’t have enough coins, the next time you join it says that you already own that car
ill give the rest of the code tomorrow if you need it

Yeah that would be great. Just reply to this with the code.

I gave all the code to help because I don’t know what code needs to be fixed

Original script i needed help with (in a folder in serverscriptservice)

local players = game:GetService("Players")
local dataStore = game:GetService("DataStoreService")
local CarDataStore = dataStore:GetDataStore("CarDatastore")

players.PlayerAdded:Connect(function(player)
	local folder = Instance.new("Folder")
	folder.Name = "OwnedCars"
	folder.Parent = player
	
	local car1 = Instance.new("BoolValue")
	car1.Name = "Basic sedan"
	car1.Parent = player.OwnedCars
	car1.Value = CarDataStore:GetAsync(player.UserId) or false

	local car2 = Instance.new("BoolValue")
	car2.Name = "Basic SUV"
	car2.Parent = player.OwnedCars
	car2.Value = CarDataStore:GetAsync(player.UserId) or false

	local car3 = Instance.new("BoolValue")
	car3.Name = "Basic truck"
	car3.Parent = player.OwnedCars
	car3.Value = CarDataStore:GetAsync(player.UserId) or false
	
	local car4 = Instance.new("BoolValue")
	car4.Name = "Luxurious sedan"
	car4.Parent = player.OwnedCars
	car4.Value = CarDataStore:GetAsync(player.UserId) or false
	
	local car5 = Instance.new("BoolValue")
	car5.Name = "Sporty coupe"
	car5.Parent = player.OwnedCars
	car5.Value = CarDataStore:GetAsync(player.UserId) or false

	local carData = {
		["car1"] = car1.Value,
		["car2"] = car2.Value,
		["car3"] = car3.Value,
		["car4"] = car4.Value,
		["car5"] = car5.Value
	}
	
	CarDataStore:SetAsync(player.UserId,carData)
end)

Purchasing script in the same folder

game.ReplicatedStorage.DealershipEvents.BuyCar.OnServerEvent:Connect(function(player,Car)
	local Price = game.ServerStorage.ShopCars:FindFirstChild(Car).Price.Value
	local Coins = player.leaderstats.Coins
	if Price and Coins.Value >= Price and player.OwnedCars:FindFirstChild(Car).Value == false then
		Coins.Value = Coins.Value - Price
		player.OwnedCars:FindFirstChild(Car).Value = true
	end
end)

Car buy button

script.Parent.MouseButton1Down:Connect(function()
	local player = game.Players.LocalPlayer
	local Car = script.Parent.Parent.Car.Value
	if player and script.Parent.Parent.Selected.Value == true then
		game.ReplicatedStorage.DealershipEvents.BuyCar:FireServer(Car)
		if player.OwnedCars:FindFirstChild(Car).Value == true then
			script.Parent.Text = "Car already owned!"
			wait(2)
			script.Parent.Text = "Purchase car"
		end
	end
end)

Set up so that when a car in the list is clicked, the info will show up on these labels and you can buy it with this button
Screenshot 2023-03-27 at 10.08.57 AM
Code for one of the cars in the list (they’re all the same for each car)

local ServerStorage = game:GetService("ServerStorage")

local CarName = script.Parent.Name

local Car = ServerStorage:WaitForChild("ShopCars"):FindFirstChild(CarName)

if Car then

script.Parent.CarName.Text = Car.CarName.Value

script.Parent.Price.Text = Car.Price.Value.." coins"

end

script.Parent.ClickButton.MouseButton1Click:Connect(function()

local BuyFrame = script.Parent.Parent.Parent.BuyFrame

BuyFrame.CarName.Text = Car.CarName.Value

BuyFrame.Price.Text = Car.Price.Value.." coins"

BuyFrame.Car.Value = CarName

BuyFrame.Selected.Value = true

BuyFrame.PriceValue.Value = Car.Price.Value.." coins"

end)

Sorry for the late reply try this

local players = game:GetService("Players")
local dataStore = game:GetService("DataStoreService")
local CarDataStore = dataStore:GetDataStore("CarDatastore")

players.PlayerAdded:Connect(function(player)
	local folder = Instance.new("Folder")
	folder.Name = "OwnedCars"
	folder.Parent = player

	local car1 = Instance.new("BoolValue")
	car1.Name = "Basic sedan"
	car1.Parent = player.OwnedCars
	car1.Value = CarDataStore:GetAsync(player.UserId)["car1"] or false

	local car2 = Instance.new("BoolValue")
	car2.Name = "Basic SUV"
	car2.Parent = player.OwnedCars
	car2.Value = CarDataStore:GetAsync(player.UserId)["car2"] or false

	local car3 = Instance.new("BoolValue")
	car3.Name = "Basic truck"
	car3.Parent = player.OwnedCars
	car3.Value = CarDataStore:GetAsync(player.UserId)["car3"] or false

	local car4 = Instance.new("BoolValue")
	car4.Name = "Luxurious sedan"
	car4.Parent = player.OwnedCars
	car4.Value = CarDataStore:GetAsync(player.UserId)["car4"] or false

	local car5 = Instance.new("BoolValue")
	car5.Name = "Sporty coupe"
	car5.Parent = player.OwnedCars
	car5.Value = CarDataStore:GetAsync(player.UserId)["car5"] or false

	local carData = {
		["car1"] = car1.Value,
		["car2"] = car2.Value,
		["car3"] = car3.Value,
		["car4"] = car4.Value,
		["car5"] = car5.Value
	}
	
	
	for _, car in ipairs(player.OwnedCars:GetChildren()) do
			car.Changed:Connect(function()
				local carData = {
					["car1"] = car1.Value,
					["car2"] = car2.Value,
					["car3"] = car3.Value,
					["car4"] = car4.Value,
					["car5"] = car5.Value
			}	
			CarDataStore:SetAsync(player.UserId, carData)
		end)
	end
end)
1 Like

I tried it, and while the buying part works, it now doesn’t know if you own the car or not, so you can buy it multiple times. I also get the following errors in my developer console (it just looks like it errors when I try to buy the cars because I’ve tried to buy multiple):