v1.2 Installation - meta-hub/mf-inventory GitHub Wiki

The functions listed below are taken from the default ESX resources, giving you both the original function to search for and the new function with the required changes made. You're best off looking at the changes yourself and modifying your own code so you don't overwrite any existing modifications required by other resources.

FILE: es_extended/client/functions.lua

ESX.ShowInventory
Original
ESX.ShowInventory = function()
  local playerPed = PlayerPedId()
  local elements, currentWeight = {}, 0

  for k,v in pairs(ESX.PlayerData.accounts) do
    if v.money > 0 then
      local formattedMoney = _U('locale_currency', ESX.Math.GroupDigits(v.money))
      local canDrop = v.name ~= 'bank'

      table.insert(elements, {
        label = ('%s: <span style="color:green;">%s</span>'):format(v.label, formattedMoney),
        count = v.money,
        type = 'item_account',
        value = v.name,
        usable = false,
        rare = false,
        canRemove = canDrop
      })
    end
  end

  for k,v in ipairs(ESX.PlayerData.inventory) do
    if v.count > 0 then
      currentWeight = currentWeight + (v.weight * v.count)

      table.insert(elements, {
        label = ('%s x%s'):format(v.label, v.count),
        count = v.count,
        type = 'item_standard',
        value = v.name,
        usable = v.usable,
        rare = v.rare,
        canRemove = v.canRemove
      })
    end
  end

  for k,v in ipairs(Config.Weapons) do
    local weaponHash = GetHashKey(v.name)

    if HasPedGotWeapon(playerPed, weaponHash, false) then
      local ammo, label = GetAmmoInPedWeapon(playerPed, weaponHash)

      if v.ammo then
        label = ('%s - %s %s'):format(v.label, ammo, v.ammo.label)
      else
        label = v.label
      end

      table.insert(elements, {
        label = label,
        count = 1,
        type = 'item_weapon',
        value = v.name,
        usable = false,
        rare = false,
        ammo = ammo,
        canGiveAmmo = (v.ammo ~= nil),
        canRemove = true
      })
    end
  end

  ESX.UI.Menu.CloseAll()

  ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'inventory', {
    title    = _U('inventory', currentWeight, ESX.PlayerData.maxWeight),
    align    = 'bottom-right',
    elements = elements
  }, function(data, menu)
    menu.close()
    local player, distance = ESX.Game.GetClosestPlayer()
    local elements = {}

    if data.current.usable then
      table.insert(elements, {label = _U('use'), action = 'use', type = data.current.type, value = data.current.value})
    end

    if data.current.canRemove then
      if player ~= -1 and distance <= 3.0 then
        table.insert(elements, {label = _U('give'), action = 'give', type = data.current.type, value = data.current.value})
      end

      table.insert(elements, {label = _U('remove'), action = 'remove', type = data.current.type, value = data.current.value})
    end

    if data.current.type == 'item_weapon' and data.current.canGiveAmmo and data.current.ammo > 0 and player ~= -1 and distance <= 3.0 then
      table.insert(elements, {label = _U('giveammo'), action = 'give_ammo', type = data.current.type, value = data.current.value})
    end

    table.insert(elements, {label = _U('return'), action = 'return'})

    ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'inventory_item', {
      title    = data.current.label,
      align    = 'bottom-right',
      elements = elements,
    }, function(data1, menu1)
      local item, type = data1.current.value, data1.current.type

      if data1.current.action == 'give' then
        local playersNearby = ESX.Game.GetPlayersInArea(GetEntityCoords(playerPed), 3.0)

        if #playersNearby > 0 then
          local players, elements = {}, {}

          for k,player in ipairs(playersNearby) do
            players[GetPlayerServerId(player)] = true
          end

          ESX.TriggerServerCallback('esx:getPlayerNames', function(returnedPlayers)
            for playerId,playerName in pairs(returnedPlayers) do
              table.insert(elements, {
                label = playerName,
                playerId = playerId
              })
            end

            ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'give_item_to', {
              title    = _U('give_to'),
              align    = 'bottom-right',
              elements = elements
            }, function(data2, menu2)
              local selectedPlayer, selectedPlayerId = GetPlayerFromServerId(data2.current.playerId), data2.current.playerId
              playersNearby = ESX.Game.GetPlayersInArea(GetEntityCoords(playerPed), 3.0)
              playersNearby = ESX.Table.Set(playersNearby)

              if playersNearby[selectedPlayer] then
                local selectedPlayerPed = GetPlayerPed(selectedPlayer)

                if IsPedOnFoot(selectedPlayerPed) then
                  if type == 'item_weapon' then
                    TriggerServerEvent('esx:giveInventoryItem', selectedPlayerId, type, item, nil)
                    menu2.close()
                    menu1.close()
                  else
                    ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), 'inventory_item_count_give', {
                      title = _U('amount')
                    }, function(data3, menu3)
                      local quantity = tonumber(data3.value)

                      if quantity then
                        TriggerServerEvent('esx:giveInventoryItem', selectedPlayerId, type, item, quantity)
                        menu3.close()
                        menu2.close()
                        menu1.close()
                      else
                        ESX.ShowNotification(_U('amount_invalid'))
                      end
                    end, function(data3, menu3)
                      menu3.close()
                    end)
                  end
                else
                  ESX.ShowNotification(_U('in_vehicle'))
                end
              else
                ESX.ShowNotification(_U('players_nearby'))
                menu2.close()
              end
            end, function(data2, menu2)
              menu2.close()
            end)
          end, players)
        else
          ESX.ShowNotification(_U('players_nearby'))
        end
      elseif data1.current.action == 'remove' then
        if IsPedOnFoot(playerPed) then
          local dict, anim = 'weapons@first_person@aim_rng@generic@projectile@sticky_bomb@', 'plant_floor'
          ESX.Streaming.RequestAnimDict(dict)

          if type == 'item_weapon' then
            menu1.close()
            TaskPlayAnim(playerPed, dict, anim, 8.0, 1.0, 1000, 16, 0.0, false, false, false)
            Citizen.Wait(1000)
            TriggerServerEvent('esx:removeInventoryItem', type, item)
          else
            ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), 'inventory_item_count_remove', {
              title = _U('amount')
            }, function(data2, menu2)
              local quantity = tonumber(data2.value)

              if quantity then
                menu2.close()
                menu1.close()
                TaskPlayAnim(playerPed, dict, anim, 8.0, 1.0, 1000, 16, 0.0, false, false, false)
                Citizen.Wait(1000)
                TriggerServerEvent('esx:removeInventoryItem', type, item, quantity)
              else
                ESX.ShowNotification(_U('amount_invalid'))
              end
            end, function(data2, menu2)
              menu2.close()
            end)
          end
        end
      elseif data1.current.action == 'use' then
        TriggerServerEvent('esx:useItem', item)
      elseif data1.current.action == 'return' then
        ESX.UI.Menu.CloseAll()
        ESX.ShowInventory()
      elseif data1.current.action == 'give_ammo' then
        local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer()
        local closestPed = GetPlayerPed(closestPlayer)
        local pedAmmo = GetAmmoInPedWeapon(playerPed, GetHashKey(item))

        if IsPedOnFoot(closestPed) then
          if closestPlayer ~= -1 and closestDistance < 3.0 then
            if pedAmmo > 0 then
              ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), 'inventory_item_count_give', {
                title = _U('amountammo')
              }, function(data2, menu2)
                local quantity = tonumber(data2.value)

                if quantity then
                  if pedAmmo >= quantity and quantity > 0 then
                    TriggerServerEvent('esx:giveInventoryItem', GetPlayerServerId(closestPlayer), 'item_ammo', item, quantity)
                    menu2.close()
                    menu1.close()
                  else
                    ESX.ShowNotification(_U('noammo'))
                  end
                else
                  ESX.ShowNotification(_U('amount_invalid'))
                end
              end, function(data2, menu2)
                menu2.close()
              end)
            else
              ESX.ShowNotification(_U('noammo'))
            end
          else
            ESX.ShowNotification(_U('players_nearby'))
          end
        else
          ESX.ShowNotification(_U('in_vehicle'))
        end
      end
    end, function(data1, menu1)
      ESX.UI.Menu.CloseAll()
      ESX.ShowInventory()
    end)
  end, function(data, menu)
    menu.close()
  end)
end
Modified
ESX.ShowInventory = function()
  exports["mf-inventory"]:openInventory()
end

FILE: es_extended/server/functions.lua

ESX.UseItem
Original
ESX.UseItem = function(source, item)
  ESX.UsableItemsCallbacks[item](source)
end
Modified
ESX.UseItem = function(source, item, remove, ...)
  if ESX.UsableItemsCallbacks[item] then
    ESX.UsableItemsCallbacks[item](source,remove,...)
  end
end
ESX.SavePlayer
Original
ESX.SavePlayer = function(xPlayer, cb)
  local asyncTasks = {}

  -- User accounts
  for k,v in ipairs(xPlayer.accounts) do
    if ESX.LastPlayerData[xPlayer.source].accounts[v.name] ~= v.money then
      table.insert(asyncTasks, function(cb)
        MySQL.Async.execute('UPDATE user_accounts SET money = @money WHERE identifier = @identifier AND name = @name', {
          ['@money'] = v.money,
          ['@identifier'] = xPlayer.identifier,
          ['@name'] = v.name
        }, function(rowsChanged)
          cb()
        end)
      end)

      ESX.LastPlayerData[xPlayer.source].accounts[v.name] = v.money
    end
  end

  -- Job, loadout, inventory and position
  table.insert(asyncTasks, function(cb)
    MySQL.Async.execute('UPDATE users SET job = @job, job_grade = @job_grade, loadout = @loadout, position = @position, inventory = @inventory WHERE identifier = @identifier', {
      ['@job'] = xPlayer.job.name,
      ['@job_grade'] = xPlayer.job.grade,
      ['@loadout'] = json.encode(xPlayer.getLoadout()),
      ['@position'] = json.encode(xPlayer.getCoords()),
      ['@identifier'] = xPlayer.identifier,
      ['@inventory'] = json.encode(xPlayer.getInventory(true))
    }, function(rowsChanged)
      cb()
    end)
  end)

  Async.parallel(asyncTasks, function(results)
    print(('[es_extended] [^2INFO^7] Saved player "%s^7"'):format(xPlayer.getName()))

    if cb ~= nil then
      cb()
    end
  end)
end
Modified
ESX.SavePlayer = function(xPlayer, cb)
  local asyncTasks = {}

  -- User accounts
  for k,v in ipairs(xPlayer.accounts) do
    if ESX.LastPlayerData[xPlayer.source].accounts[v.name] ~= v.money then
      table.insert(asyncTasks, function(cb)
        MySQL.Async.execute('UPDATE user_accounts SET money = @money WHERE identifier = @identifier AND name = @name', {
          ['@money'] = v.money,
          ['@identifier'] = xPlayer.identifier,
          ['@name'] = v.name
        }, function(rowsChanged)
          cb()
        end)
      end)

      ESX.LastPlayerData[xPlayer.source].accounts[v.name] = v.money
    end
  end

  -- Job, loadout, inventory and position
  table.insert(asyncTasks, function(cb)
    MySQL.Async.execute('UPDATE users SET job = @job, job_grade = @job_grade, loadout = @loadout, position = @position, inventory = @inventory WHERE identifier = @identifier', {
      ['@job'] = xPlayer.job.name,
      ['@job_grade'] = xPlayer.job.grade,
      ['@loadout'] = json.encode(xPlayer.getLoadout()),
      ['@position'] = json.encode(xPlayer.getCoords()),
      ['@identifier'] = xPlayer.identifier,
      ['@inventory'] = json.encode(xPlayer.getInventory(true))
    }, function(rowsChanged)
      cb()
    end)

    exports["mf-inventory"]:saveInventory(xPlayer.getIdentifier())
  end)

  Async.parallel(asyncTasks, function(results)
    print(('[es_extended] [^2INFO^7] Saved player "%s^7"'):format(xPlayer.getName()))

    if cb ~= nil then
      cb()
    end
  end)
end

FILE: es_extended/server/commands.lua

clearinventory
Original
ESX.RegisterCommand('clearinventory', 'admin', function(xPlayer, args, showError)
  for k,v in ipairs(args.playerId.inventory) do
    if v.count > 0 then
      args.playerId.setInventoryItem(v.name, 0)
    end
  end
end, true, {help = _U('command_clearinventory'), validate = true, arguments = {
  {name = 'playerId', help = _U('id_param'), type = 'player'}
}})
Modified
ESX.RegisterCommand('clearinventory', 'admin', function(xPlayer, args, showError)
  exports["mf-inventory"]:clearInventory(args.playerId.identifier)
end, true, {help = _U('command_clearinventory'), validate = true, arguments = {
  {name = 'playerId', help = _U('id_param'), type = 'player'}
}})
clearloadout
Original
ESX.RegisterCommand('clearloadout', 'admin', function(xPlayer, args, showError)
  for k,v in ipairs(args.playerId.loadout) do
    args.playerId.removeWeapon(v.name)
  end
end, true, {help = _U('command_clearloadout'), validate = true, arguments = {
  {name = 'playerId', help = _U('id_param'), type = 'player'}
}})
Modified
ESX.RegisterCommand('clearloadout', 'admin', function(xPlayer, args, showError)
  for k,v in ipairs(args.playerId.loadout) do
    args.playerId.removeWeapon(v.name,v.ammo,true)
  end
  exports["mf-inventory"]:clearLoadout(args.playerId.identifier)
end, true, {help = _U('command_clearloadout'), validate = true, arguments = {
  {name = 'playerId', help = _U('id_param'), type = 'player'}
}})
giveitem
Original
ESX.RegisterCommand('giveitem', 'admin', function(xPlayer, args, showError)
  args.playerId.addInventoryItem(args.item, args.count)
end, true, {help = _U('giveitem'), validate = true, arguments = {
  {name = 'playerId', help = _U('id_param'), type = 'player'},
  {name = 'item', help = _U('item'), type = 'item'},
  {name = 'count', help = _U('amount'), type = 'number'}
}})
Modified
ESX.RegisterCommand('giveitem', 'admin', function(xPlayer, args, showError)
  local item = args.item:lower()
  for i=1,#Config.Weapons do
    if Config.Weapons[i].name:lower() == item then
      return
    end
  end
  
  args.playerId.addInventoryItem(args.item, args.count)
end, true, {help = _U('command_giveitem'), validate = true, arguments = {
  {name = 'playerId', help = _U('commandgeneric_playerid'), type = 'player'},
  {name = 'item', help = _U('command_giveitem_item'), type = 'item'},
  {name = 'count', help = _U('command_giveitem_count'), type = 'number'}
}})

es_extended/server/main.lua

print invalid item
Original
print(('[es_extended] [^3WARNING^7] Ignoring invalid item "%s" for "%s"'):format(name, identifier))
Modified
-- print(('[es_extended] [^3WARNING^7] Ignoring invalid item "%s" for "%s"'):format(name, identifier))

es_extended/server/classes/player.lua

self.getInventory
Original
self.getInventory = function(minimal)
  if minimal then
    local items = {}

    for k,v in ipairs(self.inventory) do
      if v.count > 0 then
        items[v.name] = v.count
      end
    end

    return items
  else
    return self.inventory
  end
end
Modified
-- Reverted to original after recent changes.
self.setInventory
Original
-- Original does not exist. Add this function.
Modified
self.setInventory = function(inv)
  self.inventory = inv
end
self.getInventoryItem
Original
self.getInventoryItem = function(name)
  for k,v in ipairs(self.inventory) do
    if v.name == name then
      return v
    end
  end

  return
end
Modified
self.getInventoryItem = function(name,count, ...)
  return exports["mf-inventory"]:getInventoryItem(self.identifier,name,count, ...)
end
self.addInventoryItem
Original
self.addInventoryItem = function(name, count)
  local item = self.getInventoryItem(name)

  if item then
    count = ESX.Math.Round(count)

    local newCount = item.count + count
    item.count = newCount

    TriggerEvent('esx:onAddInventoryItem', self.source, item.name, item.count)
    self.triggerEvent('esx:addInventoryItem', item.name, item.count)
  end
end
Modified
self.addInventoryItem = function(name, count, quality, ...)
  return exports["mf-inventory"]:addInventoryItem(self.identifier,name,count,self.source,quality, ...)
end
self.removeInventoryItem
Original
self.removeInventoryItem = function(name, count)
  local item = self.getInventoryItem(name)

  if item then
    count = ESX.Math.Round(count)
    local newCount = item.count - count

    if newCount >= 0 then
      item.count = newCount

      TriggerEvent('esx:onRemoveInventoryItem', self.source, item.name, item.count)
      self.triggerEvent('esx:removeInventoryItem', item.name, item.count)
    end
  end
end
Modified
self.removeInventoryItem = function(name, count, ...)
  return exports["mf-inventory"]:removeInventoryItem(self.identifier,name,count,self.source, ...)
end
self.addWeapon
Original
self.addWeapon = function(weaponName, ammo)
  if not self.hasWeapon(weaponName) then
    local weaponLabel = ESX.GetWeaponLabel(weaponName)

    table.insert(self.loadout, {
      name = weaponName,
      ammo = ammo,
      label = weaponLabel,
      components = {},
      tintIndex = 0
    })

    self.triggerEvent('esx:addWeapon', weaponName, ammo)
    self.triggerEvent('esx:addInventoryItem', weaponLabel, false, true)
  end
end
Modified
self.addWeapon = function(weaponName, ammo, metadata, ignoreInventory)
  if not self.hasWeapon(weaponName) then
    local weaponLabel = ESX.GetWeaponLabel(weaponName)

    table.insert(self.loadout, {
      name = weaponName,
      ammo = ammo,
      label = weaponLabel,
      components = {},
      tintIndex = 0
    })

    self.triggerEvent('esx:addWeapon', weaponName, ammo)
    self.triggerEvent('esx:addInventoryItem', weaponLabel, false, true)

    if not ignoreInventory then
      exports["mf-inventory"]:addInventoryItem(self.identifier,weaponName,1,self.source,100,metadata)
    end
  end
end
self.removeWeapon
Original
self.removeWeapon = function(weaponName, ammo)
  local weaponLabel

  for k,v in ipairs(self.loadout) do
    if v.name == weaponName then
      weaponLabel = v.label

      for k2,v2 in ipairs(v.components) do
        self.removeWeaponComponent(weaponName, v2)
      end

      table.remove(self.loadout, k)
      break
    end
  end

  if weaponLabel then
    self.triggerEvent('esx:removeWeapon', weaponName, ammo)
    self.triggerEvent('esx:removeInventoryItem', weaponLabel, false, true)
  end
end
Modified
self.removeWeapon = function(weaponName, ammo, ignoreInventory)
  local weaponLabel

  for k,v in ipairs(self.loadout) do
    if v.name == weaponName then
      weaponLabel = v.label

      for k2,v2 in ipairs(v.components) do
        self.removeWeaponComponent(weaponName, v2)
      end

      table.remove(self.loadout, k)
      break
    end
  end

  if weaponLabel then
    self.triggerEvent('esx:removeWeapon', weaponName, ammo)
    self.triggerEvent('esx:removeInventoryItem', weaponLabel, false, true)

    if not ignoreInventory then
      exports["mf-inventory"]:removeInventoryItem(self.identifier,weaponName,1,self.source)
    end
  end
end
self.setAccountMoney
Original
self.setAccountMoney = function(accountName, money)
  if money >= 0 then
    local account = self.getAccount(accountName)

    if account then
      local prevMoney = account.money
      local newMoney = ESX.Math.Round(money)

      account.money = newMoney

      if accountName == 'bank' then
        self.set('bank', newMoney)
      end

      self.triggerEvent('esx:setAccountMoney', account)
    end
  end
end
Modified
self.setAccountMoney = function(accountName, money)
  if money >= 0 then
    local account = self.getAccount(accountName)

    if account then
      local prevMoney = account.money
      local newMoney = ESX.Math.Round(money)

      account.money = newMoney

      if accountName == 'bank' then
        self.set('bank', newMoney)
      end

      self.triggerEvent('esx:setAccountMoney', account)

      exports["mf-inventory"]:setAccountMoney(self.source,self.identifier,accountName,account.money)
    end
  end
end
self.addAccountMoney
Original
self.addAccountMoney = function(accountName, money)
  if money > 0 then
    local account = self.getAccount(accountName)

    if account then
      local newMoney = account.money + ESX.Math.Round(money)
      account.money = newMoney

      if accountName == 'bank' then
        self.set('bank', newMoney)
      end

      self.triggerEvent('esx:setAccountMoney', account)
    end
  end
end
Modified
self.addAccountMoney = function(accountName, money, ignoreInventory)
  if money > 0 then
    local account = self.getAccount(accountName)

    if account then
      local newMoney = account.money + ESX.Math.Round(money)
      account.money = newMoney

      if accountName == 'bank' then
        self.set('bank', newMoney)
      end

      self.triggerEvent('esx:setAccountMoney', account)

      if not ignoreInventory then
        exports["mf-inventory"]:setAccountMoney(self.source,self.identifier,accountName,account.money)
      end
    end
  end
end
self.removeAccountMoney
Original
self.removeAccountMoney = function(accountName, money)
  if money > 0 then
    local account = self.getAccount(accountName)

    if account then
      local newMoney = account.money - ESX.Math.Round(money)
      account.money = newMoney

      if accountName == 'bank' then
        self.set('bank', newMoney)
      end

      self.triggerEvent('esx:setAccountMoney', account)
    end
  end
end
Modified
self.removeAccountMoney = function(accountName, money, ignoreInventory)
  if money > 0 then
    local account = self.getAccount(accountName)

    if account then
      local newMoney = account.money - ESX.Math.Round(money)
      account.money = newMoney

      if accountName == 'bank' then
        self.set('bank', newMoney)
      end

      self.triggerEvent('esx:setAccountMoney', account)

      if not ignoreInventory then
        exports["mf-inventory"]:setAccountMoney(self.source,self.identifier,accountName,account.money)
      end
    end
  end
end
self.canCarryItem
Original
self.canCarryItem = function(name, count)
  local currentWeight, itemWeight = self.weight, ESX.Items[name].weight
  local newWeight = currentWeight + (itemWeight * count)

  return newWeight <= self.maxWeight
end
Modified
self.canCarryItem = function(...)
  return exports['mf-inventory']:canCarry(self.identifier,...)
end
self.canSwapItem
Original
self.canSwapItem = function(firstItem, firstItemCount, testItem, testItemCount)
  local firstItemObject = self.getInventoryItem(firstItem)
  local testItemObject = self.getInventoryItem(testItem)

  if firstItemObject.count >= firstItemCount then
    local weightWithoutFirstItem = ESX.Math.Round(self.weight - (firstItemObject.weight * firstItemCount))
    local weightWithTestItem = ESX.Math.Round(weightWithoutFirstItem + (testItemObject.weight * testItemCount))

    return weightWithTestItem <= self.maxWeight
  end

  return false
end
Modified
self.canSwapItem = function(...)
  return exports['mf-inventory']:canSwap(self.identifier,...)
end
⚠️ **GitHub.com Fallback** ⚠️