Why is my data duplicating?

.CreateInventory() (method below) gets called whenever a player joins the server. And then it checks the player’s previous save and then puts back all those items back, after that to test the data saving, I added ServerInventoryManager.GiveItem(player, "Slinger", "Plantable", 5) to add a new item with a new GUID.

But whenever I play test again, my items gets duplicated and when I rejoin, those duplicated items will be duplicated indefinitely.

HandledItems[player.Name] = data.Inventory

	task.spawn(function()
		
		local items = table.clone(HandledItems[player.Name])

		for guid, item in items do
			ServerInventoryManager.GiveItem(player, item.Name, item.Type, item.Quantity, item.Size)
		end
		
		ServerInventoryManager.GiveItem(player, "Slinger", "Plantable", 5)
	end)

function ServerInventoryManager.GiveItem(player: Player, itemName: string, typeOfTool: TOOLS, initialValue: number?, size: number?)
	--...
	
	if inventory then
		--...
		-- Adding items into array
		local playerItems = HandledItems[player.Name]
		if playerItems then
			local data: ItemData.Item_Data = {
				Name = itemName,
				Quantity = initialValue,
				Size = size or 1,
				Type = typeOfTool,
			}
			
			playerItems[guid] = data
		else
			warn("Tried to add item, but player was not initialized in HandledItems.")
		end
	end
end

Try not using a cloned version of the table, instead use the table itself (HandledItems[player.Name])

Could we see the code where you’re saving the data? And the code where you’re getting it?

That was the original method, but it still results the same problem

local Players = game:GetService("Players")
local ServerScriptService = game:GetService("ServerScriptService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")

local Template = require(script.Template)
local ProfileStore = require(ServerScriptService.Libraries.ProfileStore)
local Leaderstat = require(ServerScriptService.Modules.Leaderstat)
local ServerInventoryManager = require(ServerScriptService.Modules.Managers.ServerInventoryManager)

local INDEX = 14
local DS_KEY = `Prod_{INDEX}`
if RunService:IsStudio() then
	DS_KEY = `Studio_{INDEX}`
end

local PlayerStore = ProfileStore.New(DS_KEY, Template.SHARED_TEMPLATE)

local DataManager = {}
DataManager.Profiles = {} :: {[Player]: typeof(PlayerStore:StartSessionAsync())}

function DataManager.LoadProfile(player: Player)
	local profile = PlayerStore:StartSessionAsync(`{player.UserId}`, {
		Cancel = function()
			return player.Parent ~= Players
		end,
	})
	
	if profile == nil then
		return player:Kick("Unable to load profile")
	end
	
	profile:AddUserId(player.UserId)
	profile:Reconcile()
	
	profile.OnSessionEnd:Connect(function()
		DataManager.Profiles[player] = nil
		player:Kick("Ended session")
	end)
	
	local isInGame = player.Parent == Players
	if isInGame then
		DataManager.Profiles[player] = profile
	else
		profile:EndSession()
	end
	
	local data = DataManager.GetData(player)
	
	Leaderstat.Create(player, data)
	ServerInventoryManager.CreateInventory(player, data)
end

function DataManager.GetData(player: Player) : Template.PLAYER_DATA?
	local profile = DataManager.Profiles[player]
	if not profile then return end

	return profile.Data
end

function DataManager.RemoveProfile(player: Player)
	local profile = DataManager.Profiles[player]
	if profile ~= nil then
		profile:EndSession()
	end
end

function DataManager.Start()
	for _, player in Players:GetPlayers() do
		task.spawn(DataManager.LoadProfile, player)
	end

	Players.PlayerAdded:Connect(DataManager.LoadProfile)
	Players.PlayerRemoving:Connect(DataManager.RemoveProfile)
end

DataManager.Start()

return DataManager

It’s just a standard ProfileStore setup

But reading what you sent, that’s literally what you’re designing it to do though?

-------- [ Top part ] --------

-- Your data was already set to that same spot
HandledItems[player.Name] = data.Inventory

-- // Right below
-- Cloning it here, which doesn't seem to be doing much
local items = table.clone(HandledItems[player.Name])
for guid, item in items do
	ServerInventoryManager.GiveItem(
		player,
		item.Name,
		item.Type,
		item.Quantity,
		item.Size
	)
end

-------- [ Bottom part ] --------

-- Which is currently your data.Inventory
local playerItems = HandledItems[player.Name]

-- // Little further down
-- new guid, not the same as previous guid came from nowhere
-- global/outside variable it's not passed through giveItem function
playerItems[guid] = data

So when you say you’re “putting it back”, it was already there in the first place. I don’t think profile service clears the profile.Data when it saves, so you’re just duplicating your data when you join. Or save, idk when this occurs in your code.

1 Like

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