Files
esx_core/server/main.lua
T
P0Xyio 1367f5ebaa even better way to fix bug with duplicating money and weapons
In my solution, I check if player has weapon/money that officers might want to take server-side. Previous solutions were vulnerable e.g. if two or more officers were searching one player and all took weapon or money at the same time, they would all get that items.
2020-11-17 11:42:04 +00:00

497 lines
14 KiB
Lua

ESX = nil
TriggerEvent('esx:getSharedObject', function(obj) ESX = obj end)
if Config.EnableESXService then
if Config.MaxInService ~= -1 then
TriggerEvent('esx_service:activateService', 'police', Config.MaxInService)
end
end
TriggerEvent('esx_phone:registerNumber', 'police', _U('alert_police'), true, true)
TriggerEvent('esx_society:registerSociety', 'police', 'Police', 'society_police', 'society_police', 'society_police', {type = 'public'})
RegisterNetEvent('esx_policejob:confiscatePlayerItem')
AddEventHandler('esx_policejob:confiscatePlayerItem', function(target, itemType, itemName, amount)
local _source = source
local sourceXPlayer = ESX.GetPlayerFromId(_source)
local targetXPlayer = ESX.GetPlayerFromId(target)
if sourceXPlayer.job.name ~= 'police' then
print(('esx_policejob: %s attempted to confiscate!'):format(sourceXPlayer.identifier))
return
end
if itemType == 'item_standard' then
local targetItem = targetXPlayer.getInventoryItem(itemName)
local sourceItem = sourceXPlayer.getInventoryItem(itemName)
-- does the target player have enough in their inventory?
if targetItem.count > 0 and targetItem.count <= amount then
-- can the player carry the said amount of x item?
if sourceXPlayer.canCarryItem(itemName, sourceItem.count) then
targetXPlayer.removeInventoryItem(itemName, amount)
sourceXPlayer.addInventoryItem (itemName, amount)
sourceXPlayer.showNotification(_U('you_confiscated', amount, sourceItem.label, targetXPlayer.name))
targetXPlayer.showNotification(_U('got_confiscated', amount, sourceItem.label, sourceXPlayer.name))
else
sourceXPlayer.showNotification(_U('quantity_invalid'))
end
else
sourceXPlayer.showNotification(_U('quantity_invalid'))
end
elseif itemType == 'item_account' then
local targetAccount = targetXPlayer.getAccount(itemName)
-- does the target player have enough money?
if targetAccount.money >= amount then
targetXPlayer.removeAccountMoney(itemName, amount)
sourceXPlayer.addAccountMoney (itemName, amount)
sourceXPlayer.showNotification(_U('you_confiscated_account', amount, itemName, targetXPlayer.name))
targetXPlayer.showNotification(_U('got_confiscated_account', amount, itemName, sourceXPlayer.name))
else
sourceXPlayer.showNotification(_U('quantity_invalid'))
end
elseif itemType == 'item_weapon' then
if amount == nil then amount = 0 end
-- does the target player have weapon?
if targetXPlayer.hasWeapon(itemName) then
targetXPlayer.removeWeapon(itemName, amount)
sourceXPlayer.addWeapon (itemName, amount)
sourceXPlayer.showNotification(_U('you_confiscated_weapon', ESX.GetWeaponLabel(itemName), targetXPlayer.name, amount))
targetXPlayer.showNotification(_U('got_confiscated_weapon', ESX.GetWeaponLabel(itemName), amount, sourceXPlayer.name))
else
sourceXPlayer.showNotification(_U('quantity_invalid'))
end
end
end)
RegisterNetEvent('esx_policejob:handcuff')
AddEventHandler('esx_policejob:handcuff', function(target)
local xPlayer = ESX.GetPlayerFromId(source)
if xPlayer.job.name == 'police' then
TriggerClientEvent('esx_policejob:handcuff', target)
else
print(('esx_policejob: %s attempted to handcuff a player (not cop)!'):format(xPlayer.identifier))
end
end)
RegisterNetEvent('esx_policejob:drag')
AddEventHandler('esx_policejob:drag', function(target)
local xPlayer = ESX.GetPlayerFromId(source)
if xPlayer.job.name == 'police' then
TriggerClientEvent('esx_policejob:drag', target, source)
else
print(('esx_policejob: %s attempted to drag (not cop)!'):format(xPlayer.identifier))
end
end)
RegisterNetEvent('esx_policejob:putInVehicle')
AddEventHandler('esx_policejob:putInVehicle', function(target)
local xPlayer = ESX.GetPlayerFromId(source)
if xPlayer.job.name == 'police' then
TriggerClientEvent('esx_policejob:putInVehicle', target)
else
print(('esx_policejob: %s attempted to put in vehicle (not cop)!'):format(xPlayer.identifier))
end
end)
RegisterNetEvent('esx_policejob:OutVehicle')
AddEventHandler('esx_policejob:OutVehicle', function(target)
local xPlayer = ESX.GetPlayerFromId(source)
if xPlayer.job.name == 'police' then
TriggerClientEvent('esx_policejob:OutVehicle', target)
else
print(('esx_policejob: %s attempted to drag out from vehicle (not cop)!'):format(xPlayer.identifier))
end
end)
RegisterNetEvent('esx_policejob:getStockItem')
AddEventHandler('esx_policejob:getStockItem', function(itemName, count)
local _source = source
local xPlayer = ESX.GetPlayerFromId(_source)
TriggerEvent('esx_addoninventory:getSharedInventory', 'society_police', function(inventory)
local inventoryItem = inventory.getItem(itemName)
-- is there enough in the society?
if count > 0 and inventoryItem.count >= count then
-- can the player carry the said amount of x item?
if xPlayer.canCarryItem(itemName, count) then
inventory.removeItem(itemName, count)
xPlayer.addInventoryItem(itemName, count)
xPlayer.showNotification(_U('have_withdrawn', count, inventoryItem.label))
else
xPlayer.showNotification(_U('quantity_invalid'))
end
else
xPlayer.showNotification(_U('quantity_invalid'))
end
end)
end)
RegisterNetEvent('esx_policejob:putStockItems')
AddEventHandler('esx_policejob:putStockItems', function(itemName, count)
local xPlayer = ESX.GetPlayerFromId(source)
local sourceItem = xPlayer.getInventoryItem(itemName)
TriggerEvent('esx_addoninventory:getSharedInventory', 'society_police', function(inventory)
local inventoryItem = inventory.getItem(itemName)
-- does the player have enough of the item?
if sourceItem.count >= count and count > 0 then
xPlayer.removeInventoryItem(itemName, count)
inventory.addItem(itemName, count)
xPlayer.showNotification(_U('have_deposited', count, inventoryItem.label))
else
xPlayer.showNotification(_U('quantity_invalid'))
end
end)
end)
ESX.RegisterServerCallback('esx_policejob:getOtherPlayerData', function(source, cb, target, notify)
local xPlayer = ESX.GetPlayerFromId(target)
if notify then
xPlayer.showNotification(_U('being_searched'))
end
if xPlayer then
local data = {
name = xPlayer.getName(),
job = xPlayer.job.label,
grade = xPlayer.job.grade_label,
inventory = xPlayer.getInventory(),
accounts = xPlayer.getAccounts(),
weapons = xPlayer.getLoadout()
}
if Config.EnableESXIdentity then
data.dob = xPlayer.get('dateofbirth')
data.height = xPlayer.get('height')
if xPlayer.get('sex') == 'm' then data.sex = 'male' else data.sex = 'female' end
end
TriggerEvent('esx_status:getStatus', target, 'drunk', function(status)
if status then
data.drunk = ESX.Math.Round(status.percent)
end
end)
if Config.EnableLicenses then
TriggerEvent('esx_license:getLicenses', target, function(licenses)
data.licenses = licenses
cb(data)
end)
else
cb(data)
end
end
end)
ESX.RegisterServerCallback('esx_policejob:getFineList', function(source, cb, category)
MySQL.Async.fetchAll('SELECT * FROM fine_types WHERE category = @category', {
['@category'] = category
}, function(fines)
cb(fines)
end)
end)
ESX.RegisterServerCallback('esx_policejob:getVehicleInfos', function(source, cb, plate)
MySQL.Async.fetchAll('SELECT owner FROM owned_vehicles WHERE plate = @plate', {
['@plate'] = plate
}, function(result)
local retrivedInfo = {plate = plate}
if result[1] then
local xPlayer = ESX.GetPlayerFromIdentifier(result[1].owner)
-- is the owner online?
if xPlayer then
retrivedInfo.owner = xPlayer.getName()
cb(retrivedInfo)
elseif Config.EnableESXIdentity then
MySQL.Async.fetchAll('SELECT firstname, lastname FROM users WHERE identifier = @identifier', {
['@identifier'] = result[1].owner
}, function(result2)
if result2[1] then
retrivedInfo.owner = ('%s %s'):format(result2[1].firstname, result2[1].lastname)
cb(retrivedInfo)
else
cb(retrivedInfo)
end
end)
else
cb(retrivedInfo)
end
else
cb(retrivedInfo)
end
end)
end)
ESX.RegisterServerCallback('esx_policejob:getArmoryWeapons', function(source, cb)
TriggerEvent('esx_datastore:getSharedDataStore', 'society_police', function(store)
local weapons = store.get('weapons')
if weapons == nil then
weapons = {}
end
cb(weapons)
end)
end)
ESX.RegisterServerCallback('esx_policejob:addArmoryWeapon', function(source, cb, weaponName, removeWeapon)
local xPlayer = ESX.GetPlayerFromId(source)
if removeWeapon then
xPlayer.removeWeapon(weaponName)
end
TriggerEvent('esx_datastore:getSharedDataStore', 'society_police', function(store)
local weapons = store.get('weapons') or {}
local foundWeapon = false
for i=1, #weapons, 1 do
if weapons[i].name == weaponName then
weapons[i].count = weapons[i].count + 1
foundWeapon = true
break
end
end
if not foundWeapon then
table.insert(weapons, {
name = weaponName,
count = 1
})
end
store.set('weapons', weapons)
cb()
end)
end)
ESX.RegisterServerCallback('esx_policejob:removeArmoryWeapon', function(source, cb, weaponName)
local xPlayer = ESX.GetPlayerFromId(source)
xPlayer.addWeapon(weaponName, 500)
TriggerEvent('esx_datastore:getSharedDataStore', 'society_police', function(store)
local weapons = store.get('weapons') or {}
local foundWeapon = false
for i=1, #weapons, 1 do
if weapons[i].name == weaponName then
weapons[i].count = (weapons[i].count > 0 and weapons[i].count - 1 or 0)
foundWeapon = true
break
end
end
if not foundWeapon then
table.insert(weapons, {
name = weaponName,
count = 0
})
end
store.set('weapons', weapons)
cb()
end)
end)
ESX.RegisterServerCallback('esx_policejob:buyWeapon', function(source, cb, weaponName, type, componentNum)
local xPlayer = ESX.GetPlayerFromId(source)
local authorizedWeapons, selectedWeapon = Config.AuthorizedWeapons[xPlayer.job.grade_name]
for k,v in ipairs(authorizedWeapons) do
if v.weapon == weaponName then
selectedWeapon = v
break
end
end
if not selectedWeapon then
print(('esx_policejob: %s attempted to buy an invalid weapon.'):format(xPlayer.identifier))
cb(false)
else
-- Weapon
if type == 1 then
if xPlayer.getMoney() >= selectedWeapon.price then
xPlayer.removeMoney(selectedWeapon.price)
xPlayer.addWeapon(weaponName, 100)
cb(true)
else
cb(false)
end
-- Weapon Component
elseif type == 2 then
local price = selectedWeapon.components[componentNum]
local weaponNum, weapon = ESX.GetWeapon(weaponName)
local component = weapon.components[componentNum]
if component then
if xPlayer.getMoney() >= price then
xPlayer.removeMoney(price)
xPlayer.addWeaponComponent(weaponName, component.name)
cb(true)
else
cb(false)
end
else
print(('esx_policejob: %s attempted to buy an invalid weapon component.'):format(xPlayer.identifier))
cb(false)
end
end
end
end)
ESX.RegisterServerCallback('esx_policejob:buyJobVehicle', function(source, cb, vehicleProps, type)
local xPlayer = ESX.GetPlayerFromId(source)
local price = getPriceFromHash(vehicleProps.model, xPlayer.job.grade_name, type)
-- vehicle model not found
if price == 0 then
print(('esx_policejob: %s attempted to exploit the shop! (invalid vehicle model)'):format(xPlayer.identifier))
cb(false)
else
if xPlayer.getMoney() >= price then
xPlayer.removeMoney(price)
MySQL.Async.execute('INSERT INTO owned_vehicles (owner, vehicle, plate, type, job, `stored`) VALUES (@owner, @vehicle, @plate, @type, @job, @stored)', {
['@owner'] = xPlayer.identifier,
['@vehicle'] = json.encode(vehicleProps),
['@plate'] = vehicleProps.plate,
['@type'] = type,
['@job'] = xPlayer.job.name,
['@stored'] = true
}, function (rowsChanged)
cb(true)
end)
else
cb(false)
end
end
end)
ESX.RegisterServerCallback('esx_policejob:storeNearbyVehicle', function(source, cb, nearbyVehicles)
local xPlayer = ESX.GetPlayerFromId(source)
local foundPlate, foundNum
for k,v in ipairs(nearbyVehicles) do
local result = MySQL.Sync.fetchAll('SELECT plate FROM owned_vehicles WHERE owner = @owner AND plate = @plate AND job = @job', {
['@owner'] = xPlayer.identifier,
['@plate'] = v.plate,
['@job'] = xPlayer.job.name
})
if result[1] then
foundPlate, foundNum = result[1].plate, k
break
end
end
if not foundPlate then
cb(false)
else
MySQL.Async.execute('UPDATE owned_vehicles SET `stored` = true WHERE owner = @owner AND plate = @plate AND job = @job', {
['@owner'] = xPlayer.identifier,
['@plate'] = foundPlate,
['@job'] = xPlayer.job.name
}, function (rowsChanged)
if rowsChanged == 0 then
print(('esx_policejob: %s has exploited the garage!'):format(xPlayer.identifier))
cb(false)
else
cb(true, foundNum)
end
end)
end
end)
function getPriceFromHash(vehicleHash, jobGrade, type)
local vehicles = Config.AuthorizedVehicles[type][jobGrade]
for k,v in ipairs(vehicles) do
if GetHashKey(v.model) == vehicleHash then
return v.price
end
end
return 0
end
ESX.RegisterServerCallback('esx_policejob:getStockItems', function(source, cb)
TriggerEvent('esx_addoninventory:getSharedInventory', 'society_police', function(inventory)
cb(inventory.items)
end)
end)
ESX.RegisterServerCallback('esx_policejob:getPlayerInventory', function(source, cb)
local xPlayer = ESX.GetPlayerFromId(source)
local items = xPlayer.inventory
cb({items = items})
end)
AddEventHandler('playerDropped', function()
-- Save the source in case we lose it (which happens a lot)
local playerId = source
-- Did the player ever join?
if playerId then
local xPlayer = ESX.GetPlayerFromId(playerId)
-- Is it worth telling all clients to refresh?
if xPlayer and xPlayer.job.name == 'police' then
Citizen.Wait(5000)
TriggerClientEvent('esx_policejob:updateBlip', -1)
end
end
end)
RegisterNetEvent('esx_policejob:spawned')
AddEventHandler('esx_policejob:spawned', function()
local xPlayer = ESX.GetPlayerFromId(playerId)
if xPlayer and xPlayer.job.name == 'police' then
Citizen.Wait(5000)
TriggerClientEvent('esx_policejob:updateBlip', -1)
end
end)
RegisterNetEvent('esx_policejob:forceBlip')
AddEventHandler('esx_policejob:forceBlip', function()
TriggerClientEvent('esx_policejob:updateBlip', -1)
end)
AddEventHandler('onResourceStart', function(resource)
if resource == GetCurrentResourceName() then
Citizen.Wait(5000)
TriggerClientEvent('esx_policejob:updateBlip', -1)
end
end)
AddEventHandler('onResourceStop', function(resource)
if resource == GetCurrentResourceName() then
TriggerEvent('esx_phone:removeNumber', 'police')
end
end)