695 lines
22 KiB
Lua
695 lines
22 KiB
Lua
if not lib then return end
|
|
|
|
require 'modules.bridge.server'
|
|
require 'modules.crafting.server'
|
|
require 'modules.shops.server'
|
|
require 'modules.pefcl.server'
|
|
|
|
if GetConvar('inventory:versioncheck', 'true') == 'true' then
|
|
lib.versionCheck('overextended/ox_inventory')
|
|
end
|
|
|
|
local TriggerEventHooks = require 'modules.hooks.server'
|
|
local db = require 'modules.mysql.server'
|
|
local Items = require 'modules.items.server'
|
|
local Inventory = require 'modules.inventory.server'
|
|
|
|
---@param player table
|
|
---@param data table?
|
|
--- player requires source, identifier, and name
|
|
--- optionally, it should contain jobs/groups, sex, and dateofbirth
|
|
function server.setPlayerInventory(player, data)
|
|
while not shared.ready do Wait(0) end
|
|
|
|
if not data then
|
|
data = db.loadPlayer(player.identifier)
|
|
end
|
|
|
|
local inventory = {}
|
|
local totalWeight = 0
|
|
|
|
if type(data) == 'table' then
|
|
local ostime = os.time()
|
|
|
|
for _, v in pairs(data) do
|
|
if type(v) == 'number' or not v.count or not v.slot then
|
|
if server.convertInventory then
|
|
inventory, totalWeight = server.convertInventory(player.source, data)
|
|
break
|
|
else
|
|
return error(('Inventory for player.%s (%s) contains invalid data. Ensure you have converted inventories to the correct format.'):format(player.source, GetPlayerName(player.source)))
|
|
end
|
|
else
|
|
local item = Items(v.name)
|
|
|
|
if item then
|
|
v.metadata = Items.CheckMetadata(v.metadata or {}, item, v.name, ostime)
|
|
local weight = Inventory.SlotWeight(item, v)
|
|
totalWeight = totalWeight + weight
|
|
|
|
inventory[v.slot] = {name = item.name, label = item.label, weight = weight, slot = v.slot, count = v.count, description = item.description, metadata = v.metadata, stack = item.stack, close = item.close}
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
player.source = tonumber(player.source)
|
|
local inv = Inventory.Create(player.source, player.name, 'player', shared.playerslots, totalWeight, shared.playerweight, player.identifier, inventory)
|
|
|
|
if inv then
|
|
inv.player = server.setPlayerData(player)
|
|
inv.player.ped = GetPlayerPed(player.source)
|
|
|
|
if server.syncInventory then server.syncInventory(inv) end
|
|
TriggerClientEvent('ox_inventory:setPlayerInventory', player.source, Inventory.Drops, inventory, totalWeight, inv.player)
|
|
end
|
|
end
|
|
exports('setPlayerInventory', server.setPlayerInventory)
|
|
AddEventHandler('ox_inventory:setPlayerInventory', server.setPlayerInventory)
|
|
|
|
local registeredDumpsters = {}
|
|
|
|
---@param coords vector3
|
|
---@return string?
|
|
local function getDumpsterFromCoords(coords)
|
|
local found
|
|
|
|
for i = 1, #registeredDumpsters do
|
|
local distance = #(coords - registeredDumpsters[i])
|
|
|
|
if distance < 0.1 then
|
|
found = i
|
|
break
|
|
end
|
|
end
|
|
|
|
return found
|
|
end
|
|
|
|
---@param playerPed number
|
|
---@param stash OxInventory
|
|
---@return vector3?
|
|
local function getClosestStashCoords(playerPed, stash)
|
|
local playerCoords = GetEntityCoords(playerPed)
|
|
local distance = stash.distance or 10
|
|
local coordinates = stash.coords
|
|
|
|
if not coordinates then return end
|
|
|
|
if type(coordinates) == 'table' then
|
|
for i = 1, #coordinates do
|
|
local coords = coordinates[i] --[[@as vector3]]
|
|
|
|
if #(coords - playerCoords) < distance then
|
|
return coords
|
|
end
|
|
end
|
|
|
|
return
|
|
end
|
|
|
|
return #(coordinates - playerCoords) < distance and coordinates or nil
|
|
end
|
|
|
|
---@param source number
|
|
---@param invType string
|
|
---@param data? string|number|table
|
|
---@param ignoreSecurityChecks boolean?
|
|
---@return table | false | nil, table | false | nil, string?
|
|
local function openInventory(source, invType, data, ignoreSecurityChecks)
|
|
if Inventory.Lock then return false end
|
|
|
|
local left = Inventory(source)
|
|
local right, closestCoords
|
|
|
|
if not left then return end
|
|
|
|
left:closeInventory(true)
|
|
Inventory.CloseAll(left, source)
|
|
|
|
if invType == 'player' and data == source then
|
|
data = nil
|
|
end
|
|
|
|
local playerPed = left.player.ped
|
|
|
|
if data then
|
|
local isDataTable = type(data) == 'table'
|
|
|
|
if invType == 'stash' then
|
|
right = Inventory(data, left, ignoreSecurityChecks)
|
|
if right == false then return false end
|
|
elseif isDataTable then
|
|
if data.netid then
|
|
local entity = NetworkGetEntityFromNetworkId(data.netid)
|
|
|
|
if not entity then return end
|
|
|
|
if not ignoreSecurityChecks then
|
|
if #(GetEntityCoords(playerPed) - GetEntityCoords(entity)) > 16 then return end
|
|
end
|
|
|
|
if invType == 'glovebox' then
|
|
if not ignoreSecurityChecks and GetVehiclePedIsIn(playerPed, false) ~= entity then
|
|
return
|
|
end
|
|
end
|
|
|
|
if invType == 'trunk' then
|
|
local lockStatus = ignoreSecurityChecks and 0 or GetVehicleDoorLockStatus(entity)
|
|
|
|
-- 0: no lock; 1: unlocked; 8: boot unlocked
|
|
if lockStatus > 1 and lockStatus ~= 8 then
|
|
return false, false, 'vehicle_locked'
|
|
end
|
|
end
|
|
|
|
local plate = (invType == 'glovebox' or invType == 'trunk') and GetVehicleNumberPlateText(entity)
|
|
|
|
if plate then
|
|
if server.trimplate then plate = string.strtrim(plate) end
|
|
|
|
if not data.id then
|
|
data.id = (invType == 'glovebox' and 'glove' or 'trunk') .. plate
|
|
end
|
|
end
|
|
|
|
data.type = invType
|
|
right = Inventory(data)
|
|
|
|
if right and data.netid ~= right.netid then
|
|
local invEntity = NetworkGetEntityFromNetworkId(right.netid)
|
|
|
|
if not (invEntity > 0 and DoesEntityExist(invEntity)) or (plate and not string.match(GetVehicleNumberPlateText(invEntity) or '', plate)) then
|
|
Inventory.Remove(right)
|
|
right = Inventory(data)
|
|
end
|
|
end
|
|
elseif invType == 'drop' then
|
|
right = Inventory(data.id)
|
|
else
|
|
return
|
|
end
|
|
elseif invType == 'policeevidence' then
|
|
if ignoreSecurityChecks or server.hasGroup(left, shared.police) then
|
|
right = Inventory(('evidence-%s'):format(data))
|
|
end
|
|
elseif invType == 'dumpster' then
|
|
if shared.networkdumpsters then
|
|
local dumpsterId = getDumpsterFromCoords(data)
|
|
right = dumpsterId and Inventory(('dumpster-%s'):format(dumpsterId))
|
|
|
|
if not right then
|
|
dumpsterId = #registeredDumpsters + 1
|
|
right = Inventory.Create(('dumpster-%s'):format(dumpsterId), locale('dumpster'), invType, 15, 0, 100000, false)
|
|
registeredDumpsters[dumpsterId] = data
|
|
end
|
|
else
|
|
---@cast data string
|
|
right = Inventory(data)
|
|
|
|
if not right then
|
|
local netid = tonumber(data:sub(9))
|
|
|
|
if netid and NetworkGetEntityFromNetworkId(netid) > 0 then
|
|
right = Inventory.Create(data, locale('dumpster'), invType, 15, 0, 100000, false)
|
|
end
|
|
end
|
|
end
|
|
elseif invType == 'container' then
|
|
left.containerSlot = data --[[@as number]]
|
|
data = left.items[data]
|
|
|
|
if data then
|
|
right = Inventory(data.metadata.container)
|
|
|
|
if not right then
|
|
right = Inventory.Create(data.metadata.container, data.label, invType, data.metadata.size[1], 0, data.metadata.size[2], false)
|
|
end
|
|
else left.containerSlot = nil end
|
|
else right = Inventory(data) end
|
|
|
|
if not right then return end
|
|
|
|
if not ignoreSecurityChecks and right.groups and not server.hasGroup(left, right.groups) then return end
|
|
|
|
local hookPayload = {
|
|
source = source,
|
|
inventoryId = right.id,
|
|
inventoryType = right.type,
|
|
}
|
|
|
|
if invType == 'container' then hookPayload.slot = left.containerSlot end
|
|
if isDataTable and data.netid then hookPayload.netId = data.netid end
|
|
|
|
if not TriggerEventHooks('openInventory', hookPayload) then return end
|
|
|
|
if left == right then return end
|
|
|
|
if right.player then
|
|
if right.open then return end
|
|
|
|
right.coords = not ignoreSecurityChecks and GetEntityCoords(right.player.ped) or nil
|
|
end
|
|
|
|
if not ignoreSecurityChecks and right.coords then
|
|
closestCoords = getClosestStashCoords(playerPed, right)
|
|
|
|
if not closestCoords then return end
|
|
end
|
|
|
|
left:openInventory(right)
|
|
else
|
|
left:openInventory(left)
|
|
end
|
|
|
|
return {
|
|
id = left.id,
|
|
label = left.label,
|
|
type = left.type,
|
|
slots = left.slots,
|
|
weight = left.weight,
|
|
maxWeight = left.maxWeight
|
|
}, right and {
|
|
id = right.id,
|
|
label = right.player and '' or right.label,
|
|
type = right.player and 'otherplayer' or right.type,
|
|
slots = right.slots,
|
|
weight = right.weight,
|
|
maxWeight = right.maxWeight,
|
|
items = right.items,
|
|
coords = closestCoords or right.coords,
|
|
distance = right.distance
|
|
}
|
|
end
|
|
|
|
---@param source number
|
|
---@param invType string
|
|
---@param data string|number|table
|
|
lib.callback.register('ox_inventory:openInventory', function(source, invType, data)
|
|
return openInventory(source, invType, data)
|
|
end)
|
|
|
|
---@param netId number
|
|
lib.callback.register('ox_inventory:isVehicleATrailer', function(source, netId)
|
|
local entity = NetworkGetEntityFromNetworkId(netId)
|
|
local retval = GetVehicleType(entity)
|
|
return retval == 'trailer'
|
|
end)
|
|
|
|
---@param playerId number
|
|
---@param invType string
|
|
---@param data string|number|table
|
|
function server.forceOpenInventory(playerId, invType, data)
|
|
local left, right = openInventory(playerId, invType, data, true)
|
|
|
|
if left and right then
|
|
TriggerClientEvent('ox_inventory:forceOpenInventory', playerId, left, right)
|
|
return right.id
|
|
end
|
|
end
|
|
|
|
exports('forceOpenInventory', server.forceOpenInventory)
|
|
|
|
local Licenses = lib.load('data.licenses')
|
|
|
|
lib.callback.register('ox_inventory:buyLicense', function(source, id)
|
|
local license = Licenses[id]
|
|
if not license then return end
|
|
|
|
local inventory = Inventory(source)
|
|
if not inventory then return end
|
|
|
|
return server.buyLicense(inventory, license)
|
|
end)
|
|
|
|
lib.callback.register('ox_inventory:getItemCount', function(source, item, metadata, target)
|
|
local inventory = target and Inventory(target) or Inventory(source)
|
|
return (inventory and Inventory.GetItemCount(inventory, item, metadata, true))
|
|
end)
|
|
|
|
lib.callback.register('ox_inventory:getInventory', function(source, id)
|
|
local inventory = Inventory(id or source)
|
|
return inventory and {
|
|
id = inventory.id,
|
|
label = inventory.label,
|
|
type = inventory.type,
|
|
slots = inventory.slots,
|
|
weight = inventory.weight,
|
|
maxWeight = inventory.maxWeight,
|
|
owned = inventory.owner and true or false,
|
|
items = inventory.items
|
|
}
|
|
end)
|
|
|
|
RegisterNetEvent('ox_inventory:usedItemInternal', function(slot)
|
|
local inventory = Inventory(source)
|
|
|
|
if not inventory then return end
|
|
|
|
local item = inventory.usingItem
|
|
|
|
if not item or item.slot ~= slot then
|
|
---@todo
|
|
DropPlayer(inventory.id, 'sussy')
|
|
|
|
return
|
|
end
|
|
|
|
TriggerEvent('ox_inventory:usedItem', inventory.id, item.name, item.slot, next(item.metadata) and item.metadata)
|
|
|
|
inventory.usingItem = nil
|
|
end)
|
|
|
|
---@param source number
|
|
---@param itemName string
|
|
---@param slot number?
|
|
---@param metadata { [string]: any }?
|
|
---@return table | boolean | nil
|
|
lib.callback.register('ox_inventory:useItem', function(source, itemName, slot, metadata, noAnim)
|
|
local inventory = Inventory(source) --[[@as OxInventory]]
|
|
|
|
if inventory.player then
|
|
local item = Items(itemName)
|
|
local data = item and (slot and inventory.items[slot] or Inventory.GetSlotWithItem(inventory, item.name, metadata, true))
|
|
|
|
if not data then return end
|
|
|
|
slot = data.slot
|
|
local durability = data.metadata.durability --[[@as number|boolean|nil]]
|
|
local consume = item.consume
|
|
local label = data.metadata.label or item.label
|
|
|
|
if durability and consume then
|
|
if durability > 100 then
|
|
local ostime = os.time()
|
|
|
|
if ostime > durability then
|
|
Items.UpdateDurability(inventory, data, item, 0)
|
|
return TriggerClientEvent('ox_lib:notify', source, { type = 'error', description = locale('no_durability', label) })
|
|
elseif consume ~= 0 and consume < 1 then
|
|
local degrade = (data.metadata.degrade or item.degrade) * 60
|
|
local percentage = ((durability - ostime) * 100) / degrade
|
|
|
|
if percentage < consume * 100 then
|
|
return TriggerClientEvent('ox_lib:notify', source, { type = 'error', description = locale('not_enough_durability', label) })
|
|
end
|
|
end
|
|
elseif durability <= 0 then
|
|
return TriggerClientEvent('ox_lib:notify', source, { type = 'error', description = locale('no_durability', label) })
|
|
elseif consume ~= 0 and consume < 1 and durability < consume * 100 then
|
|
return TriggerClientEvent('ox_lib:notify', source, { type = 'error', description = locale('not_enough_durability', label) })
|
|
end
|
|
|
|
if data.count > 1 and consume < 1 and consume > 0 and not Inventory.GetEmptySlot(inventory) then
|
|
return TriggerClientEvent('ox_lib:notify', source, { type = 'error', description = locale('cannot_use', label) })
|
|
end
|
|
end
|
|
|
|
if item and data and data.count > 0 and data.name == item.name then
|
|
data = {name=data.name, label=label, count=data.count, slot=slot, metadata=data.metadata, weight=data.weight}
|
|
|
|
if item.ammo then
|
|
if inventory.weapon then
|
|
local weapon = inventory.items[inventory.weapon]
|
|
|
|
if weapon and weapon?.metadata.durability > 0 then
|
|
consume = nil
|
|
end
|
|
else return false end
|
|
elseif item.component or item.tint then
|
|
consume = 1
|
|
data.component = true
|
|
elseif consume then
|
|
if data.count >= consume then
|
|
local result = item.cb and item.cb('usingItem', item, inventory, slot)
|
|
|
|
if result == false then return end
|
|
|
|
if result ~= nil then
|
|
data.server = result
|
|
end
|
|
else
|
|
return TriggerClientEvent('ox_lib:notify', source, { type = 'error', description = locale('item_not_enough', item.name) })
|
|
end
|
|
elseif not item.weapon and server.UseItem then
|
|
inventory.usingItem = data
|
|
-- This is used to call an external useItem function, i.e. ESX.UseItem
|
|
-- If an error is being thrown on item use there is no internal solution. We previously kept a list
|
|
-- of usable items which led to issues when restarting resources (for obvious reasons), but config
|
|
-- developers complained the inventory broke their items. Safely invoking registered item callbacks
|
|
-- should resolve issues, i.e. https://github.com/esx-framework/esx-legacy/commit/9fc382bbe0f5b96ff102dace73c424a53458c96e
|
|
return pcall(server.UseItem, source, data.name, data)
|
|
end
|
|
|
|
data.consume = consume
|
|
|
|
if not TriggerEventHooks('usingItem', {
|
|
source = source,
|
|
inventoryId = inventory and inventory.id,
|
|
item = inventory.items[slot],
|
|
consume = consume
|
|
}) then return false end
|
|
|
|
---@type boolean
|
|
local success = lib.callback.await('ox_inventory:usingItem', source, data, noAnim)
|
|
|
|
if item.weapon then
|
|
inventory.weapon = success and slot or nil
|
|
end
|
|
|
|
if not success then return end
|
|
|
|
inventory.usingItem = data
|
|
|
|
if consume and consume ~= 0 and not data.component then
|
|
data = inventory.items[data.slot]
|
|
|
|
if not data then return end
|
|
|
|
durability = consume ~= 0 and consume < 1 and data.metadata.durability --[[@as number | false]]
|
|
|
|
if durability then
|
|
if durability > 100 then
|
|
local degrade = (data.metadata.degrade or item.degrade) * 60
|
|
durability -= degrade * consume
|
|
else
|
|
durability -= consume * 100
|
|
end
|
|
|
|
if data.count > 1 then
|
|
local emptySlot = Inventory.GetEmptySlot(inventory)
|
|
|
|
if emptySlot then
|
|
local newItem = Inventory.SetSlot(inventory, item, 1, table.deepclone(data.metadata), emptySlot)
|
|
|
|
if newItem then
|
|
Items.UpdateDurability(inventory, newItem, item, durability)
|
|
end
|
|
end
|
|
|
|
durability = 0
|
|
else
|
|
Items.UpdateDurability(inventory, data, item, durability)
|
|
end
|
|
|
|
if durability <= 0 then
|
|
durability = false
|
|
end
|
|
end
|
|
|
|
if not durability then
|
|
Inventory.RemoveItem(inventory.id, data.name, consume < 1 and 1 or consume, nil, data.slot)
|
|
else
|
|
inventory.changed = true
|
|
|
|
if server.syncInventory then server.syncInventory(inventory) end
|
|
end
|
|
|
|
if item?.cb then
|
|
item.cb('usedItem', item, inventory, data.slot)
|
|
end
|
|
end
|
|
|
|
return true
|
|
end
|
|
end
|
|
end)
|
|
|
|
local function conversionScript()
|
|
shared.ready = false
|
|
|
|
local file = 'setup/convert.lua'
|
|
local import = LoadResourceFile(shared.resource, file)
|
|
local func = load(import, ('@@%s/%s'):format(shared.resource, file)) --[[@as function]]
|
|
|
|
conversionScript = func()
|
|
end
|
|
|
|
RegisterCommand('convertinventory', function(source, args)
|
|
if source ~= 0 then return warn('This command can only be executed with the server console.') end
|
|
if type(conversionScript) == 'function' then conversionScript() end
|
|
local arg = args[1]
|
|
|
|
local convert = arg and conversionScript[arg]
|
|
|
|
if not convert then
|
|
return warn('Invalid conversion argument. Valid options: esx, esxproperty')
|
|
end
|
|
|
|
CreateThread(convert)
|
|
end, true)
|
|
|
|
|
|
lib.addCommand({'additem', 'giveitem'}, {
|
|
help = 'Gives an item to a player with the given id',
|
|
params = {
|
|
{ name = 'target', type = 'playerId', help = 'The player to receive the item' },
|
|
{ name = 'item', type = 'string', help = 'The name of the item' },
|
|
{ name = 'count', type = 'number', help = 'The amount of the item to give', optional = true },
|
|
{ name = 'type', help = 'Sets the "type" metadata to the value', optional = true },
|
|
},
|
|
restricted = 'group.admin',
|
|
}, function(source, args)
|
|
local item = Items(args.item)
|
|
|
|
if item then
|
|
local inventory = Inventory(args.target) --[[@as OxInventory]]
|
|
local count = args.count or 1
|
|
local success, response = Inventory.AddItem(inventory, item.name, count, args.type and { type = tonumber(args.type) or args.type })
|
|
|
|
if not success then
|
|
return Citizen.Trace(('Failed to give %sx %s to player %s (%s)'):format(count, item.name, args.target, response))
|
|
end
|
|
|
|
source = Inventory(source) or { label = 'console', owner = 'console' }
|
|
|
|
if server.loglevel > 0 then
|
|
lib.logger(source.owner, 'admin', ('"%s" gave %sx %s to "%s"'):format(source.label, count, item.name, inventory.label))
|
|
end
|
|
end
|
|
end)
|
|
|
|
lib.addCommand('removeitem', {
|
|
help = 'Removes an item to a player with the given id',
|
|
params = {
|
|
{ name = 'target', type = 'playerId', help = 'The player to remove the item from' },
|
|
{ name = 'item', type = 'string', help = 'The name of the item' },
|
|
{ name = 'count', type = 'number', help = 'The amount of the item to take' },
|
|
{ name = 'type', help = 'Only remove items with a matching metadata "type"', optional = true },
|
|
},
|
|
restricted = 'group.admin',
|
|
}, function(source, args)
|
|
local item = Items(args.item)
|
|
|
|
if item and args.count > 0 then
|
|
local inventory = Inventory(args.target) --[[@as OxInventory]]
|
|
local success, response = Inventory.RemoveItem(inventory, item.name, args.count, args.type and { type = tonumber(args.type) or args.type }, nil, true)
|
|
|
|
if not success then
|
|
return Citizen.Trace(('Failed to remove %sx %s from player %s (%s)'):format(args.count, item.name, args.target, response))
|
|
end
|
|
|
|
source = Inventory(source) or {label = 'console', owner = 'console'}
|
|
|
|
if server.loglevel > 0 then
|
|
lib.logger(source.owner, 'admin', ('"%s" removed %sx %s from "%s"'):format(source.label, args.count, item.name, inventory.label))
|
|
end
|
|
end
|
|
end)
|
|
|
|
lib.addCommand('setitem', {
|
|
help = 'Sets the item count for a player, removing or adding as needed',
|
|
params = {
|
|
{ name = 'target', type = 'playerId', help = 'The player to set the items for' },
|
|
{ name = 'item', type = 'string', help = 'The name of the item' },
|
|
{ name = 'count', type = 'number', help = 'The amount of items to set', optional = true },
|
|
{ name = 'type', help = 'Add or remove items with the metadata "type"', optional = true },
|
|
},
|
|
restricted = 'group.admin',
|
|
}, function(source, args)
|
|
local item = Items(args.item)
|
|
|
|
if item then
|
|
local inventory = Inventory(args.target) --[[@as OxInventory]]
|
|
local success, response = Inventory.SetItem(inventory, item.name, args.count or 0, args.type and { type = tonumber(args.type) or args.type })
|
|
|
|
if not success then
|
|
return Citizen.Trace(('Failed to set %s count to %sx for player %s (%s)'):format(item.name, args.count, args.target, response))
|
|
end
|
|
|
|
source = Inventory(source) or {label = 'console', owner = 'console'}
|
|
|
|
if server.loglevel > 0 then
|
|
lib.logger(source.owner, 'admin', ('"%s" set "%s" %s count to %sx'):format(source.label, inventory.label, item.name, args.count))
|
|
end
|
|
end
|
|
end)
|
|
|
|
lib.addCommand('clearevidence', {
|
|
help = 'Clears a police evidence locker with the given id',
|
|
params = {
|
|
{ name = 'locker', type = 'number', help = 'The locker id to clear' },
|
|
},
|
|
}, function(source, args)
|
|
if not server.isPlayerBoss then return end
|
|
|
|
local inventory = Inventory(source)
|
|
local group, grade = server.hasGroup(inventory, shared.police)
|
|
local hasPermission = group and server.isPlayerBoss(source, group, grade)
|
|
|
|
if hasPermission then
|
|
MySQL.query('DELETE FROM ox_inventory WHERE name = ?', {('evidence-%s'):format(args.locker)})
|
|
end
|
|
end)
|
|
|
|
lib.addCommand('takeinv', {
|
|
help = 'Confiscates the target inventory, to restore with /restoreinv',
|
|
params = {
|
|
{ name = 'target', type = 'playerId', help = 'The player to confiscate items from' },
|
|
},
|
|
restricted = 'group.admin',
|
|
}, function(source, args)
|
|
Inventory.Confiscate(args.target)
|
|
end)
|
|
|
|
lib.addCommand({'restoreinv', 'returninv'}, {
|
|
help = 'Restores a previously confiscated inventory for the target',
|
|
params = {
|
|
{ name = 'target', type = 'playerId', help = 'The player to restore items to' },
|
|
},
|
|
restricted = 'group.admin',
|
|
}, function(source, args)
|
|
Inventory.Return(args.target)
|
|
end)
|
|
|
|
lib.addCommand('clearinv', {
|
|
help = 'Wipes all items from the target inventory',
|
|
params = {
|
|
{ name = 'invId', help = 'The inventory to wipe items from' },
|
|
},
|
|
restricted = 'group.admin',
|
|
}, function(source, args)
|
|
Inventory.Clear(tonumber(args.invId) or args.invId == 'me' and source or args.invId)
|
|
end)
|
|
|
|
lib.addCommand('saveinv', {
|
|
help = 'Save all pending inventory changes to the database',
|
|
params = {
|
|
{ name = 'lock', help = 'Lock inventory access, until restart or saved without a lock', optional = true },
|
|
},
|
|
restricted = 'group.admin',
|
|
}, function(source, args)
|
|
Inventory.SaveInventories(args.lock == 'true', false)
|
|
end)
|
|
|
|
lib.addCommand('viewinv', {
|
|
help = 'Inspect the target inventory without allowing interactions',
|
|
params = {
|
|
{ name = 'invId', help = 'The inventory to inspect' },
|
|
},
|
|
restricted = 'group.admin',
|
|
}, function(source, args)
|
|
Inventory.InspectInventory(source, tonumber(args.invId) or args.invId)
|
|
end)
|