I tried several other ways, like making newer module’s with tool converting, to doing child adding and wouldn’t add
local ClientInventory = {}
-- Services
local Players, ReplicatedStorage, TweenService = game:GetService("Players"), game:GetService("ReplicatedStorage"), game:GetService("TweenService")
local UserInputService, RunService, StarterGui = game:GetService("UserInputService"), game:GetService("RunService"), game:GetService("StarterGui")
-- Setup
StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Backpack, false)
local player, PlayerGui = Players.LocalPlayer, Players.LocalPlayer.PlayerGui
local character, remotes = player.Character or player.CharacterAdded:Wait(), ReplicatedStorage.Remotes
local playerBackpack = player.Backpack
local humanoid = character:WaitForChild("Humanoid")
local TradeablesData = require(ReplicatedStorage.Modules.Shared.TradeablesData)
local ClientInventoryViewport = require(ReplicatedStorage.Modules.ClientModules.ClientInventoryViewport)
local ClientInventoryEffects = require(ReplicatedStorage.Modules.ClientModules.ClientInventoryEffects)
local ClientInventoryDisplay = require(ReplicatedStorage.Modules.ClientModules.ClientInventoryDisplay)
local ScreenGui = PlayerGui:WaitForChild("HUD", math.huge)
local Backpack, Notifications = ScreenGui.Backpack, ScreenGui.Notifications
local Inventory, Hotbar, DraggingFrame, ToolTip = Backpack.Inventory, Backpack.Hotbar, Backpack.DraggingFrame, Backpack.ToolTip
local ToolTipTitle, ToolTipDescription = ToolTip.ToolTipTitle, ToolTip.ToolTipDescription
local List, Equip, Unequip, ItemFrame, DisplayFrame = Inventory.List, Inventory.Equip, Inventory.Unequip, Inventory.ItemFrame, Inventory.DisplayFrame
local EquipmentFrame = Inventory.EquipmentFrame
local ItemFrameTitle, Slots = ItemFrame.Title, EquipmentFrame.Slots
local OutlineFrame, ViewportFrame, WorldModel = EquipmentFrame.Outline, EquipmentFrame.Outline.ViewportFrame, EquipmentFrame.Outline.ViewportFrame.WorldModel
local Chakra, ChakraInc, DamageInc, DefenseInc, Health, HealthInc, Speed, Stamina, StaminaInc = DisplayFrame.Chakra, DisplayFrame.ChakraInc, DisplayFrame.DamageInc, DisplayFrame.DefenseInc, DisplayFrame.Health, DisplayFrame.HealthInc,DisplayFrame.Speed, DisplayFrame.Stamina, DisplayFrame.StaminaInc
local equipAccessoryRemote = remotes.EquipAccessory
local unequipAccessoryRemote = remotes.UnequipAccessory
local checkItemRemote = remotes.CheckItem
local requestPreviewRemote = remotes.RequestAccessoryPreview
local updateAccessoryEquip = remotes.UpdateAccessoryEquipButton
local accessoryEquipSuccess = remotes.AccessoryEquipSuccess
local accessoryUnequipSuccess = remotes.AccessoryUnequipSuccess
local getInventoryData = remotes.GetInventoryData
local verifyUnequipRemote = remotes.VerifyUnequip
local requestPreviewRemotes = remotes.RequestAccessoryPreviews
local updateInventoryRemote = remotes.UpdateInventoryData
local refreshInventoryRemote = remotes.RefreshInventory
-- Private variables
local _isDragging, _draggedItem, _draggedItemOrigin, _draggedItemSlot, _draggedItemData = false, nil, nil, nil, nil
local _selectedSlot, _currentItem, _currentselectedSlot = 1, nil, nil
local _hotbarItems, _inventoryItems, _viewportModels, _slotItems, _toolMap, _previewRequests, _previewRequestsQueue = {}, {}, {}, {}, {}, {}, {}
local _dragOffsetX, _dragOffsetY = 0, 0
local equipped = {}
local selectedItemName = nil
local steps = 15
local waveStep = math.pi / 6
local colorSequenceCache = {}
local counter = 0
local frameCount = 0
local rotationIndex = 1
local mythicalGradients = {}
local _toolConnections = {}
local _equippedTool = nil
local _config = {
SLOT_SIZE = 50,
HORBAR_SIZE = 10,
INVENTORY_ROWS = 4,
INVENTORY_COLS = 6,
VIEWPORT_ROTATION_SPEED = 1,
}
ClientInventory.hotbarItems, ClientInventory.inventoryItems, ClientInventory.slotItems = _hotbarItems, _inventoryItems, _slotItems
-- Convert Tool to inventory item format
function ConvertToolToItem(tool)
if not tool or not tool:IsA("Tool") then return nil end
local itemData = {
name = tool.Name,
rarity = tool:GetAttribute("Rarity") or "Common",
description = tool:GetAttribute("Description") or "A useful tool",
quantity = 1,
id = tool.Name .. "_tool_" .. tostring(tool:GetDebugId()),
toolInstance = tool, -- Reference to actual tool
isRobloxTool = true, -- Flag to identify this as a Roblox tool
toolExists = true
}
return itemData
end
-- Sync tools from backpack to inventory
function SyncToolsToInventory()
print("Syncing tools from backpack to inventory...")
local toolsFound = 0
for _, tool in pairs(playerBackpack:GetChildren()) do
if tool:IsA("Tool") then
toolsFound = toolsFound + 1
local itemData = ConvertToolToItem(tool)
if itemData then
-- Check if tool already exists in inventory
local existingIndex = nil
for idx, item in pairs(_inventoryItems) do
if item and item.isRobloxTool and item.name == tool.Name then
existingIndex = idx
break
end
end
if not existingIndex then
-- Add tool to inventory if not already there
local success = ClientInventory.ManageItem("add", itemData)
if success then
print("Added tool to inventory:", tool.Name)
end
end
end
end
end
print("Found", toolsFound, "tools in backpack")
end
-- Remove tool from inventory when it's deleted from backpack
function RemoveToolFromInventory(toolName)
for idx, item in pairs(_inventoryItems) do
if item and item.isRobloxTool and item.name == toolName then
_inventoryItems[idx] = nil
CompactInventory()
ClientInventory.UpdateSlots("inventory")
print("Removed tool from inventory:", toolName)
break
end
end
end
-- Equip tool to character
function EquipTool(itemData)
if not itemData or not itemData.isRobloxTool then return false end
-- Unequip current tool first
if _equippedTool then
_equippedTool.Parent = playerBackpack
_equippedTool = nil
end
-- Find the tool in backpack
local tool = playerBackpack:FindFirstChild(itemData.name)
if tool and tool:IsA("Tool") then
tool.Parent = character
_equippedTool = tool
-- Update UI to show equipped state
ClientInventoryEffects.CreateNotification(1, "Tool Equipped", "Equipped " .. tool.Name)
return true
else
print("Tool not found in backpack:", itemData.name)
return false
end
end
-- Unequip current tool
function UnequipCurrentTool()
if _equippedTool then
_equippedTool.Parent = playerBackpack
local toolName = _equippedTool.Name
_equippedTool = nil
ClientInventoryEffects.CreateNotification(1, "Tool Unequipped", "Unequipped " .. toolName)
return true
end
return false
end
-- Monitor backpack changes
function SetupBackpackMonitoring()
-- Clean up existing connections
for _, connection in pairs(_toolConnections) do
connection:Disconnect()
end
_toolConnections = {}
-- Monitor tools added to backpack
table.insert(_toolConnections, playerBackpack.ChildAdded:Connect(function(child)
if child:IsA("Tool") then
print("Tool added to backpack:", child.Name)
wait(0.1) -- Small delay to ensure tool is fully loaded
local itemData = ConvertToolToItem(child)
if itemData then
ClientInventory.ManageItem("add", itemData)
end
end
end))
-- Monitor tools removed from backpack
table.insert(_toolConnections, playerBackpack.ChildRemoved:Connect(function(child)
if child:IsA("Tool") then
print("Tool removed from backpack:", child.Name)
RemoveToolFromInventory(child.Name)
end
end))
-- Monitor character changes (for re-equipping tools)
table.insert(_toolConnections, player.CharacterAdded:Connect(function(newCharacter)
character = newCharacter
humanoid = character:WaitForChild("Humanoid")
_equippedTool = nil
-- Re-sync tools after character respawn
wait(1) -- Wait for character to fully load
SyncToolsToInventory()
end))
end
function FindEmptyInvSlot()
for i = 1, _config.INVENTORY_ROWS * _config.INVENTORY_COLS do
if not _inventoryItems[i] then return i end
end
return nil
end
function CompactInventory()
local temp, idx = {}, 1
for _, item in pairs(_inventoryItems) do
if item then temp[idx], idx = item, idx + 1 end
end
_inventoryItems = temp
end
function SetupSlotEvents(slot, idx, isHb)
slot.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1 then
if isHb and not Inventory.Visible then
ClientInventory.SelectSlot(idx)
return
end
local iData = isHb and _hotbarItems[idx] or _inventoryItems[idx]
local hasItem = iData and (not isHb or iData.name ~= "Item Name")
if not isHb and hasItem then
ClientInventoryDisplay.DisplayItemInFrame(iData)
_currentItem, _currentselectedSlot = iData, idx
end
if hasItem then
_isDragging, _draggedItemOrigin = true, isHb and "hotbar" or "inventory"
_draggedItemSlot, _draggedItemData = idx, iData
_draggedItem = slot:Clone()
_draggedItem.Parent = DraggingFrame
local mPos = UserInputService:GetMouseLocation()
local sCenter = slot.AbsolutePosition + (slot.AbsoluteSize / 2)
_dragOffsetX, _dragOffsetY = mPos.X - sCenter.X, mPos.Y - sCenter.Y
_draggedItem.Position = UDim2.new(0, mPos.X-(_config.SLOT_SIZE/2)-_dragOffsetX, 0, mPos.Y-(_config.SLOT_SIZE/2)-_dragOffsetY)
_draggedItem.Size, _draggedItem.ZIndex = UDim2.new(0, _config.SLOT_SIZE, 0, _config.SLOT_SIZE), 101
end
if isHb then
ClientInventory.SelectSlot(idx)
if Inventory.Visible and iData and iData.name ~= "Item Name" then
ClientInventoryDisplay.DisplayItemInFrame(iData)
_currentItem, _currentselectedSlot = iData, idx
end
end
elseif input.UserInputType == Enum.UserInputType.MouseMovement then
TweenService:Create(slot, TweenInfo.new(0.1), {BackgroundColor3 = Color3.fromRGB(70, 70, 70)}):Play()
local iData = isHb and _hotbarItems[idx] or _inventoryItems[idx]
if iData and iData.name ~= "Item Name" then ClientInventoryEffects.ShowTooltip(iData, UserInputService:GetMouseLocation(), script.GradTemplates) end
end
end)
slot.InputChanged:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseMovement then
local iData = isHb and _hotbarItems[idx] or _inventoryItems[idx]
if iData and iData.name ~= "Item Name" and ToolTip.Visible then
ClientInventoryEffects.ShowTooltip(iData, UserInputService:GetMouseLocation(), script.GradTemplates)
end
end
end)
slot.InputEnded:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseMovement then
TweenService:Create(slot, TweenInfo.new(0.1), {BackgroundColor3 = Color3.fromRGB(50, 50, 50)}):Play()
ClientInventoryEffects.HideTooltip()
end
end)
end
function HandleDragEnd(pos)
if not Inventory.Visible and _draggedItemOrigin == "hotbar" then
if _draggedItem then _draggedItem:Destroy() end
_isDragging, _draggedItemOrigin, _draggedItemSlot, _draggedItemData = false, nil, nil, nil
return
end
if _draggedItem then _draggedItem:Destroy() end
if not _isDragging or not _draggedItemOrigin or not _draggedItemSlot or not _draggedItemData then
_isDragging = false
return
end
local tgtSlot, tgtType, tgtIdx = nil, nil, nil
-- Check hotbar slots first
for i = 1, _config.HORBAR_SIZE do
local sName = i == 10 and "0" or tostring(i)
local s = Hotbar:FindFirstChild(sName)
if s and pos.X >= s.AbsolutePosition.X and pos.X <= s.AbsolutePosition.X + s.AbsoluteSize.X and
pos.Y >= s.AbsolutePosition.Y and pos.Y <= s.AbsolutePosition.Y + s.AbsoluteSize.Y then
tgtSlot, tgtType, tgtIdx = s, "hotbar", i
break
end
end
-- If not dropped on hotbar and inventory is open, check inventory slots
if not tgtSlot and Inventory.Visible then
for i = 1, _config.INVENTORY_ROWS * _config.INVENTORY_COLS do
local s = List:FindFirstChild("InventorySlot"..i)
if s and pos.X >= s.AbsolutePosition.X and pos.X <= s.AbsolutePosition.X + s.AbsoluteSize.X and
pos.Y >= s.AbsolutePosition.Y and pos.Y <= s.AbsolutePosition.Y + s.AbsoluteSize.Y then
tgtSlot, tgtType, tgtIdx = s, "inventory", i
break
end
end
-- If dragging from hotbar and dropped in inventory area but not on slot, find empty slot
if not tgtSlot and _draggedItemOrigin == "hotbar" then
local invPos, invSize = Inventory.AbsolutePosition, Inventory.AbsoluteSize
if pos.X >= invPos.X and pos.X <= invPos.X + invSize.X and
pos.Y >= invPos.Y and pos.Y <= invPos.Y + invSize.Y then
local slot = FindEmptyInvSlot()
if slot then tgtType, tgtIdx = "inventory", slot end
end
end
end
-- Process the drop
if (tgtType and tgtIdx) then
if _draggedItemOrigin ~= tgtType or _draggedItemSlot ~= tgtIdx then
ClientInventory.MoveItem(_draggedItemOrigin, _draggedItemSlot, tgtType, tgtIdx)
end
elseif _draggedItemOrigin == "hotbar" and _draggedItemData.name ~= "Item Name" then
local slot = FindEmptyInvSlot()
if slot then ClientInventory.MoveItem(_draggedItemOrigin, _draggedItemSlot, "inventory", slot) end
end
_isDragging, _draggedItemOrigin, _draggedItemSlot, _draggedItemData = false, nil, nil, nil
end
function ClientInventory.CreateSlot(type, num, item)
local script = script
-- Make sure item is valid before proceeding
if not item then
warn("CreateSlot called with nil item for slot", num)
-- Create a default item to avoid errors
item = {name = "Item Name", rarity = "Common"}
end
-- Ensure item has required properties
if not item.rarity then item.rarity = "Common" end
if not item.name then item.name = "Item Name" end
local rarity = item.rarity
local tmpl = script.HotbarTemplates:FindFirstChild(rarity.."Template") or script:FindFirstChild("CommonTemplate")
if not tmpl then warn("Could not find template for rarity:", rarity) return nil end
local slot = tmpl:Clone()
slot.Name = type == "Inventory" and (tostring(item.name) or "InventorySlot"..num) or tostring(num)
local lbl, btn, qty = slot:FindFirstChild("Slot"), slot:FindFirstChild("Button"), slot:FindFirstChild("Quanity")
local qtyT = qty:WaitForChild("Title", math.huge)
if lbl then lbl.Text, lbl.Visible = tostring(num), (type == "Hotbar") end
-- Add tool indicator
if item.isRobloxTool then
-- Create a small tool indicator
local toolIndicator = Instance.new("Frame")
toolIndicator.Name = "ToolIndicator"
toolIndicator.Size = UDim2.new(0, 8, 0, 8)
toolIndicator.Position = UDim2.new(1, -10, 0, 2)
toolIndicator.BackgroundColor3 = Color3.fromRGB(0, 255, 0)
toolIndicator.BorderSizePixel = 0
toolIndicator.Parent = slot
-- Make it round
local corner = Instance.new("UICorner")
corner.CornerRadius = UDim.new(0, 4)
corner.Parent = toolIndicator
end
if btn then
if type == "Inventory" and item then
lbl.Visible = false
qtyT.Visible = false
btn.Text = ""
btn.MouseButton1Click:Connect(function()
local isAlreadySelected = _currentselectedSlot == tostring(num)
if _currentselectedSlot then
local prev = List:FindFirstChild("InventorySlot".._currentselectedSlot)
if prev and prev:FindFirstChild("UIStroke") then
TweenService:Create(prev.UIStroke, TweenInfo.new(0.2), {Thickness = 0}):Play()
end
end
if isAlreadySelected then
ItemFrame.Visible = false
_currentselectedSlot, _currentItem = nil, nil
else
_currentselectedSlot, _currentItem = tostring(num), item
if slot:FindFirstChild("UIStroke") then
TweenService:Create(slot.UIStroke, TweenInfo.new(0.2), {Thickness = 3}):Play()
end
ClientInventoryDisplay.DisplayItemInFrame(item)
-- Call DisplayItemInfo with the item name when selecting
if item and item.name and item.name ~= "Item Name" then
ClientInventoryDisplay.DisplayItemInfo(item.name)
end
end
end)
elseif type == "Hotbar" then
btn.MouseButton1Down:Connect(function()
ClientInventory.SelectSlot(num)
end)
end
end
if item then slot:SetAttribute("ItemName", item.name) end
if item and item.name and item.name ~= "Item Name" then
local existing = slot:FindFirstChild("ItemViewport")
if existing then existing:Destroy() end
-- Wrap in pcall to catch any errors in CreateViewPort
pcall(function()
ClientInventoryViewport.CreateViewPort(slot, item.name)
end)
end
if qty then
qty.Visible = (item and item.quantity and item.quantity > 1)
if item and item.quantity and item.quantity > 1 then qtyT.Text = tostring(item.quantity) end
end
slot:SetAttribute("TooltipConnected", true)
return slot
end
function ClientInventory.SelectSlot(idx)
if _selectedSlot == idx then return end
_selectedSlot = idx
for i = 1, _config.HORBAR_SIZE do
local slotName = i == 10 and "0" or tostring(i)
local slot = Hotbar:WaitForChild(slotName, math.huge)
if slot and slot:WaitForChild("UIStroke", math.huge) then
local isSelected = (i == _selectedSlot)
TweenService:Create(
slot.UIStroke,
TweenInfo.new(0.2),
{
Thickness = isSelected and 5 or 0,
Transparency = isSelected and 0 or 1
}
):Play()
end
end
local selectedItem = _hotbarItems[idx]
if selectedItem and selectedItem.name ~= "Item Name" then
-- If it's a tool, equip it
if selectedItem.isRobloxTool then
EquipTool(selectedItem)
end
ClientInventoryEffects.CreateNotification(1, "Selected", "Selected " .. selectedItem.name)
end
end
--Original
function ClientInventory.UpdateSlots(type)
if type == "hotbar" or type == "both" then
-- Clear existing hotbar slots
for _, child in pairs(Hotbar:GetChildren()) do
if child:IsA("ImageLabel") then child:Destroy() end
end
-- Create new hotbar slots
for i = 1, _config.HORBAR_SIZE do
local item = _hotbarItems[i]
local slot = ClientInventory.CreateSlot("Hotbar", i, item)
if slot then
slot.Parent = Hotbar
slot.Visible = Inventory.Visible or (item and item.name ~= "Item Name")
local ivp, qty, slbl, btn = slot:FindFirstChild("ItemViewport"), slot:FindFirstChild("Quanity"), slot:FindFirstChild("Slot"), slot:FindFirstChild("Button")
if ivp then ivp.Visible = false end
if qty then qty.Visible = true end
if slbl then slbl.Visible = true end
if btn then btn.Text = (item and item.name ~= "Item Name") and item.name or "" end
SetupSlotEvents(slot, i, true)
end
end
-- Update selection indicator
for i = 1, _config.HORBAR_SIZE do
local s = Hotbar:FindFirstChild(i == 10 and "0" or tostring(i))
if s and s:FindFirstChild("UIStroke") then s.UIStroke.Thickness = (i == _selectedSlot) and 3 or 0 end
end
end
if type == "inventory" or type == "both" then
-- Clear existing inventory slots
for _, child in pairs(List:GetChildren()) do
if child:IsA("ImageLabel") then child:Destroy() end
end
-- Create new inventory slots
for i = 1, _config.INVENTORY_ROWS * _config.INVENTORY_COLS do
if _inventoryItems[i] then
local slot = ClientInventory.CreateSlot("Inventory", i, _inventoryItems[i])
if slot then
slot.Parent = List
slot.Name = "InventorySlot" .. i -- Ensure consistent naming
local qty, slbl, btn = slot:FindFirstChild("Quanity"), slot:FindFirstChild("Slot"), slot:FindFirstChild("Button")
if qty then qty.Visible = false end
if slbl then slbl.Visible = false end
if btn then btn.Text = "" end
SetupSlotEvents(slot, i, false)
end
end
end
end
end
function ClientInventory.MoveItem(fromType, fromIdx, toType, toIdx)
-- Debug output
print("Moving item from " .. fromType .. "[" .. tostring(fromIdx) .. "] to " .. toType .. "[" .. tostring(toIdx) .. "]")
-- Validate the inventory is visible if dealing with hotbar
if not Inventory.Visible and (fromType == "hotbar" or toType == "hotbar") then
print("Inventory must be visible to interact with hotbar items")
return
end
-- Get source and target item arrays
local srcItems = fromType == "hotbar" and _hotbarItems or _inventoryItems
local tgtItems = toType == "hotbar" and _hotbarItems or _inventoryItems
-- Get the source item
local srcItem = srcItems[fromIdx]
if not srcItem then
print("Source item not found at " .. fromType .. "[" .. tostring(fromIdx) .. "]")
return
end
-- Get target item (if any)
local tgtItem = tgtItems[toIdx]
-- Debug print items
print("Source item: " .. (srcItem.name or "nil"))
print("Target item: " .. (tgtItem and tgtItem.name or "nil"))
-- Handle different movement cases
if fromType ~= toType then
-- Moving between inventory and hotbar
if fromType == "inventory" and toType == "hotbar" then
-- Moving from inventory to hotbar
print("Moving from inventory to hotbar")
-- Check if we're moving to a valid hotbar slot
if toIdx < 1 or toIdx > _config.HORBAR_SIZE then
print("Invalid hotbar slot index: " .. tostring(toIdx))
return
end
-- Move the item and handle the swap
if tgtItem and tgtItem.name ~= "Item Name" then
-- Swap items if target has a real item
local tempSrcItem = srcItem
tgtItems[toIdx] = tempSrcItem
srcItems[fromIdx] = tgtItem
else
-- Move to empty hotbar slot or slot with placeholder
tgtItems[toIdx] = srcItem
srcItems[fromIdx] = nil -- Remove completely, don't leave placeholder
CompactInventory()
end
elseif fromType == "hotbar" and toType == "inventory" then
-- Moving from hotbar to inventory
print("Moving from hotbar to inventory")
-- Make sure we have a valid target index
local tIdx = (toIdx > #_inventoryItems + 1) and FindEmptyInvSlot() or toIdx
if not tIdx then
print("No empty inventory slots available")
return
end
-- Place the item in inventory and leave an empty slot in hotbar
if tgtItem then
-- If target has an item, swap
local tempSrcItem = srcItem
srcItems[fromIdx] = tgtItem
tgtItems[tIdx] = tempSrcItem
else
-- If target is empty, just move
tgtItems[tIdx] = srcItem
srcItems[fromIdx] = {name = "Item Name", rarity = "Common"} -- Empty placeholder in hotbar
end
end
else
-- Moving within the same area (hotbar or inventory)
if fromType == "hotbar" then
-- Hotbar to hotbar swapping
tgtItems[toIdx], srcItems[fromIdx] = srcItem, tgtItem or {name = "Item Name", rarity = "Common"}
else
-- Inventory to inventory swapping
-- Store both items in temporary variables first
local tempSrcItem = srcItem
local tempTgtItem = tgtItem
-- Then perform the swap
if tempTgtItem then
-- If target has an item, perform proper swap
srcItems[fromIdx] = tempTgtItem
tgtItems[toIdx] = tempSrcItem
else
-- If target is empty, move source to target and clean up
tgtItems[toIdx] = tempSrcItem
srcItems[fromIdx] = nil -- Remove completely, don't leave placeholder
CompactInventory()
end
end
end
-- Update selection indicators and item frame
if _currentItem and _currentselectedSlot then
if fromType == "inventory" and fromIdx == _currentselectedSlot then
if toType == "inventory" then
_currentselectedSlot, _currentItem = toIdx, _inventoryItems[toIdx]
ClientInventoryDisplay.DisplayItemInFrame(_currentItem)
local prevSlot = List:FindFirstChild("InventorySlot"..fromIdx)
local newSlot = List:FindFirstChild("InventorySlot"..toIdx)
if prevSlot and prevSlot:FindFirstChild("UIStroke") then
TweenService:Create(prevSlot.UIStroke, TweenInfo.new(0.2), {Thickness = 0}):Play()
end
if newSlot and newSlot:FindFirstChild("UIStroke") then
TweenService:Create(newSlot.UIStroke, TweenInfo.new(0.2), {Thickness = 3}):Play()
end
else
ItemFrame.Visible, _currentItem, _currentselectedSlot, _currentVanityItem = false, nil, nil, nil
end
elseif toType == "inventory" and toIdx == _currentselectedSlot then
_currentItem = _inventoryItems[_currentselectedSlot]
ClientInventoryDisplay.DisplayItemInFrame(_currentItem)
end
end
-- Update UI
ClientInventory.UpdateSlots("hotbar")
ClientInventory.UpdateSlots("inventory")
-- Debugging
print("Move completed successfully!")
end
function ClientInventory.ToggleInventory(visible)
Inventory.Visible = visible
if not visible and ItemFrame then
ItemFrame.Visible = false
_currentItem = nil
_currentVanityItem = nil
_currentselectedSlot = nil
end
ClientInventory.UpdateSlots("hotbar")
end
function ClientInventory.ToggleVanityMode(enabled)
_isVanityMode = enabled
-- Reset selection when switching modes
if _currentselectedSlot then
local currentSlot = List:FindFirstChild("InventorySlot".._currentselectedSlot)
if currentSlot and currentSlot:FindFirstChild("UIStroke") then
TweenService:Create(currentSlot.UIStroke, TweenInfo.new(0.2), {Thickness = 0}):Play()
end
end
-- Clear current selections
_currentselectedSlot = nil
_currentItem = nil
_currentVanityItem = nil
-- Hide item frame
if ItemFrame then
ItemFrame.Visible = false
end
-- Update UI to show the mode change
ClientInventoryEffects.CreateNotification(2, _isVanityMode and "Vanity Mode" or "Normal Mode", _isVanityMode and "Switched to Vanity Mode" or "Switched to Normal Mode")
-- Refresh inventory display
ClientInventory.UpdateSlots("inventory")
end
-- CLIENT MODULE - Fixed ManageItem function
function ClientInventory.ManageItem(action, itemData)
-- Enhanced debug diagnostics
print("ManageItem called with action:", action)
print("itemData type:", type(itemData))
-- Validate itemData
if not itemData then
warn("ManageItem called with nil itemData")
return false
end
if type(itemData) ~= "table" then
-- If it's a string, convert it to a simple table
if type(itemData) == "string" then
itemData = {
name = itemData,
id = itemData .. "_id_" .. tostring(os.time()),
rarity = "Common",
description = "No description",
quantity = 1
}
else
warn("ManageItem called with invalid itemData type:", type(itemData))
return false
end
end
-- Print all keys and values (for debugging)
print("ItemData contents:")
for k, v in pairs(itemData) do
print(" - " .. tostring(k) .. " = " .. tostring(v))
end
-- Check for required properties, trying both lowercase and uppercase versions
local itemName = itemData.name or itemData.Name
if not itemName or type(itemName) ~= "string" then
warn("ManageItem called with invalid or missing name property:", tostring(itemName))
return false
end
-- Get other properties with fallbacks and validation
local itemRarity = itemData.rarity or itemData.Rarity or "Common"
local itemId = itemData.id or itemData.Id or (itemName .. "_id_" .. tostring(os.time()))
local itemDescription = itemData.description or itemData.Description or "No description available"
local itemQuantity = tonumber(itemData.quantity or itemData.Quantity or 1)
-- Ensure quantity is valid
if not itemQuantity or itemQuantity < 1 then
itemQuantity = 1
end
if action == "setupinventory" then
-- Check if item already exists by ID first, then by name
local existingIndex = nil
for idx, item in pairs(_inventoryItems) do
if item and (item.id == itemId or (not item.id and item.name == itemName)) then
existingIndex = idx
break
end
end
if existingIndex then
-- Update existing item quantity
local currentQty = _inventoryItems[existingIndex].quantity or 1
_inventoryItems[existingIndex].quantity = currentQty + itemQuantity
print("Updated existing item quantity:", itemName, "new quantity:", _inventoryItems[existingIndex].quantity)
else
-- Add as new item
local idx = FindEmptyInvSlot()
if not idx then
ClientInventoryEffects.CreateNotification(3, "Inventory Full", "Cannot add more items to your inventory!")
return false
end
-- Create clean item object
_inventoryItems[idx] = {
name = itemName,
id = itemId,
rarity = itemRarity,
description = itemDescription,
quantity = itemQuantity
}
print("Added new item to inventory:", itemName, "at slot:", idx)
end
ClientInventory.UpdateSlots("inventory")
return true
elseif action == "jutsu" then
local existingIndex = nil
for idx, item in pairs(_inventoryItems) do
if item and (item.id == itemId or (not item.id and item.name == itemName)) then
existingIndex = idx
break
end
end
if existingIndex then
-- Update existing item quantity
local currentQty = _inventoryItems[existingIndex].quantity or 1
_inventoryItems[existingIndex].quantity = currentQty + itemQuantity
print("Updated existing item quantity:", itemName, "new quantity:", _inventoryItems[existingIndex].quantity)
else
-- Add as new item
local idx = FindEmptyInvSlot()
if not idx then
ClientInventoryEffects.CreateNotification(3, "Inventory Full", "Cannot add more items to your inventory!")
return false
end
-- Create clean item object
_inventoryItems[idx] = {
name = itemName,
id = itemId,
rarity = itemRarity,
description = itemDescription,
quantity = itemQuantity,
toolExists = itemData.toolExists -- Preserve tool existence flag
}
print("Added new item to inventory:", itemName, "at slot:", idx)
end
return true
elseif action == "add" or action == "purchase" then
-- Check for accessory previews if needed
if not ReplicatedStorage:FindFirstChild("AccessoryPreviews") or
not ReplicatedStorage.AccessoryPreviews:FindFirstChild(itemName) then
-- Only request preview if the remote exists
if requestPreviewRemote then
requestPreviewRemote:InvokeServer(itemName)
end
end
-- Check if we already have this item (by id first, then by name)
local existingIndex = nil
for idx, item in pairs(_inventoryItems) do
if item and (item.id == itemId or (not item.id and item.name == itemName)) then
existingIndex = idx
break
end
end
if existingIndex then
-- Update existing item
local currentQty = _inventoryItems[existingIndex].quantity or 1
_inventoryItems[existingIndex].quantity = currentQty + itemQuantity
else
-- Add as new item
local idx = FindEmptyInvSlot()
if not idx then
ClientInventoryEffects.CreateNotification(3, "Inventory Full", "Cannot add more items to your inventory.")
return false
end
_inventoryItems[idx] = {
name = itemName,
id = itemId,
rarity = itemRarity,
description = itemDescription,
quantity = itemQuantity
}
end
ClientInventory.UpdateSlots("inventory")
-- Show notification
local title = action == "add" and "Item Received" or "Purchase Complete!"
local msg = "[" .. (action == "add" and "Received " or "Successfully purchased ") .. itemName .. "!]"
ClientInventoryEffects.CreateNotification(3, title, msg)
return true
elseif action == "remove" then
local idx, name
-- Handle different input types for removal
if type(itemData) == "string" then
-- String could be ID or name
for i, item in pairs(_inventoryItems) do
if item and (item.id == itemData or item.name == itemData) then
idx, name = i, item.name
break
end
end
elseif type(itemData) == "table" then
local searchId = itemId
local searchName = itemName
for i, item in pairs(_inventoryItems) do
if item and ((searchId and item.id == searchId) or (searchName and item.name == searchName)) then
idx, name = i, item.name
break
end
end
end
if idx and name then
-- Close item frame if this item is currently selected
if ItemFrame and ItemFrame.Visible and _currentItem and _currentItem.name == name then
ItemFrame.Visible = false
_currentItem, _currentselectedSlot = nil, nil
end
-- Handle quantity
local currentQty = _inventoryItems[idx].quantity or 1
if currentQty > 1 then
_inventoryItems[idx].quantity = currentQty - 1
else
_inventoryItems[idx] = nil
CompactInventory()
end
ClientInventory.UpdateSlots("inventory")
ClientInventoryEffects.CreateNotification(3, "Item Removed", "[Removed " .. name .. "!]")
return true
else
warn("Could not find item to remove:", tostring(itemData))
return false
end
end
warn("Unknown action in ManageItem:", action)
return false
end
-- Add this helper function to ClientInventory module
function ClientInventory.ClearInventory()
ClientInventory.inventoryItems = {}
ClientInventory.slotItems = {}
-- Update UI
ClientInventory.UpdateSlots("inventory")
ClientInventory.UpdateSlots("hotbar")
end
-- Function to add and initialize test items
function ClientInventory.AddTestItems()
for i = 1, 10 do _hotbarItems[i] = {name = "Item Name", rarity = "Common"} end
end
function ClientInventory.GetSelectedItem()
if _isVanityMode then
return _currentVanityItem
else
return _currentItem
end
end
-- Event handlers
UserInputService.InputChanged:Connect(function(input)
if _isDragging and _draggedItem and input.UserInputType == Enum.UserInputType.MouseMovement then
local mPos = UserInputService:GetMouseLocation()
_draggedItem.Position = UDim2.new(0, mPos.X-(_config.SLOT_SIZE/2)-_dragOffsetX, 0, mPos.Y-(_config.SLOT_SIZE/2)-_dragOffsetY)
end
end)
UserInputService.InputEnded:Connect(function(input)
if _isDragging and input.UserInputType == Enum.UserInputType.MouseButton1 then HandleDragEnd(UserInputService:GetMouseLocation()) end
end)
RunService.RenderStepped:Connect(function()
if _isDragging and _draggedItem then _draggedItem.Rotation = math.sin(tick() * 5) * 5 end
end)
-- Handle preview requests from server
requestPreviewRemotes.OnClientEvent:Connect(function(itemName)
-- First check if preview already exists
if not ReplicatedStorage:FindFirstChild("AccessoryPreviews") or
not ReplicatedStorage.AccessoryPreviews:FindFirstChild(itemName) then
-- Request preview from server
local success = requestPreviewRemote:InvokeServer(itemName)
if not success then
warn("Failed to get preview for:", itemName)
end
end
if List then
for _, slot in pairs(List:GetChildren()) do
if slot:IsA("ImageLabel") or slot:IsA("Frame") then
local viewport = slot:FindFirstChild("ItemViewport")
if viewport and viewport:GetAttribute("PendingModelLoad") == itemName then
ClientInventoryViewport.LoadModelIntoViewPort(viewport, itemName)
viewport:SetAttribute("PendingModelLoad", nil)
end
end
end
end
end)
-- Handle inventory data updates from server
updateInventoryRemote.OnClientEvent:Connect(function(slotIndex, itemData)
_inventoryItems[slotIndex] = itemData
end)
-- Handle refresh requests from server
refreshInventoryRemote.OnClientEvent:Connect(function()
ClientInventory.UpdateSlots("inventory")
end)
-- CLIENT SIDE - Fixed event handler
remotes.InventoryRemotes.InventoryHandler.OnClientEvent:Connect(function(action, itemData)
print("=== INVENTORY EVENT RECEIVED ===")
print("Action:", action)
print("ItemData type:", type(itemData))
-- Add more detailed logging for debugging
if type(itemData) == "table" then
print("ItemData name:", itemData.name or itemData.Name or "NO_NAME")
end
-- Validate that we received proper data
if not itemData then
warn("Received nil itemData for action:", action)
return
end
if action == "SyncInventory" then
if type(itemData) == "table" then
print("Processing SyncInventory with", #itemData, "items")
for i, item in ipairs(itemData) do
-- Enhanced validation
if type(item) ~= "table" then
warn("Invalid item in inventory sync at index", i, ":", tostring(item))
continue
end
-- Debug the item
local itemName = item.name or item.Name
print("Processing inventory item #" .. i .. ":", itemName or "unknown")
-- Create a clean item structure with all required properties
local cleanItem = {
name = itemName,
rarity = item.rarity or item.Rarity or
(TradeablesData[itemName] and TradeablesData[itemName].Rarity) or "Common",
id = item.id or item.Id or (itemName .. "_id_" .. tostring(os.time()) .. "_" .. i),
quantity = item.quantity or item.Quantity or 1,
description = item.description or item.Description or "No description",
toolExists = item.toolExists
}
-- Only process items with valid names
if cleanItem.name and type(cleanItem.name) == "string" then
local success = ClientInventory.ManageItem("setupinventory", cleanItem)
print("Added inventory item:", cleanItem.name, "Success:", success)
else
warn("Item missing valid name property at index", i, ":", tostring(cleanItem.name))
end
end
ClientInventory.UpdateSlots("hotbar")
ClientInventory.UpdateSlots("inventory")
print("Completed SyncInventory processing")
else
warn("Invalid data format for SyncInventory:", type(itemData))
end
elseif action == "AddedItem" then
print("Adding item:", itemData.name or itemData.Name or "unknown")
ClientInventory.ManageItem("add", itemData)
elseif action == "RemovedItem" then
print("Removing item:", itemData.name or itemData.Name or tostring(itemData))
ClientInventory.ManageItem("remove", itemData)
elseif action == "PurchaseItem" then
print("Purchasing item:", itemData.name or itemData.Name or "unknown")
ClientInventory.ManageItem("purchase", itemData)
else
warn("Unknown inventory action:", action)
end
print("=== END INVENTORY EVENT ===")
end)
ClientInventoryDisplay.SetupEquipUnequipHandlers({
GetCurrentItemCallback = function()
return _currentItem
end
})
return ClientInventory
So does anyone have an idea how to get this to work by any chance?