local H=5 local u=game:GetService("\082\101\112\108\105\099\097\116\101\100\083\116\111\114\097\103\101")local z=game:GetService("\073\110\115\101\114\116\083\101\114\118\105\099\101")local A=require((u:WaitForChild("\080\114\111\106\101\099\116")):WaitForChild("\082\101\112\108\105\099\097\116\101\100\083\116\111\114\097\103\101"))local Z=(require((u:WaitForChild("\080\114\111\106\101\099\116")):WaitForChild("\083\101\114\118\101\114\083\099\114\105\112\116\083\101\114\118\105\099\101"))):GetContext(script)local W=A:GetObjectReference("\071\097\109\101\068\097\116\097\046\073\116\101\109\046\073\116\101\109\115")local s=A:GetResource("\071\097\109\101\068\097\116\097\046\073\116\101\109\046\073\116\101\109\115")local V=A:GetResource("\071\097\109\101\068\097\116\097\046\081\117\101\115\116\046\081\117\101\115\116\115")local U=A:GetResource("\083\116\097\116\101\046\073\110\118\101\110\116\111\114\121")local d=A:GetResource("\071\097\109\101\082\101\112\108\105\099\097\116\105\111\110")local f=(A:GetResource("\069\120\116\101\114\110\097\108\085\116\105\108\046\078\101\120\117\115\073\110\115\116\097\110\099\101\046\078\101\120\117\115\073\110\115\116\097\110\099\101")):Extend()f:SetClassName("\073\110\118\101\110\116\111\114\121\083\101\114\118\105\099\101")f.PlayerInventories={}Z:SetContextResource(f)local v=Z:GetResource("\083\101\114\118\105\099\101\046\067\111\109\112\108\105\097\110\099\101\083\101\114\118\105\099\101")local B=Z:GetResource("\083\101\114\118\105\099\101\046\080\108\097\121\101\114\068\097\116\097\083\101\114\118\105\099\101")local R=Z:GetResource("\083\101\114\118\105\099\101\046\080\101\116\083\101\114\118\105\099\101")local g=Z:GetResource("\083\101\114\118\105\099\101\046\081\117\101\115\116\083\101\114\118\105\099\101")local T=Instance.new("\070\111\108\100\101\114")T.Name="\073\110\118\101\110\116\111\114\121\082\101\112\108\105\099\097\116\105\111\110"T.Parent=d local F=Instance.new("\082\101\109\111\116\101\069\118\101\110\116")F.Name="\083\119\097\112\083\108\111\116\115"F.Parent=T F.OnServerEvent:Connect(function(H,u,z)f:SwapSlots(H,u,z)end)local M=Instance.new("\082\101\109\111\116\101\069\118\101\110\116")M.Name="\083\101\116\080\101\116"M.Parent=T M.OnServerEvent:Connect(function(H,u)local z=B:GetPlayerData(H)if u=="\068\111\103"or(z:GetValue("\080\101\116\115\079\119\110\101\100"))[u]then z:SetValue("\067\117\114\114\101\110\116\080\101\116",u)R:SpawnPet(H)end end)local x=Instance.new("\082\101\109\111\116\101\069\118\101\110\116")x.Name="\085\110\108\111\099\107\067\104\101\115\116"x.Parent=T x.OnServerEvent:Connect(function(H,u)f:UnlockChest(H,u)end)local e=Instance.new("\082\101\109\111\116\101\069\118\101\110\116")e.Name="\068\101\108\101\116\101\073\116\101\109"e.Parent=T e.OnServerEvent:Connect(function(H,u)f:DeleteItem(H,u)end)function f.LoadPlayer(u,H)local z=U.GetInventory(H)u.PlayerInventories[H]=z if not v:CanUseRandomPaidItems(H)then local A={}for H,u in z.Inventory do if u.Name=="\084\114\101\097\115\117\114\101\067\104\101\115\116"then A[H]=u.Zone end end for A,Z in A do z:RemoveSlot(A)u:AwardRandomItem(H,Z)end end end function f.ClearPlayer(u,H)u.PlayerInventories[H]=nil end function f.LoadCharacterAssets(H)local u=0 local A=Instance.new("\066\105\110\100\097\098\108\101\069\118\101\110\116")for H,Z in pairs(s)do local s=Z.RobloxId if s then u=u+1;(coroutine.wrap(function()local Z,V=pcall(function()return z:LoadAsset(s)end)if Z then V.Name=H V.Parent=W else warn("\070\097\105\108\101\100 \116\111 \108\111\097\100 "..(tostring(s)..(" \098\101\099\097\117\115\101 "..tostring(V))))end u=u-1 A:Fire()end))()end end while u>0 do A.Event:Wait()end end function f.GetInventory(u,H)return u.PlayerInventories[H]end function f.GetItem(z,H,u)local A=z.PlayerInventories[H]return A and A:GetItem(u)end function f.GetInventoryChangedEvent(u,H)return u.PlayerInventories[H].InventoryChanged end function f.AddItem(z,H,u)if type(u)=="\115\116\114\105\110\103"then u={Name=u}end local A=z.PlayerInventories[H]local Z=A:GetNextOpenSlot()if not Z then return false end A:AddItem(u)return true end function f.AwardRandomItem(A,u,z)local Z=A:GetInventory(u)if not Z:GetNextOpenSlot()then return false end local W={}for A,s in pairs(s)do if s.Awardable~=false and(z==nil or z==s.Zone)then local z=1 local U=1 local d=s.Quest if d then if g:QuestConditonValid(u,d,"\073\110\118\101\110\116\111\114\121")then local u=V[d]if u and(u.RequiredItems and(u.RequiredItems[1]and u.RequiredItems[1].Name==A))then z=u.RequiredItems[1].Amount or 0 U=H end else z=0 end end if z>#Z:GetItemSlots(A)then for H=1,U,1 do table.insert(W,A)end end end end if z~=nil and#W==0 then return A:AwardRandomItem(u)end if#W>0 then local H=W[math.random(1,#W)]A:AddItem(u,H)return true,H else return false end end function f.SwapSlots(A,H,u,z)local Z=A.PlayerInventories[H]if Z:CanSwap(u,z)then Z:SwapSlots(u,z)end end function f.UnlockChest(z,H,u)local A=z.PlayerInventories[H]local Z=A:GetItem(u)if not Z or Z.Name~="\081\117\101\115\116 \067\104\101\115\116"and Z.Name~="\084\114\101\097\115\117\114\101\067\104\101\115\116"then return end if Z.Name=="\084\114\101\097\115\117\114\101\067\104\101\115\116"then local H=A:GetItemSlots("\084\114\101\097\115\117\114\101\075\101\121")if#H==0 then return end A:RemoveSlot(H[1])end A:RemoveSlot(u)z:AwardRandomItem(H,Z.Zone)end function f.RemoveItemsByName(z,H,u)local A=z.PlayerInventories[H]A:RemoveSlots(A:GetItemSlots(u))end function f.DeleteItem(z,H,u)local A=z.PlayerInventories[H]A:RemoveSlot(u)end return f
--[[
TheNexusAvenger

Controls the inventory of the player.
Class is static (should not be created).
--]]

local QUEST_ITEM_MULTIPLIER = 5




local ReplicatedStorage = game:GetService("ReplicatedStorage")
local InsertService = game:GetService("InsertService")

local ReplicatedStorageProject = require(ReplicatedStorage:WaitForChild("Project"):WaitForChild("ReplicatedStorage"))
local ServerScriptServiceProject = require(ReplicatedStorage:WaitForChild("Project"):WaitForChild("ServerScriptService")):GetContext(script)

local ItemDataModule = ReplicatedStorageProject:GetObjectReference("GameData.Item.Items")
local ItemData = ReplicatedStorageProject:GetResource("GameData.Item.Items")
local Quests = ReplicatedStorageProject:GetResource("GameData.Quest.Quests")
local Inventory = ReplicatedStorageProject:GetResource("State.Inventory")
local GameReplication = ReplicatedStorageProject:GetResource("GameReplication")

local InventoryService = ReplicatedStorageProject:GetResource("ExternalUtil.NexusInstance.NexusInstance"):Extend()
InventoryService:SetClassName("InventoryService")
InventoryService.PlayerInventories = {}
ServerScriptServiceProject:SetContextResource(InventoryService)

local ComplianceService = ServerScriptServiceProject:GetResource("Service.ComplianceService")
local PlayerDataService = ServerScriptServiceProject:GetResource("Service.PlayerDataService")
local PetService = ServerScriptServiceProject:GetResource("Service.PetService")
local QuestService = ServerScriptServiceProject:GetResource("Service.QuestService")



--Set up the replication.
local InventoryReplication = Instance.new("Folder")
InventoryReplication.Name = "InventoryReplication"
InventoryReplication.Parent = GameReplication

local SwapSlots = Instance.new("RemoteEvent")
SwapSlots.Name = "SwapSlots"
SwapSlots.Parent = InventoryReplication
SwapSlots.OnServerEvent:Connect(function(Player,Slot1,Slot2)
    InventoryService:SwapSlots(Player,Slot1,Slot2)
end)

local SetPet = Instance.new("RemoteEvent")
SetPet.Name = "SetPet"
SetPet.Parent = InventoryReplication
SetPet.OnServerEvent:Connect(function(Player,PetName)
    local PlayerData = PlayerDataService:GetPlayerData(Player)
    if PetName == "Dog" or PlayerData:GetValue("PetsOwned")[PetName] then
        PlayerData:SetValue("CurrentPet",PetName)
        PetService:SpawnPet(Player)
    end
end)

local UnlockChest = Instance.new("RemoteEvent")
UnlockChest.Name = "UnlockChest"
UnlockChest.Parent = InventoryReplication
UnlockChest.OnServerEvent:Connect(function(Player,Slot)
    InventoryService:UnlockChest(Player,Slot)
end)

local DeleteItem = Instance.new("RemoteEvent")
DeleteItem.Name = "DeleteItem"
DeleteItem.Parent = InventoryReplication
DeleteItem.OnServerEvent:Connect(function(Player,Slot)
    InventoryService:DeleteItem(Player,Slot)
end)



--[[
Initializes the inventory for a player.
--]]
function InventoryService:LoadPlayer(Player)
    local PlayerInventory = Inventory.GetInventory(Player)
    self.PlayerInventories[Player] = PlayerInventory

    --Unlock all locked chests if the region does not allow for random items.
    if not ComplianceService:CanUseRandomPaidItems(Player) then
        local SlotsToUnlock = {}
        for Slot, Item in PlayerInventory.Inventory do
            if Item.Name == "TreasureChest" then
                SlotsToUnlock[Slot] = Item.Zone
            end
        end
        for Slot, Zone in SlotsToUnlock do
            PlayerInventory:RemoveSlot(Slot)
            self:AwardRandomItem(Player, Zone)
        end
    end
end

--[[
Clears a player.
--]]
function InventoryService:ClearPlayer(Player)
    self.PlayerInventories[Player] = nil
end

--[[
Inserts all of the character items. Yields for them all
to be inserted or fail. This is required for the local
inventory display.
--]]
function InventoryService:LoadCharacterAssets()
    --Start loading the assets.
    local AssetsRemaining = 0
    local AssetLoaded = Instance.new("BindableEvent")
    for Name,AssetData in pairs(ItemData) do
        local AssetId = AssetData.RobloxId
        if AssetId then
            AssetsRemaining = AssetsRemaining + 1
            coroutine.wrap(function()
                local Worked,Model = pcall(function()
                    return InsertService:LoadAsset(AssetId)
                end)

                --Set up the asset.
                if Worked then
                    Model.Name = Name
                    Model.Parent = ItemDataModule
                else
                    warn("Failed to load "..tostring(AssetId).." because "..tostring(Model))
                end

                --Register the model is loaded.
                AssetsRemaining = AssetsRemaining - 1
                AssetLoaded:Fire()
            end)()
        end
    end

    --Wait for the assets to load.
    while AssetsRemaining > 0 do
        AssetLoaded.Event:Wait()
    end
end

--[[
Returns the inventory object for a player.
--]]
function InventoryService:GetInventory(Player)
    return self.PlayerInventories[Player]
end

--[[
Returns the item for a given slot.
--]]
function InventoryService:GetItem(Player,SlotName)
    local PlayerInventory = self.PlayerInventories[Player]
    return PlayerInventory and PlayerInventory:GetItem(SlotName)
end

--[[
Returns the inventory changed event for a player.
--]]
function InventoryService:GetInventoryChangedEvent(Player)
    return self.PlayerInventories[Player].InventoryChanged
end

--[[
Adds an item to a player's inventory.
Returns if it was successful.
--]]
function InventoryService:AddItem(Player,Item)
    --Wrap the item as a table if it is a string.
    if type(Item) == "string" then
        Item = {Name=Item}
    end

    --Get the next open slot and return false if the inventory is full.
    local PlayerInventory = self.PlayerInventories[Player]
    local OpenSlot = PlayerInventory:GetNextOpenSlot()
    if not OpenSlot then
        return false
    end

    --Add the item and return true.
    PlayerInventory:AddItem(Item)
    return true
end

--[[
Awards a random item to the given player.
Returns if an item was given and the name
of the item.
--]]
function InventoryService:AwardRandomItem(Player,Zone)
    --Return if the inventory is full.
    local PlayerInventory = self:GetInventory(Player)
    if not PlayerInventory:GetNextOpenSlot() then
        return false
    end
    
    --Compile the options for items.
    local Items = {}
    for ItemName,Data in pairs(ItemData) do
        if Data.Awardable ~= false and (Zone == nil or Zone == Data.Zone) then
            --Determine how many of an item the player can have.
            local TotalPossible = 1
            local Multiplier = 1
            local QuestName = Data.Quest
            if QuestName then
                if QuestService:QuestConditonValid(Player,QuestName,"Inventory") then
                    --Set the total possible as the items for the quest.
                    local QuestData = Quests[QuestName]
                    if QuestData and QuestData.RequiredItems and QuestData.RequiredItems[1] and QuestData.RequiredItems[1].Name == ItemName then
                        TotalPossible = QuestData.RequiredItems[1].Amount or 0
                        Multiplier = QUEST_ITEM_MULTIPLIER
                    end
                else
                    --Set the item as unobtainable.
                    TotalPossible = 0
                end
            end

            --Add the item if the player can have more of an item.
            if TotalPossible > #PlayerInventory:GetItemSlots(ItemName) then
                for i = 1,Multiplier do
                    table.insert(Items,ItemName)
                end
            end
        end
    end

    --Award without the zone limit if no options are possible for the zone.
    if Zone ~= nil and #Items == 0 then
        return self:AwardRandomItem(Player)
    end

    --Add a random item if one exists.
    if #Items > 0 then
        local ItemName = Items[math.random(1,#Items)]
        self:AddItem(Player,ItemName)
        return true,ItemName
    else
        return false
    end
end

--[[
Swaps two slots in a player's inventory.
--]]
function InventoryService:SwapSlots(Player,Slot1,Slot2)
    local PlayerInventory = self.PlayerInventories[Player]
    if PlayerInventory:CanSwap(Slot1,Slot2) then
        PlayerInventory:SwapSlots(Slot1,Slot2)
    end
end

--[[
Unlocks a chest for a player.
--]]
function InventoryService:UnlockChest(Player,Slot)
    --Return if the item isnt' a chest.
    local PlayerInventory = self.PlayerInventories[Player]
    local Item = PlayerInventory:GetItem(Slot)
    if not Item or (Item.Name ~= "Quest Chest" and Item.Name ~= "TreasureChest") then
        return
    end

    --Remove a key if it is a treasure chest.
    if Item.Name == "TreasureChest" then
        --Return if a key doesn't exist.
        local KeySlots = PlayerInventory:GetItemSlots("TreasureKey")
        if #KeySlots == 0 then
            return
        end

        --Remove a key.
        PlayerInventory:RemoveSlot(KeySlots[1])
    end

    --Remove the chest.
    PlayerInventory:RemoveSlot(Slot)

    --Add a new random item.
    self:AwardRandomItem(Player,Item.Zone)
end

--[[
Removes the items of a player's inventory.
--]]
function InventoryService:RemoveItemsByName(Player,Name)
    local PlayerInventory = self.PlayerInventories[Player]
    PlayerInventory:RemoveSlots(PlayerInventory:GetItemSlots(Name))
end

--[[
Deletes an item from a player's inventory.
--]]
function InventoryService:DeleteItem(Player,Slot)
    local PlayerInventory = self.PlayerInventories[Player]
    PlayerInventory:RemoveSlot(Slot)
end



return InventoryService