When a player join, he get other player's data

Hello. I made a dataservice module but I have a problem. Everything works fine but sometimes when a player join, he get the data of an other player. Can someone solve this problem?
Here is the script:

local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetDataStore("PlayerData")
local HttpService = game:GetService("HttpService")
local MarketPlaceService = game:GetService("MarketplaceService")
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Events = ReplicatedStorage:WaitForChild("Events")

local DataService = {}
DataService.__index = DataService

local template = {
	Stage = 1,
	Rebirths = 0,
	Coins = 0,
	CoinsPositions = {
		Positions = {},
		Refreshed = false,
	},
	
	MorphsOwned = {},
}

local Cooldown = {}
local Referenced = {}
local Using_Data = {}
local Stages, Coins, Maid

local Gamepasses = {
	["Gravity Coil"] = 99413769,
	["Speed Coil"] = 99414476,
	["Rainbow Carpet"] = 99413938,
	["Jetpack"] = 99413472,
	["Ghost Bundle"] = 99410657,
	["Nightmare Rush"] = 99411076,
	["Nightmare Ambush"] = 99411348,
	["Flashlight"] = 100101933,
	["Timothy"] = 99411540,
	["Shadow"] = 99411709,
	["Freeze"] = 99411876,
	["VIP"] = 100293851,
}

function get_random_in_whitelist(folder:Folder, actual)
	local number = math.random(1,#folder:GetChildren())
	if not table.find(actual, number) then
		table.insert(actual, number)
		return actual
	else
		return get_random_in_whitelist(folder, actual)
	end
end

function DataService.Start(_manager)
	Stages = _manager.Stages
	Coins = _manager.Coin
	Maid = _manager.Maid
	
	Events.GetData.OnServerInvoke = function(player)
		if Cooldown[player] == true then
			player:Kick("Exploit protocol.")
			return
		end
		
		Cooldown[player] = true
		return DataService.Get(player).Data or {}
	end
	
	local function player_added(player:Player)
		local function character_added(character)
			local folder = player:WaitForChild("Gamepasses", 1000)
			for _, v in pairs(folder:GetChildren()) do
				if v.Value == true and script.Tools:FindFirstChild(v.Name) then
					script.Tools:WaitForChild(v.Name):Clone().Parent = player.Backpack
				end
			end
		end
		
		if player.Character then
			task.spawn(character_added, player.Character)
		end
		player.CharacterAdded:Connect(character_added)
		
		DataService.new(player)
	end
	
	local function player_removing(player:Player)
		if Referenced[player] ~= nil then
			Referenced[player]:Destroy()
		end
	end
	
	for _, v in pairs(Players:GetPlayers()) do
		task.spawn(player_added, v)
	end
	
	Players.PlayerAdded:Connect(player_added)
	Players.PlayerRemoving:Connect(player_removing)
	
	game:BindToClose(function()
		for _, v in pairs(Players:GetChildren()) do
			if Referenced[v] ~= nil then
				Referenced[v]:Destroy()
			end
		end

		repeat
			task.wait(1)
		until next(Using_Data) == nil
	end)
end

function DataService.Get(player:Player)
	if Referenced[player] == nil then
		repeat
			wait(1)
		until player == nil or not (player:IsDescendantOf("Players")) or Referenced[player] ~= nil
	end

	return Referenced[player]
end

function DataService.new(player:Player)
	local self = setmetatable({
		_maid = Maid.new(),
	}, DataService)
	
	self.Owner = player
	self.Data = {}
	
	local s,e = pcall(function()
		return DataStore:GetAsync("Player_"..self.Owner.UserId)
	end)
	
	if s then
		self.Data = e or template
		self:UpdateTemplate()
		
		for i, v in pairs(self.Data) do
			warn(tostring(i), tostring(v))
		end
		
		if self.Data.Refreshed == false then
			self:RegenerateCoins()
		end
		
		local leaderstats = Instance.new("Folder")
		leaderstats.Name = "leaderstats"
		leaderstats.Parent = self.Owner

		self.Stage = Instance.new("IntValue")
		self.Stage.Value = self.Data.Stage
		self.Stage.Name = "Stage"
		self.Stage.Parent = leaderstats

		self.Coins = Instance.new("IntValue")
		self.Coins.Value = self.Data.Coins
		self.Coins.Name = "Coins"
		self.Coins.Parent = leaderstats

		self.Rebirths = Instance.new("IntValue")
		self.Rebirths.Value = self.Data.Rebirths
		self.Rebirths.Name = "Rebirths"
		self.Rebirths.Parent = leaderstats

		self.GamepassFolder = Instance.new("Folder")
		self.GamepassFolder.Name = "Gamepasses"
		self.GamepassFolder.Parent = self.Owner

		for gamepassName, gamepassId in pairs(Gamepasses) do
			local value = Instance.new("BoolValue")
			value.Name = gamepassName
			value.Value = MarketPlaceService:UserOwnsGamePassAsync(self.Owner.UserId, gamepassId)
			value.Parent = self.GamepassFolder
		end
	else
		warn("Error: Failed to get player data: "..self.Owner.UserId..".")
	end
	
	self._maid:GiveTask(function()
		if Referenced[self.Owner] ~= nil then
			Referenced[self.Owner] = nil
		end
		
		Using_Data[self.Owner.UserId] = true
		
		local s, e = pcall(function()
			DataStore:SetAsync("Player_"..self.Owner.UserId, self.Data)
		end)
		
		if s then
			warn("Successfully saved data for the player key: "..self.Owner.UserId)
		else
			warn("Error: Failed to save data for the player: "..self.Owner.UserId.." - "..tostring(e)..".")
		end
		
		Using_Data[self.Owner.UserId] = nil
		self = nil
	end)
	
	Referenced[self.Owner] = self
	return self
end

function DataService:Update()
	self.Stage.Value = self.Data.Stage
	self.Coins.Value = self.Data.Coins
	self.Rebirths.Value = self.Data.Rebirths
	
	Events.DataUpdate:FireClient(self.Owner, self.Data)
end

function DataService:Add(statName:string, increment:number)
	if self.Data[statName] then
		self.Data[statName] += increment
		self:Update()
	else
		warn("Cannot find the stat named: "..tostring(statName)..".")
	end
end

function DataService:Set(statName:string, newValue:any)
	if self.Data[statName] then
		self.Data[statName] = newValue
		self:Update()
	else
		warn("Cannot find the stat named: "..tostring(statName)..".")
	end
end

function DataService:UpdateTemplate()
	for index, value in pairs(template) do
		if not self.Data[index] then
			self.Data[index] = value
			warn("Updated index "..tostring(index)..", set to "..tostring(value)..". (Data added)")
		end
	end
end

function DataService:SkipStage(player:Player)
	self:Add("Stage", 1)
end

function DataService:RegenerateCoins()
	local actual = {}

	for i = 1, 30 do
		actual = get_random_in_whitelist(script:WaitForChild("CoinPositions"), actual)
	end

	self.Data.CoinsPositions.Positions = actual
	self.Data.Refreshed = true
end

function DataService:ReplicateCoins(player:Player)
	for _, pos in pairs(self.Data.CoinsPositions.Positions) do
		Coins.new(self.Owner, pos)
	end
end

function DataService:Destroy()
	self._maid:DoCleaning()
end

return DataService

Example: (Coins changed because they picked up some coins)
image

Ok I found the problem. I diddnt clone the table named “template” so when a new player joined, data were set to template and if data were edited, template were edited and when a new player joined, he got the old player data. So replace the self.Data = e or template with self.Data = e or table.clone(template)

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.