--Updated Code and Question--<<

When the player joins the game, if their data is successfully loaded, or they are a new player, the script sets a flag(setting bool value to true) to show that their data can be saved. If their data fails to load, this value is set to false.

local store = game:GetService("DataStoreService")
local getstore = store:GetDataStore("Playerstats1")
local runservice = game:GetService("RunService")
local serverstorage = game:GetService("ServerStorage")


local writedata = function(key, datatable, plrfolder)
	
	local cansave = plrfolder:FindFirstChild("dataloaded")
	if not cansave then return end
	if not cansave.Value == true then return end
	if cansave.Value == true then
		
		local succeed, errored = pcall(function()
			getstore:SetAsync(key, datatable)
		end)
		if succeed then
			print("New Data saved successfully")
		else
			warn("Newdata has not been saved. Reason: "..errored)
		end
		
		
	end
end



game:GetService("Players").PlayerAdded:Connect(function(plr)
	local playerfolder = serverstorage:WaitForChild("PlayerData")
	
	local stats = Instance.new("Folder")
	stats.Name = tostring(plr.UserId)
	local level = Instance.new("IntValue", stats)
	level.Name = "Level"
	local experience = Instance.new("IntValue", stats)
	experience.Name = "Experience"
	local berries = Instance.new("IntValue", stats)
	berries.Name = "Berries"
	local power = Instance.new("IntValue", stats)
	power.Name = "Power"
	local melee = Instance.new("IntValue", stats)
	melee.Name = "Melee"
	local weapon = Instance.new("IntValue", stats)
	weapon.Name = "Weapon"
	local fruit = Instance.new("IntValue", stats)
	fruit.Name = "Fruit"	
	
	local dataloaded = Instance.new("BoolValue", stats)
	dataloaded.Name = "dataloaded"
	
	local key = plr.UserId
	local savedvalues
	
	local success, errormessage = pcall(function()
		savedvalues = getstore:GetAsync(key)
	end)
	
	if success then
		
		if savedvalues ~= nil then
			
			level.Value = savedvalues[1]
			experience.Value = savedvalues[2]
			berries.Value = savedvalues[3]
			power.Value = savedvalues[4]
			melee.Value = savedvalues[5]
			weapon.Value = savedvalues[6]
			fruit.Value = savedvalues[7]
			dataloaded.Value = true
			
			
			
		else
			--new  player
			level.Value = 1
			experience.Value = 0
			berries.Value = 0
			power.Value = 1
			melee.Value = 1
			weapon.Value = 1
			fruit.Value = 0
			dataloaded.Value = true
			
			local valuestosave = {level.Value, experience.Value, berries.Value, power.Value, melee.Value,
			weapon.Value, fruit.Value}
			
			writedata(key, valuestosave)
		end

	else	
		--failed to load data
		dataloaded.Value = false
		wait()
		plr:Kick("Failed to load data. Rejoin to try again.")
	end
	stats.Parent = playerfolder
end)

local updatedata = function(plr)
	
	local key = plr.UserId
	local playerfolder = serverstorage:WaitForChild("PlayerData")
	local mydata = playerfolder:FindFirstChild(tostring(plr.UserId))
	if not mydata then return end
	local dataloaded = mydata:FindFirstChild("dataloaded")
	local level = mydata:FindFirstChild("Level")
	local experience = mydata:FindFirstChild("Experience")
	local berries = mydata:FindFirstChild("Berries")
	local power = mydata:FindFirstChild("Power")
	local melee = mydata:FindFirstChild("Melee")
	local weapon = mydata:FindFirstChild("Weapon")
	local fruit = mydata:FindFirstChild("Fruit")
-----------------------------------------------------------
	if dataloaded == nil then
		plr:Kick()
	else
		
		if dataloaded.Value == false then
			plr:Kick()
		end
	end
-----------------------------------------------------------	
	local valuestosave = {level.Value, experience.Value, berries.Value, power.Value,
	melee.Value, weapon.Value, fruit.Value}
	
	local successfully, warningmessage = pcall(function()
		getstore:SetAsync(key, valuestosave)
	end)
	
	if successfully then
		--data successfully saved
			
	else
		warn("warning, data could not be saved! Retrying!")
		local retry_count = 0
		while retry_count <6 do
			wait(60)
			local success, errormessage = pcall(function()
				getstore:SetAsync(key, valuestosave)
			end)
			if success then
				break
			else
				retry_count = retry_count + 1
			end
		end
	end
	
end






game:GetService("Players").PlayerRemoving:Connect(updatedata)

game:BindToClose(function()
	if runservice:IsStudio() then
		print("is studio")
		return
	else
		if not runservice:IsStudio() then
			print("not in studio")
			for i, v in pairs(game:GetService("Players"):GetPlayers()) do
				updatedata(v)
			end
		end
	end
end)

Is it a good idea to rely on a bool value to decide whether or not the data should be saved? Wouldn't an exploiter be able to change this value?

5 comments

0

Saving a lot of things at once could make it so that the game doesnt save if a lot of people leave. Also this code could cause a lot of data loss maybe

0

any recommendations?

0

Yeah don't use 4 compartments to save data within.

0

I've just updated my code. Thanks for the Input

0

In general, value objects should not be used to store data like this. This is a bad practice that has carried over from the pre-FilteringEnabled days when it was an easy way to pass values between client and server. Nowadays, this doesn't work, and you should just store player data in a table.