0% found this document useful (0 votes)
32 views8 pages

Inventory Server

Uploaded by

Inoob 8C
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
32 views8 pages

Inventory Server

Uploaded by

Inoob 8C
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 8

-- Services

local StarterPack = game:GetService("StarterPack")


local Players = game:GetService("Players")
local RS = game:GetService("ReplicatedStorage")
local SS = game:GetService("ServerStorage")
local HS = game:GetService("HttpService")
local DataStoreService = game:GetService("DataStoreService")

-- Modules
local Signal = require(RS.Modules.Signal)
local Janitor = require(RS.Modules.Janitor)
local NotificationsModule = require(RS.ClientModules.NotificationModule)

-- DataStore
local InventoryDataStore = DataStoreService:GetDataStore("InventoryDataStore2")

-- Module
local InventoryServer = {}
InventoryServer.AllInventories = {}
InventoryServer.MaxStacks = 50
InventoryServer.MaxStackData = {
Weapon = 1,
Armor = 1,
Consumable = 8,
Resource = 16
}

-- Finding Stack Data From Id


function InventoryServer.FindStackDataFromId(player, stackId)
for i, stackData in pairs(InventoryServer.AllInventories[player].Inventory)
do
if stackData.StackId == stackId then
return stackData
end
end
end

-- Dropping Item
function InventoryServer.DropItem(player, stackId)
local stackData = InventoryServer.FindStackDataFromId(player, stackId)
if not stackData then return end

if not stackData.IsDroppable then


NotificationsModule:CreateNotification(player, "Item isn't droppable!",
Color3.fromRGB(134, 0, 0), "error")
return
end

local char = player.Character; if not char then return end


local root = char:FindFirstChild("HumanoidRootPart"); if not root then return
end

local toolToDrop = stackData.Items[1]


local handle = toolToDrop:FindFirstChild("Handle")
InventoryServer.UnequipItems(player, toolToDrop)
InventoryServer.UnRegisterItem(player, toolToDrop)
toolToDrop.Parent = workspace.Drops

local dropDistance = 5
local dropPosition = root.CFrame.Position + root.CFrame.LookVector *
dropDistance
handle.CFrame = CFrame.new(dropPosition)
end

-- Equip Item
function InventoryServer.EquipItem(player, slotNum)
local inv = InventoryServer.AllInventories[player]
local stackData = nil
for slotKey, stackId in pairs(inv.Hotbar) do
if slotKey == "Slot" .. slotNum then
stackData = InventoryServer.FindStackDataFromId(player, stackId)
break
end
end

InventoryServer.UnequipItems(player)
if stackData then
local tool = stackData.Items[1]
if not player.Character then return end
tool.Parent = player.Character

Signal.FireClient(player, "Inventory:ItemsUpdated",
InventoryServer.GetInventoryJSON(player))
end
end

-- Unequipping All Items


function InventoryServer.UnequipItems(player)
local char = player.Character; if not char then return end
local hum = char:FindFirstChild("Humanoid"); if not hum then return end
hum:UnequipTools()

Signal.FireClient(player, "Inventory:ItemsUpdated",
InventoryServer.GetInventoryJSON(player))
end

-- Unequip all items


function InventoryServer.UnequipAllItems(player)
local playerInventory = InventoryServer.AllInventories[player]
if not playerInventory then return end

for slot, stackId in pairs(playerInventory.Hotbar) do


playerInventory.Hotbar[slot] = nil
end

Signal.FireClient(player, "Inventory:ItemsUpdated",
InventoryServer.GetInventoryJSON(player))
end

-- Equipping Item To Hotbar


function InventoryServer.EquipToHotbar(player, equipTo, stackId)
local inv = InventoryServer.AllInventories[player]

InventoryServer.UnequipFromHotbar(player, stackId)

local isValid = false


for i, stackData in pairs(inv.Inventory) do
if stackData.StackId == stackId and stackData.ItemType ~= "Armor" then
isValid = true
end
end
if not isValid then return end

inv.Hotbar["Slot" .. equipTo] = stackId

Signal.FireClient(player, "Inventory:ItemsUpdated",
InventoryServer.GetInventoryJSON(player))
end

-- Updating Item From Hotbar


function InventoryServer.UnequipFromHotbar(player, stackId)
local inv = InventoryServer.AllInventories[player]

local found = false


for slotKey, equippedId in pairs(inv.Hotbar) do
if equippedId == stackId then
inv.Hotbar[slotKey] = nil
found = true
end
end

if found then
Signal.FireClient(player, "Inventory:ItemsUpdated",
InventoryServer.GetInventoryJSON(player))
end
end

-- Adding Items
function InventoryServer.RegisterItem(player, tool)
if tool.ClassName ~= "Tool" then return end

local inv = InventoryServer.AllInventories[player]

local foundStack = nil


for i, stackData in pairs(inv.Inventory) do
if table.find(stackData.Items, tool) then
return
elseif stackData.Name == tool.Name and #stackData.Items <
InventoryServer.MaxStackData[stackData.ItemType] then
table.insert(stackData.Items, tool)
foundStack = stackData
break
end
end

if not foundStack then


if #inv.Inventory < InventoryServer.MaxStacks then
local stack = {
Name = tool.Name,
Description = tool.ToolTip,
Image = tool.TextureId,
ItemType = tool:GetAttribute("ItemType"),
Rarity = tool:GetAttribute("Rarity"),
ArmorType = (tool:GetAttribute("ItemType") == "Armor") and
tool:GetAttribute("ArmorType") or nil,
ItemTypeDescription = (tool:GetAttribute("ItemType") ==
"Weapon") and tool:GetAttribute("ItemTypeDescription") or nil,
IsDroppable = tool:GetAttribute("IsDroppable"),
Items = {tool},
StackId = inv.LastStackId
}
inv.LastStackId += 1
table.insert(inv.Inventory, stack)

for slotNum = 1, 9 do
if inv.Hotbar["Slot" .. slotNum] == nil then
InventoryServer.EquipToHotbar(player, slotNum,
stack.StackId)
break
end
end
else
error("The user has more than the max stacks of 50!")
end
end
Signal.FireClient(player, "Inventory:ItemsUpdated",
InventoryServer.GetInventoryJSON(player))
end

function InventoryServer.UnRegisterItem(player, tool)


InventoryServer.CharacterToolRemoved()
if tool.ClassName ~= "Tool" then return end
if tool.Parent == player.Backpack or (player.Character and tool.Parent ==
player.Character) then return end

local inv = InventoryServer.AllInventories[player]

for i, stackData in pairs(inv.Inventory) do


local found = table.find(stackData.Items, tool)
if found then
table.remove(stackData.Items, found)

if #stackData.Items == 0 then
table.remove(inv.Inventory, table.find(inv.Inventory,
stackData))
InventoryServer.UnequipFromHotbar(player,
stackData.StackId)
end
end
end
Signal.FireClient(player, "Inventory:ItemsUpdated",
InventoryServer.GetInventoryJSON(player))
end

-- Save Inventory Data with Debugging and Data Printing


function InventoryServer.SaveInventoryData(player)
local inventoryData = InventoryServer.AllInventories[player]
if not inventoryData then
warn("SaveInventoryData: No inventory data found for player " ..
player.Name)
return
end

-- Collecting data to save


local saveData = {
Inventory = {},
Hotbar = inventoryData.Hotbar,
LastStackId = inventoryData.LastStackId
}

for _, stack in pairs(inventoryData.Inventory) do


local stackData = {
Name = stack.Name,
Description = stack.Description,
Image = stack.Image,
ItemType = stack.ItemType,
Rarity = stack.Rarity,
ArmorType = stack.ArmorType,
ItemTypeDescription = stack.ItemTypeDescription,
IsDroppable = stack.IsDroppable,
Items = {},
StackId = stack.StackId
}
for _, item in ipairs(stack.Items) do
table.insert(stackData.Items, item.Name)
end
table.insert(saveData.Inventory, stackData)
end

-- Attempting to save data


local success, errorMessage = pcall(function()
InventoryDataStore:SetAsync("Inventory_" .. player.UserId, saveData)
end)
if success then
print(saveData)
else
warn("SaveInventoryData: Failed to save inventory data for player " ..
player.Name .. " - Error: " .. errorMessage)
end
end

function InventoryServer.StartAutoSave()
while true do
-- Save inventory data for each player
for _, player in pairs(game.Players:GetPlayers()) do
InventoryServer.SaveInventoryData(player)
print("Auto Save: Saved inventory data for player " ..
player.Name)
end
-- Delay for 1 to 3 minutes (60 to 180 seconds)
local saveInterval = math.random(60, 180)
task.wait(saveInterval)
end
end

-- Load Inventory Data with Debugging and Data Printing


function InventoryServer.LoadInventoryData(player)
-- Attempting to load data
local success, savedData = pcall(function()
return InventoryDataStore:GetAsync("Inventory_" .. player.UserId)
end)
if not success then
warn("LoadInventoryData: Failed to load inventory data for player " ..
player.Name)
return
end

if not savedData then


print("LoadInventoryData: No saved data found for player " ..
player.Name)
InventoryServer.AllInventories[player] = {
Inventory = {},
Hotbar = {},
Armor = {
Head = nil,
Chest = nil,
Feet = nil
},
LastStackId = 0
}
return
end

-- Preparing inventory data


local inventoryData = {
Inventory = {},
Hotbar = savedData.Hotbar or {},
Armor = savedData.Armor or {
Head = nil,
Chest = nil,
Feet = nil
},
LastStackId = savedData.LastStackId or 0
}

-- Loading inventory items


for _, stackData in pairs(savedData.Inventory) do
local stack = {
Name = stackData.Name,
Description = stackData.Description,
Image = stackData.Image,
ItemType = stackData.ItemType,
Rarity = stackData.Rarity,
ArmorType = stackData.ArmorType,
ItemTypeDescription = stackData.ItemTypeDescription,
IsDroppable = stackData.IsDroppable,
Items = {},
StackId = stackData.StackId
}
task.wait(0.1)
for _, toolName in ipairs(stackData.Items) do
local tool = SS.Assets.Tools:FindFirstChild(toolName)
if tool then
local clonedTool = tool:Clone()
table.insert(stack.Items, clonedTool)
clonedTool.Parent = player.Backpack -- Place tool directly
into the player's backpack
else
warn("LoadInventoryData: Tool '" .. toolName .. "' not
found in ServerStorage for player " .. player.Name)
end
end
table.insert(inventoryData.Inventory, stack)
end

InventoryServer.AllInventories[player] = inventoryData
end

-- Player Added
function InventoryServer.PlayerAdded(player)
InventoryServer.LoadInventoryData(player)

for i, tool in pairs(player.Backpack:GetChildren()) do


InventoryServer.RegisterItem(player, tool)
end

player.Backpack.ChildAdded:Connect(function(child)
InventoryServer.RegisterItem(player, child)
end)
player.Backpack.ChildRemoved:Connect(function(child)
InventoryServer.UnRegisterItem(player, child)
end)

function InventoryServer.CharacterToolRemoved()
local enabled = false
for _, tool in pairs(player.Character:GetChildren()) do
if tool:IsA("Tool") and enabled == true then
tool:GetPropertyChangedSignal("Parent"):Connect(function()
if tool.Parent ~= player.Character or player.Backpack
then
InventoryServer.UnRegisterItem(player, tool)
end
end)
end
end
end

local function charAdded(char)


InventoryServer.CharacterToolRemoved()
local hum = char:WaitForChild("Humanoid")

player.Backpack.ChildAdded:Connect(function(child)
InventoryServer.RegisterItem(player, child)
end)
player.Backpack.ChildRemoved:Connect(function(child)
InventoryServer.UnRegisterItem(player, child)
end)

char.ChildAdded:Connect(function(child)
InventoryServer.RegisterItem(player, child)
end)
char.ChildRemoved:Connect(function(child)
InventoryServer.UnRegisterItem(player, child)
end)
end

if player.Character then
task.spawn(charAdded, player.Character)
end

player.CharacterAdded:Connect(charAdded)
end

-- Player Removing
function InventoryServer.PlayerRemoving(player)
InventoryServer.SaveInventoryData(player)
InventoryServer.AllInventories[player] = nil
end

-- Getting Inventory Data


function InventoryServer.GetInventoryJSON(player)
while not InventoryServer.AllInventories[player] do task.wait() end
local inv = InventoryServer.AllInventories[player]

local adjustedInv = {
Inventory = {},
Hotbar = inv.Hotbar,
Armor = inv.Armor,
LastStackId = inv.LastStackId
}
for i, stackData in pairs(inv.Inventory) do
table.insert(adjustedInv.Inventory, {
Name = stackData.Name,
Description = stackData.Description,
Image = stackData.Image,
ItemType = stackData.ItemType,
ArmorType = stackData.ArmorType,
ItemTypeDescription = stackData.ItemTypeDescription,
Rarity = stackData.Rarity,
IsDroppable = stackData.IsDroppable,
Items = stackData.Items,
Count = #stackData.Items,
StackId = stackData.StackId
})
end

return adjustedInv
end

-- Initializing
function InventoryServer.Start()
for i, player in pairs(Players:GetPlayers()) do
task.spawn(InventoryServer.PlayerAdded, player)
end
Players.PlayerAdded:Connect(InventoryServer.PlayerAdded)
Players.PlayerRemoving:Connect(InventoryServer.PlayerRemoving)
task.spawn(InventoryServer.StartAutoSave)
Signal.ListenRemote("Inventory:GetInventoryJSON",
InventoryServer.GetInventoryJSON)
Signal.ListenRemote("Inventory:DropItem", InventoryServer.DropItem)
Signal.ListenRemote("InventoryEquipToHotbar", InventoryServer.EquipToHotbar)
Signal.ListenRemote("InventoryUnequipFromHotbar",
InventoryServer.UnequipFromHotbar)
Signal.ListenRemote("Inventory:EquipItem", InventoryServer.EquipItem)
Signal.ListenRemote("Inventory:UnequipItems", InventoryServer.UnequipItems)
Signal.ListenRemote("Inventory:UnequipAllItems",
InventoryServer.UnequipAllItems)
end

return InventoryServer

You might also like