Is my dataStore safe?

Well, well, I gave myself the task of investigating how to improve my DataStore, how to make it safe and then I ended up basing a little on GEILER123456 and a small part of GAFFAL_1236 in the part of ejecting the player if there is an error when loading the data that that after that you will lose the data (this way they will not be lost (or that is what I understood)).

After seeing the GEILER123456 method, I realized that it was difficult for me to replicate it with the data I need since I use 11 Values ​​that I need to save and load (each one serves to configure things, such as a configuration menu), and then only I put a few little things that are shown in your method. Even after doing it, I’m not convinced even if it works.

local DataStoreService = game:GetService("DataStoreService")
local configurationsData = DataStoreService:GetDataStore("ConfigurationsData")

Players.PlayerAdded:Connect(function(player)
	local DataFolder = Instance.new("Configuration")
	DataFolder.Name = "SettingsData"
	DataFolder.Parent = player
	local GraphicsFolder = Instance.new("Folder")
	GraphicsFolder.Name = "Graphics"
	GraphicsFolder.Parent = DataFolder
	local GameFolder = Instance.new("Folder")
	GameFolder.Name = "GameSettings"
	GameFolder.Parent = DataFolder
	local KeysFolder = Instance.new("Folder")
	KeysFolder.Name = "Keys"
	KeysFolder.Parent = DataFolder

	local success, KeyInfo = pcall(function()
		return configurationsData:GetAsync(player.UserId)
	end)
	if not success then
		warn(KeyInfo)
		player:Kick("Has sido expulsado del juego para evitar la pérdida de datos, ingrese de nuevo / You have been kicked from the game to avoid data loss, please log in again.")
	elseif success then
		if KeyInfo ~= nil then
			GraphicsFolder:WaitForChild("Shadow").Value = KeyInfo.shadows
			shadowSettings[KeyInfo.shadows ](player)
			GraphicsFolder:WaitForChild("Water").Value = KeyInfo.water
			waterSettings[KeyInfo.water](player)
			GraphicsFolder:WaitForChild("Tree").Value = KeyInfo.tree_texture
			treeSettings[KeyInfo.tree_texture](player)

			GameFolder:WaitForChild("FPS").Value = KeyInfo.fps
			ViewFPS[KeyInfo.fps](player)
			GameFolder:WaitForChild("Ping").Value = KeyInfo.ping
			ViewPing[KeyInfo.ping](player)
			GameFolder:WaitForChild("BrilloVol").Value = KeyInfo.gamma
			VolumenDeBrillo["Gamma"](player, KeyInfo.gamma)
			GameFolder:WaitForChild("Language").Value = KeyInfo.language
			LanguageConfg[KeyInfo.language](player, "PlayerAdded")

			KeysFolder:WaitForChild("Crouch").Value = KeyInfo.crouch
			CrouchKey[KeyInfo.crouch](player)
		else
			GraphicsFolder:WaitForChild("Shadow").Value = "Medio"
			shadowSettings.Medio(player)
			GraphicsFolder:WaitForChild("Water").Value = "Medio"
			waterSettings.Medio(player)
			GraphicsFolder:WaitForChild("Tree").Value = "Enabled"
			treeSettings.Enabled(player)

			GameFolder:WaitForChild("FPS").Value = "UnEnabled"
			ViewFPS.UnEnabled(player)
			GameFolder:WaitForChild("Ping").Value = "UnEnabledPing"
			ViewPing.UnEnabledPing(player)
			GameFolder:WaitForChild("BrilloVol").Value = 0.5
			VolumenDeBrillo["Gamma"](player, 0.5)
			GameFolder:WaitForChild("Language").Value = "English"
			LanguageConfg.English(player)

			KeysFolder:WaitForChild("Crouch").Value = "OnePress"
			CrouchKey.OnePress(player)
		end
	end
end)

local function save(player, dontWait)
	local SettingsData = player:FindFirstChild("SettingsData")
	if SettingsData then
		local Graphics = SettingsData:FindFirstChild("Graphics")
		local GameSettings = SettingsData:FindFirstChild("GameSettings")
		local Keys = SettingsData:FindFirstChild("Keys")
		if Graphics and GameSettings and Keys then

			local Send_Data = {
				shadows = player.SettingsData.Graphics.Shadow.Value;
				water = player.SettingsData.Graphics.Water.Value;
				tree_texture = player.SettingsData.Graphics.Tree.Value;

				fps =player.SettingsData.GameSettings.FPS.Value;
				ping = player.SettingsData.GameSettings.Ping.Value;
				gamma = player.SettingsData.GameSettings.BrilloVol.Value;
				friends = player.SettingsData.GameSettings.PlayerChose.Value;
				language = player.SettingsData.GameSettings.Language.Value;
				SizeSlots = player.SettingsData.GameSettings.SlotsInventory.Value;

				crouch = player.SettingsData.Keys.Crouch.Value;
			}
			local Success,Error
			repeat
				Success,Error = pcall(configurationsData.UpdateAsync, configurationsData, player.UserId,function(Data)
					return Send_Data
				end)
			until Success 
			if Success then
				print("Se ha guardado correctamente / Has been saved successfully")
			else
				print("hubo un error al guardar / there was an error saving")
				warn(Error)
			end
		end	
	end
end

game:BindToClose(function()
	if RunService:IsStudio() then
		task.wait(2)
	else
		local finished = Instance.new("BindableEvent")
		local allPlayers = Players:GetPlayers()
		local leftPlayers = #allPlayers

		for _, player in pairs(allPlayers) do
			coroutine.wrap(function()
				save(player)
				leftPlayers -= 1
				if leftPlayers == 0  then
					finished:Fire()
				end
			end)()
		end
		finished.Event:Wait()
	end
end)

Players.PlayerRemoving:Connect(save)
1 Like