How To Save Multiple Values DataBase

There is a database code I have implemented and so far I have made many code to try and save multiple values, but none of them worked
Can someone please help or explain to me on what I have to do to achieve my goal?
Thank you for reading.
Here’s the line of code I currently have. I deleted all my non-working code.

local DataStoreService = game:GetService("DataStoreService")
local playerData = DataStoreService:GetDataStore("PlayerData")

local function onPlayerJoin(Player)
	local BlackMarketThings = Instance.new("Folder")
	BlackMarketThings.Name = "BlackMarketThings"
	BlackMarketThings.Parent = Player

	local SpeedCheck = Instance.new("BoolValue")
	SpeedCheck.Name = "SpeedCheck"
	SpeedCheck.Parent = BlackMarketThings
	SpeedCheck.Value = false
	
	local HealthCheck = Instance.new("BoolValue")
	HealthCheck.Name = "HealthCheck"
	HealthCheck.Parent = BlackMarketThings
	HealthCheck.Value = false

	local playerUserId = "Player_ ".. Player.UserId
	local data = playerData:GetAsync(playerUserId)
	if data then
		SpeedCheck.Value = data and data.SpeedCheck
	else
		SpeedCheck.Value = false
	end
end

local function onPlayerLeave(Player)
	local success, err = pcall(function()
		local playerUserId = "Player_ "..Player.UserId
		local speedCheckValue = Player.BlackMarketThings.SpeedCheck.Value

		local dataToSave = {
			SpeedCheck = speedCheckValue,
		}
		playerData:SetAsync(playerUserId, dataToSave)

	end)
	if not success then
		warn("Could not save data, Error message: ", err)
	else
		print("Saved 2")
	end
end

game.Players.PlayerAdded:Connect(onPlayerJoin)
game.Players.PlayerRemoving:Connect(onPlayerLeave)

Hello good afternoon, could you test this script?

Make sure that the “Enable Studio Access to API Services” option is active.

And also make sure that the script is in “ServerScriptServices”.
image

Here is a script:

local DataStoreService = game:GetService("DataStoreService")
local playerData = DataStoreService:GetDataStore("PlayerData")

local function onPlayerJoin(Player)
	local BlackMarketThings = Instance.new("Folder")
	BlackMarketThings.Name = "BlackMarketThings"
	BlackMarketThings.Parent = Player

	local SpeedCheck = Instance.new("BoolValue")
	SpeedCheck.Name = "SpeedCheck"
	SpeedCheck.Parent = BlackMarketThings
	SpeedCheck.Value = false

	local HealthCheck = Instance.new("BoolValue")
	HealthCheck.Name = "HealthCheck"
	HealthCheck.Parent = BlackMarketThings
	HealthCheck.Value = false

	local playerUserId = "Player_ ".. Player.UserId
	local GetData
	local Success, Error = pcall(function()
		GetData = playerData:GetAsync(playerUserId)
	end)
	
	if Success and GetData then
		SpeedCheck.Value = GetData[1]
	else
		SpeedCheck.Value = false
	end
end

local function onPlayerLeave(Player)
	local success, err = pcall(function()
		local playerUserId = "Player_ "..Player.UserId
		local speedCheckValue = Player.BlackMarketThings.SpeedCheck

		playerData:SetAsync(playerUserId, {
			speedCheckValue.Value
		})

	end)
	if not success then
		warn("Could not save data, Error message: ", err)
	else
		print("Saved 2")
	end
end

game.Players.PlayerAdded:Connect(onPlayerJoin)
game.Players.PlayerRemoving:Connect(onPlayerLeave)

If you get any errors, please let me know, or if you are in doubt, let me know.

ALWAYS when working with DataStore use the server side to change some value.

I just tried this script and it seems like it isn’t working, the boolean value was set on false instead of being set on true.

Which of the values did you change?

It is only saving one value of the two values

no, none of the values are saving

Have you tried this outside of studio yet?
Studio tends to close playtesting before datastores can save.

just tried, It still does not work

How are you changing the value?

Try saving a simple string and see if it still doesn’t work. Though to save a table to a datastore you can do this:

local HS = game:GetService("HttpService")

--When saving
local StringData = HS:JSONEncode(DataToSave)

--When loading
local TableData = HS:JSONDecode(LoadedData)

Basically, im building a shop, when someone buys it the value sets on true to ensure the player does not buy it again. When the player joins back his thingy that he bought is still there (for my code he would have a speed boost or a health boost).

Unfortunately, if I replace boolean with string, it would break loads of code outside the data saving.

If you convert it back when you load it like I showed it should get converted back into a boolean?

Have you tried using the function game:BindToClose()?

what does BindToClose do again?

The BindToClose function occurs before the server is shut down.

Example:

game:BindToClose(function()
	print('F')
end)

image

I understand what BindToClose means now, but how can that be added to my code? Im pretty sure it does nothing to my code

Let the PlayerRemoving function,
And add this writing:

game:BindToClose(function()
	for _, player in pairs(game.Players:GetPlayers()) do
		local UserId = player.UserId
		local speedCheckValue = player.BlackMarketThings.SpeedCheck
		local success, err = pcall(function()
			return playerData:SetAsync(UserId, speedCheckValue.Value)
		end)
		if not success then
			warn("Could not save data, Error message: ", err)
		end 
	end
end)