Need help with massive design flaw with data inside of my game

Hello!
I recently found a bug inside of my game. It is that data gets reset sometimes without me doing it.

Solutions I tried:

I tried adding Datastore2 to it but it seems too complicated to understand. If you can help, please let me know.

Thanks, WE

Could you please provide the code so myself and others can try to find the issue?

local Players = game:GetService("Players")
local ServerScriptService = game:GetService("ServerScriptService")
local Workspace = game:GetService("Workspace")

local DataStore2 = require(ServerScriptService.DataStore2)

-- Combine every key you use. This will eventually be the default, but for now read the "Gotchas" section to understand why we need this.
DataStore2.Combine("DATA", "points")

Players.PlayerAdded:Connect(function(player)
    local pointsStore = DataStore2("points", player)

    local leaderstats = Instance.new("Folder")
    leaderstats.Name = "leaderstats"

    local points = Instance.new("NumberValue")
    points.Name = "Points"
    points.Value = pointsStore:Get(0) -- The "0" means that by default, they'll have 0 points
    points.Parent = leaderstats

    pointsStore:OnUpdate(function(newPoints)
        -- This function runs every time the value inside the data store changes.
        points.Value = newPoints
    end)

    leaderstats.Parent = player
end)

is this still hard to understand?

1 Like
Level Data Store
local DataStore = game:GetService("DataStoreService")
local ds = DataStore:GetDataStore("AdventureModeLevel")

game.Players.PlayerAdded:Connect(function(player)
	local leader = Instance.new("Folder",player)
	leader.Name = "AdventureMode"
	local Level = Instance.new("NumberValue",leader)
	Level.Name = "Level"
	Level.Value = ds:GetAsync(player.UserId) or 1
	ds:SetAsync(player.UserId, Level.Value)
	Level.Changed:Connect(function()
		ds:SetAsync(player.UserId, Level.Value)
	end)
end)


game.Players.PlayerRemoving:Connect(function(player)
	ds:SetAsync(player.UserId, player.AdventureMode.Level.Value)
end)
CharacterShop
local starterCharScripts = game.StarterPlayer.StarterCharacterScripts

local ChangeCamSubject = game.ReplicatedStorage.Remotes.ChangeCamSubject

local new = Instance.new

local datastore = game:GetService("DataStoreService"):GetDataStore("Characters")
local updateAsync = datastore.UpdateAsync

local loadData = function(player)
	local id = player.UserId
	local data
	
	local success,output = pcall(function()
		data = datastore:GetAsync(id) 
	end)
	
	assert(success,output)
	
	if not data then
		data = {
			Characters = {},
			EquippedCharacter = "",
			leaderstats = {}
		}
	end	
	
	if not data.leaderstats then data.leaderstats = {} end
	
	for _,v in pairs(data.Characters) do
		local value = new("StringValue")
		value.Parent = player.Characters
		value.Name = v
	end
	
	for _,v in pairs(player.leaderstats:GetChildren()) do
		if data.leaderstats[v.Name] then
			v.Value = data.leaderstats[v.Name]
		end
	end
	
	player.EquippedCharacter.Value = data.EquippedCharacter
end

local saveData = function(player)
	local id = player.UserId
	local data = {
		Characters = {},
		EquippedCharacter = "",
		leaderstats = {}
	}
	
	for _,v in pairs(player.Characters:GetChildren()) do
		table.insert(data.Characters,v.Name)
	end
	
	for _,v in pairs(player.leaderstats:GetChildren()) do
		data.leaderstats[v.Name] = v.Value
	end	
	
	data.EquippedCharacter = player.EquippedCharacter.Value
	
	local success,output = pcall(updateAsync,datastore,id,function(old)
		return data
	end)
	
	assert(success,output)
end

local ChangeChar = function(player,charModel)

	player:LoadCharacter()
	local currentChar = player.Character
	local pos = currentChar.PrimaryPart.CFrame
	
	local animate = charModel:FindFirstChild('Animate')
	local health = charModel:FindFirstChild('Health')
	
	local curAnimate = currentChar:FindFirstChild("Animate")
	local curHealth = currentChar:FindFirstChild("Health")
	
	if not health and curHealth then
		curHealth:Clone().Parent = charModel
		curHealth:Destroy()
	end 
	
	charModel.Name = player.Name
	charModel.Parent = workspace
	player.Character = charModel
	charModel.PrimaryPart:SetNetworkOwner(player)
	charModel.PrimaryPart.CFrame = pos
	
	if not animate and curAnimate then
		curAnimate:Clone().Parent = charModel
		curAnimate:Destroy()
	end
	
	if not charModel.Humanoid:FindFirstChildOfClass("Animator") then
		local animator = new('Animator')
		animator.Parent = charModel.Humanoid
	end
	
	currentChar:Destroy()
	
	for _,v in pairs(starterCharScripts:GetChildren()) do
		if not charModel:FindFirstChild(v.Name) then
			v:Clone().Parent = charModel
		end
	end
	
	ChangeCamSubject:FireClient(player,charModel.Humanoid)
	
	charModel.Humanoid.Died:Connect(function()
		wait(game.Players.RespawnTime)
		updateChar(player)
	end)
end

updateChar = function(player)
	local equippedChar = player.EquippedCharacter.Value
	local chars = player.Characters
	local curChar = player.Character or player.CharacterAdded:Wait()
	local changing = player.ChangingChar
	
	if changing.Value then
		repeat wait(0.1) until not changing.Value
	end
	
	changing.Value = true
	
	if chars:FindFirstChild(equippedChar) then
		local module = game.ServerStorage.Characters:FindFirstChild(equippedChar)
		if module then
			local char = module:FindFirstChildOfClass("Model")
			ChangeChar(player,char:Clone())
		else
			player:LoadCharacter()
		end
	else
		player:LoadCharacter()
	end
	
	wait(0.1)
	changing.Value = false
end

local onJoin = function(player)
	
	-- // This is where we stored player money.
	local stats = player:WaitForChild("leaderstats")
	
	-- // This is where we store the purchased character.
	local characterfolder = new("Folder")
	characterfolder.Parent = player
	characterfolder.Name = "Characters"
	
	-- // Player's currency for the character shop.
	local money = stats:WaitForChild("Points")
	
	-- // Equipped Character Value
	local EquippedCharacter = new("StringValue")
	EquippedCharacter.Parent = player
	EquippedCharacter.Name = "EquippedCharacter"
	
	local changing = new("BoolValue")
	changing.Parent = player
	changing.Name = "ChangingChar"
	
	loadData(player)
	
	updateChar(player)
	EquippedCharacter.Changed:Connect(function()
		updateChar(player)
	end)
end

game.Players.PlayerAdded:Connect(onJoin)
game.Players.PlayerRemoving:Connect(saveData)
PointsData
local DataStore = game:GetService("DataStoreService")

local ds = DataStore:GetDataStore("Points")

game.Players.PlayerAdded:Connect(function(player)

local leader = Instance.new("Folder",player)

leader.Name = "leaderstats"

local Cash = Instance.new("IntValue",leader)

Cash.Name = "Points"

Cash.Value = ds:GetAsync(player.UserId) or 50

ds:SetAsync(player.UserId, Cash.Value)

Cash.Changed:Connect(function()

ds:SetAsync(player.UserId, Cash.Value)

end)

end)

game.Players.PlayerRemoving:Connect(function(player)

ds:SetAsync(player.UserId, player.leaderstats.Points.Value)

end)

And there are also multiple Time Trials data. Here is an example of 1 script:

Time Trials Example
local DataStore = game:GetService("DataStoreService")
local ds = DataStore:GetDataStore("SmallWorld")

game.Players.PlayerAdded:Connect(function(player)
	local leader = player:WaitForChild("TimeTrials")
	local SmallWorld = Instance.new("StringValue",leader)
	SmallWorld.Name = "SmallWorld"
	SmallWorld.Value = ds:GetAsync(player.UserId) or "9999999999"--Something in the lobby is this is someones score will say that they have never played the map before. 
	ds:SetAsync(player.UserId, SmallWorld.Value)
	SmallWorld.Changed:Connect(function()
		ds:SetAsync(player.UserId, SmallWorld.Value)
	end)
end)


game.Players.PlayerRemoving:Connect(function(player)
	ds:SetAsync(player.UserId, player.TimeTrials.SmallWorld.Value)
end)

There are also settings for the in-game settings.

Settings Example
local DataStore = game:GetService("DataStoreService") --Call Datastore

local ds = DataStore:GetDataStore("UISounds") --Creates key

game.Players.PlayerAdded:Connect(function(player) --If Player added then

local charactershopdata = player:WaitForChild("SettingsData") --Finds the folder

local Bool = Instance.new("IntValue",charactershopdata) --Creates a Bool

Bool.Name = "UISounds" --Names the bool

Bool.Value = ds:GetAsync(player.UserId) or 1 --WIll make it false if not already yet

ds:SetAsync(player.UserId, Bool.Value) -- Saves

Bool.Changed:connect(function() --If changed

ds:SetAsync(player.UserId, Bool.Value) --saves

end)

end)

game.Players.PlayerRemoving:Connect(function(player) --If Player Remove then

ds:SetAsync(player.UserId, player.SettingsData.UISounds.Value) --Saves

end)

And there is also a ban data:

Ban Example
local ManualBan = {}

local DataStoreService = game:GetService("DataStoreService")
local BanData = DataStoreService:GetDataStore("Exploiting")

game.Players.PlayerAdded:Connect(function(player)
	

	local PlayerUserId = player.UserId
	
	if ManualBan[PlayerUserId] then
		player:Kick("You have been banned for violating the WEstudios terms of service. Exploiting is now allowed. ")
	end
	
	local banned
	local sucess, errormessage = pcall(function()
		banned = BanData:GetAsync(PlayerUserId)
	end)
	
	if banned == true then
		player:Kick("You have been banned for violating the WEstudios terms of service. Exploiting is now allowed. ")
	else
		banned = false
	end
	
end)



Yes! This works. Thank you. How would we add these to DataStore2:

Good idea will be not to put everything in one data because of game not compatible of saving so much things at ones make not one Data store make more to make sure your game wont lose any data

Oh and to save that all u need is Just too

local Points = game.Player.LocalPlayer.leaderstats.Points
Points.Value = -- the value u want to save

and good idea will be to Save it instantly as it get updated so u keep the data

Everything is not one data. I have multiple different scripts and date. What were trying to do rn is make everything DataStore2.

I mean its not good idea but u can make Table and Save each of them in it

1 Like