Still cases are bugged giving everyone the item

I’ve tried EVERYTHING to fix this bug, and it is not working at all. When you open cases, sometimes everyone in the server will get it, if you sell, itll get rid of everyones inv as if your data is linked. Heres my data code:

local aloe = {};
aloe.__index = aloe;
--// SERVICES \\
local DataStoreService = game:GetService("DataStoreService")
local wipeData = 20
local wipeLeaderboards = 20
--// DATA VARS \\
local sessionData = {};
local dataSet = DataStoreService:GetDataStore("AloeV"..wipeData)
local RapSet = DataStoreService:GetOrderedDataStore('AloeV.' .. wipeLeaderboards .. ' _Rap')
local BuxSet = DataStoreService:GetOrderedDataStore('AloeV.' .. wipeLeaderboards .. '_Bux')
local JPSET = DataStoreService:GetOrderedDataStore('AloeV.' .. wipeLeaderboards .. '_JP')
local startData = {
	Values = {
		Bux = 250000,
		Tix = 0,
		XP = 0,
		Level = 0,
		Gems = 0,
		CasesOpen = 1,
		Progress = 0,
		Prestige = 1,
		JackpotProfit = 0,
	},
	Arrays = {
		Inventory = {},
		Flags = {},
		Equipped = {};
	}
}
--// FUNCTIONS \\
local function recursiveCopy(dataTable)
	local tableCopy = {}
	for index, value in pairs(dataTable) do
		if type(value) == "table" then
			value = recursiveCopy(value)
		end
		tableCopy[index] = value
	end
	return tableCopy
end
aloe.post = function(player, body, title)
	game.ReplicatedStorage.Notification:FireClient(player, body, title)
end
aloe.Get = function(value1)
	return sessionData[value1];
end
local rewards = {};
aloe.AddReward = function(player, amount)
	rewards[player] += amount
end
aloe.GetReward = function(player)
	return rewards[player]
end

aloe.LockJackpotAndCrash = function()

end
aloe.FailSafeSave = function()
	local MainSavingPoint = coroutine.running()
	local MainPointsRunning = 0
	for k, v in ipairs(game.Players:GetPlayers()) do
		local MainSavingProcess = coroutine.wrap(function()
			aloe.Save(v) 
			MainPointsRunning -= 1 
			if MainPointsRunning == 0 then
				coroutine.resume(MainSavingPoint)
			end
		end)
		MainPointsRunning += 1
		MainSavingProcess(v)
	end
	if MainPointsRunning > 0 then
		coroutine.yield()
	end
end
aloe.RAPCalculate = function(value1)
	local inventory = sessionData[value1].Arrays.Inventory;
	if not inventory then return 0 end
	local rap = 0
	for i, v in pairs(inventory) do
		rap += v.Amount * v.Rap;
	end
	return rap;
end
aloe.StartServer = function(value1)
	if dataSet:GetAsync(value1.UserId) then
		sessionData[value1] = dataSet:GetAsync(value1.UserId)
	else
		sessionData[value1] = {
			Values = {
				Bux = 250000,
				Tix = 0,
				XP = 0,
				Level = 0,
				Gems = 0,
				CasesOpen = 1,
				Progress = 0,
				Prestige = 1,
				JackpotProfit = 0,
			},
			Arrays = {
				Inventory = {},
				Flags = {},
				Equipped = {};
			}
		}
	end
	rewards[value1] = 0
	return setmetatable(sessionData[value1], aloe.__index);
end
aloe.Save = function(value1)
	task.spawn(function()
		dataSet:SetAsync(value1.UserId, sessionData[value1])
		RapSet:SetAsync(value1.Name .. ";" .. value1.UserId, aloe.RAPCalculate(value1))
		JPSET:SetAsync(value1.Name .. ";" .. value1.UserId, sessionData[value1].Values.JackpotProfit)
	end)
end
aloe.GrabRap = function()
	local globalData = {};
	local page = RapSet:GetSortedAsync(false, 100);
	page = page:GetCurrentPage();

	for key, value in next, page do
		globalData[#globalData + 1] = {value.key, value.value};
	end

	return globalData;
end
aloe.grabJpProfit = function()
	local globalData = {};
	local page = JPSET:GetSortedAsync(false, 100);
	page = page:GetCurrentPage();

	for key, value in next, page do
		globalData[#globalData + 1] = {value.key, value.value};
	end

	return globalData;
end

aloe.Flag = function(player, FlagReason, FlagTitle)

end

aloe.GiveItem = function(player, item2, Amount)
	local item
	local inventory = sessionData[player].Arrays.Inventory;
	for i = 1, #inventory do
		local v = inventory[i]
		if v.ItemId == item2 then
			v.Amount += Amount
			return
		end
	end
	local items = require(script.Parent.Items)
	for i, v in pairs(items) do
		if v.ItemId == item2 then
			item = v
		end
	end
	item.Amount = Amount;
	inventory[#inventory + 1] = item;
end
aloe.CaseItem = function(player, item2, Amount)
	local item
	local inventory = sessionData[player].Arrays.Inventory;
	for i = 1, #inventory do
		local v = inventory[i]
		if v.ItemId == item2.ItemId then
			v.Amount += Amount
			return
		end
	end
	item2.Amount = Amount;
	inventory[#inventory + 1] = item2;
end
aloe.RemoveItem = function(player, itemId, amount)
	local inventory = sessionData[player].Arrays.Inventory;
	if not itemId then return end
	local buxToReturn = 0 -- This is only if selling and not jackpotting
	for i, v in pairs(inventory) do
		if v.ItemId == itemId then
			if v.Locked == true then
				buxToReturn = 0;
				break
			end
			if v.Amount - amount == 0 then
				buxToReturn = amount * v.Rap
				table.remove(inventory, i);
				break
			end
			if tonumber(v.Amount) > amount then
				v.Amount -= amount;
				buxToReturn = amount * v.Rap
				break
			end
		end
	end
	local x = sessionData[player].Values.Prestige
	if x == 1 then x = 1 else x = x * 5.75 end
	return buxToReturn * x
end
aloe.Prestige = function(player)
	local inventory = sessionData[player].Arrays.Inventory; -- BYPASSES LOCK
	local prestigeItemCount = 0
	for i, v in pairs(inventory) do
		if inventory[i].ItemId == 140469106 then
			prestigeItemCount += inventory[i].Amount
			break
		end
	end
	sessionData[player].Arrays.Inventory = {};
	aloe.GiveItem(player, 140469106, prestigeItemCount)
end
aloe.SellAll = function(player)
	local offset = 0;
	local inventory = sessionData[player].Arrays.Inventory;
	for index = 1, #inventory do
		local item = inventory[index - offset];

		if not item.Locked then
			if item and item.Amount > 1 then

				local averagePrice = aloe.RemoveItem(player, item.ItemId, item.Amount);

				if averagePrice then
					sessionData[player].Values.Bux = sessionData[player].Values.Bux + averagePrice;
				end
			else
				local averagePrice = aloe.RemoveItem(player, item.ItemId, item.Amount);
				if averagePrice then
					sessionData[player].Values.Bux  = sessionData[player].Values.Bux + averagePrice;
				end
			end
			offset = offset + 1;
		end
	end
end

aloe.FindSpecificInventoryItem = function(player, itemInLook)
	local inventory = sessionData[player].Arrays.Inventory;
	local found = false;
	for i = 1, #inventory do
		if inventory[i].ItemId == itemInLook then
			found = true
			break
		end
	end
	return found
end

aloe.JackpotItem = function(player, itemId, amount)
	local inventory = sessionData[player].Arrays.Inventory;
	local doesHaveItem = false
	if amount < 1 then 
		return false
	end
	for i, v in pairs(inventory) do
		if v.ItemId == itemId then
			if v.Locked == true then
				doesHaveItem = false;
				break
			end
			if v.Amount - amount == 0 then
				doesHaveItem = true;
				table.remove(inventory, i);
				break
			end
			if tonumber(v.Amount) > amount then
				v.Amount -= amount;
				doesHaveItem = true;
				break
			end
		end
	end
	return doesHaveItem;
end
return setmetatable(aloe, sessionData)

Case code:


game.ReplicatedStorage.Spin.OnServerEvent:Connect(function(player, case, amount, key)
	local playerData = Data.Get(player);
	amount = tonumber(amount) or 1	
	if amount <= 0 then amount = 1 end
	if case and not spinData[player] then
		local caseItems = require(script.CaseData)[case].Items;
		print(case)
		local casePrice = require(script.CaseData)[case].Price;
		local winner = caseItems[math.random(1,#caseItems)];
		local bux = playerData.Values.Bux
		local casesOpen = playerData.Values.CasesOpen;
		if bux >= casePrice and casesOpen >= amount then
			spinData[player] = true
			playerData.Values.Bux-=casePrice*amount;
			local secretChance = math.random(1, 1000000000)
			if secretChance == 1 then 
				winner = 10760425;
				game.ReplicatedStorage.Chat:FireAllClients(player.Name .. ' has unboxed a secret item! The Staff of Sparks! (0.000000001' .. '%)','SourceSansBold')
			end
			Data.GiveItem(player, winner, amount)
			openCase(player, winner, amount)
			playerData.Values.Progress += 1
			wait(0.035)
			spinData[player] = nil;
		else
			Data.post(player, 'You are missing bux or cases required.','Case')
		end
	end
end)

Just bumping this, not sure if this is allowed but this is a major bug.

again, 2 days no response on this. This is breaking my game completely.

As before, item = v is just copying the table reference. So when the new item is added to the player’s inventory, it’s not an actual copy, but a reference to the table in script.Parent.Items. Change your code to this in aloe.GiveItem and it should work:

	for i, v in pairs(items) do
		if v.ItemId == item2 then
			item = recursiveCopy(v)
		end
	end

Any time you are adding a new item, you need to do a full recursive copy if it’s a table, or use Instance:Clone() if it’s an instance of a class like a part, model, or something.

I noticed that you have copied your starting data manually on an if statement. That will work (I tested it), but use recursiveCopy to copy that too.

Ahh okay! Thank you very much. I should read the docs on tables more haha