308 lines
14 KiB
Lua
308 lines
14 KiB
Lua
|
|
lib.versionCheck('Qbox-project/qbx_adminmenu')
|
||
|
|
|
||
|
|
local config = require 'config.server'
|
||
|
|
local isFrozen = {}
|
||
|
|
local reportsCount = 0
|
||
|
|
|
||
|
|
REPORTS = {}
|
||
|
|
|
||
|
|
--- Trigger something on players who have the passed permission
|
||
|
|
--- @param permission string - The required permission
|
||
|
|
--- @param cb function - The function, will return player object as parameter
|
||
|
|
function OnAdmin(permission, cb)
|
||
|
|
for k, v in pairs(exports.qbx_core:GetQBPlayers()) do
|
||
|
|
if IsPlayerAceAllowed(k, permission) then
|
||
|
|
cb(v)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
--- Sends a report to online staff members
|
||
|
|
--- @param source string - The player's ID
|
||
|
|
--- @param message string - Message for the report
|
||
|
|
function SendReport(source, message)
|
||
|
|
local reportId = #REPORTS + 1
|
||
|
|
reportsCount += 1
|
||
|
|
|
||
|
|
REPORTS[reportId] = {
|
||
|
|
id = reportsCount,
|
||
|
|
senderId = source,
|
||
|
|
senderName = GetPlayerName(source),
|
||
|
|
message = message,
|
||
|
|
claimed = 'Nobody'
|
||
|
|
}
|
||
|
|
|
||
|
|
table.sort(REPORTS, function(a, b) return a.id < b.id end)
|
||
|
|
|
||
|
|
exports.qbx_core:Notify(source, locale('success.report_sent'), 'success')
|
||
|
|
|
||
|
|
OnAdmin(config.commandPerms.reportReply, function(target)
|
||
|
|
exports.qbx_core:Notify(target.PlayerData.source, locale('success.new_report'), 'success')
|
||
|
|
end)
|
||
|
|
end
|
||
|
|
|
||
|
|
--- Checks if the source is inside of the target's routingbucket
|
||
|
|
--- if not set the source's routingbucket to the target's
|
||
|
|
--- @param source string - The player's ID
|
||
|
|
--- @param target string - The player's ID
|
||
|
|
function CheckRoutingbucket(source, target)
|
||
|
|
local sourceBucket = GetPlayerRoutingBucket(source)
|
||
|
|
local targetBucket = GetPlayerRoutingBucket(target)
|
||
|
|
if sourceBucket ~= targetBucket then SetPlayerRoutingBucket(source, targetBucket) end
|
||
|
|
end
|
||
|
|
|
||
|
|
RegisterNetEvent('qbx_admin:server:sendReply', function(report, message)
|
||
|
|
if not IsPlayerAceAllowed(source, config.commandPerms.reportReply) then exports.qbx_core:Notify(source, locale('error.no_perms'), 'error') return end
|
||
|
|
|
||
|
|
for k, v in pairs(REPORTS) do
|
||
|
|
if v.id == report.id then
|
||
|
|
local name = GetPlayerName(source)
|
||
|
|
|
||
|
|
TriggerClientEvent('chatMessage', report.senderId, "", {255, 0, 0}, string.format('[REPORT #%s] [%s] ^7%s', report.id, name, message))
|
||
|
|
|
||
|
|
exports.qbx_core:Notify(source, locale('success.sent_report_reply'), 'success')
|
||
|
|
if REPORTS[k].claimed == 'Nobody' then
|
||
|
|
REPORTS[k].claimed = name
|
||
|
|
OnAdmin(config.commandPerms.reportReply, function(target)
|
||
|
|
exports.qbx_core:Notify(target.PlayerData.source, string.format(locale('success.report_claimed_by'), report.id, name), 'success')
|
||
|
|
end)
|
||
|
|
end
|
||
|
|
return
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end)
|
||
|
|
|
||
|
|
RegisterNetEvent('qbx_admin:server:deleteReport', function(report)
|
||
|
|
if not IsPlayerAceAllowed(source, config.commandPerms.reportReply) then exports.qbx_core:Notify(source, locale('error.no_perms'), 'error') return end
|
||
|
|
|
||
|
|
for k, v in pairs(REPORTS) do
|
||
|
|
if v.id == report.id then
|
||
|
|
return table.remove(REPORTS, k)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end)
|
||
|
|
|
||
|
|
local generalOptions = {
|
||
|
|
function(selectedPlayer) TriggerClientEvent('qbx_admin:client:killPlayer', selectedPlayer.id) end,
|
||
|
|
function(selectedPlayer) TriggerClientEvent('qbx_medical:client:playerRevived', selectedPlayer.id) end,
|
||
|
|
function(selectedPlayer)
|
||
|
|
if isFrozen[selectedPlayer.id] then
|
||
|
|
FreezeEntityPosition(GetPlayerPed(selectedPlayer.id), false)
|
||
|
|
isFrozen[selectedPlayer.id] = false
|
||
|
|
else
|
||
|
|
FreezeEntityPosition(GetPlayerPed(selectedPlayer.id), true)
|
||
|
|
isFrozen[selectedPlayer.id] = true
|
||
|
|
end
|
||
|
|
end,
|
||
|
|
function(selectedPlayer, source)
|
||
|
|
local coords = GetEntityCoords(GetPlayerPed(selectedPlayer.id))
|
||
|
|
CheckRoutingbucket(source, selectedPlayer.id)
|
||
|
|
SetEntityCoords(GetPlayerPed(source), coords.x, coords.y, coords.z, false, false, false, false)
|
||
|
|
end,
|
||
|
|
function(selectedPlayer, source)
|
||
|
|
local coords = GetEntityCoords(GetPlayerPed(source))
|
||
|
|
CheckRoutingbucket(selectedPlayer.id, source)
|
||
|
|
SetEntityCoords(GetPlayerPed(selectedPlayer.id), coords.x, coords.y, coords.z, false, false, false, false)
|
||
|
|
end,
|
||
|
|
function(selectedPlayer, source)
|
||
|
|
local vehicle = GetVehiclePedIsIn(GetPlayerPed(selectedPlayer.id), false)
|
||
|
|
local seat = -1
|
||
|
|
if vehicle == 0 then return end
|
||
|
|
for i = 0, 8, 1 do if GetPedInVehicleSeat(vehicle, i) == 0 then seat = i break end end
|
||
|
|
if seat == -1 then return end
|
||
|
|
SetPedIntoVehicle(GetPlayerPed(source), vehicle, seat)
|
||
|
|
end,
|
||
|
|
function(selectedPlayer, _, input)
|
||
|
|
exports.qbx_core:SetPlayerBucket(selectedPlayer.id, input)
|
||
|
|
end,
|
||
|
|
}
|
||
|
|
RegisterNetEvent('qbx_admin:server:playerOptionsGeneral', function(selected, selectedPlayer, input)
|
||
|
|
if not IsPlayerAceAllowed(source, config.eventPerms.playerOptionsGeneral) then exports.qbx_core:Notify(source, locale('error.no_perms'), 'error') return end
|
||
|
|
|
||
|
|
---@diagnostic disable-next-line: redundant-parameter
|
||
|
|
generalOptions[selected](selectedPlayer, source, input)
|
||
|
|
end)
|
||
|
|
|
||
|
|
local administrationOptions = {
|
||
|
|
function(source, selectedPlayer, input)
|
||
|
|
if not IsPlayerAceAllowed(source, config.eventPerms.kick) then exports.qbx_core:Notify(source, locale('error.no_perms'), 'error') return end
|
||
|
|
DropPlayer(selectedPlayer.id, input)
|
||
|
|
end,
|
||
|
|
function(source, selectedPlayer, input)
|
||
|
|
if not IsPlayerAceAllowed(source, config.eventPerms.ban) then exports.qbx_core:Notify(source, locale('error.no_perms'), 'error') return end
|
||
|
|
local banDuration = (input[2] or 0) * 3600 + (input[3] or 0) * 86400 + (input[4] or 0) * 2629743
|
||
|
|
DropPlayer(selectedPlayer.id, locale('player_options.administration.banreason', input[1], os.date('%c', os.time() + banDuration)))
|
||
|
|
MySQL.Async.insert('INSERT INTO bans (name, license, discord, ip, reason, expire, bannedby) VALUES (?, ?, ?, ?, ?, ?, ?)', {
|
||
|
|
GetPlayerName(selectedPlayer.id), GetPlayerIdentifierByType(selectedPlayer.id, 'license'), GetPlayerIdentifierByType(selectedPlayer.id, 'discord'),
|
||
|
|
GetPlayerIdentifierByType(selectedPlayer.id, 'ip'), input[1], os.time() + banDuration, GetPlayerName(source)
|
||
|
|
})
|
||
|
|
end,
|
||
|
|
function(source, selectedPlayer, input)
|
||
|
|
if not IsPlayerAceAllowed(source, config.eventPerms.changePerms) then exports.qbx_core:Notify(source, locale('error.no_perms'), 'error') return end
|
||
|
|
if input == 'remove' then exports.qbx_core:RemovePermission(selectedPlayer.id) else exports.qbx_core:AddPermission(selectedPlayer.id, input) end
|
||
|
|
end,
|
||
|
|
}
|
||
|
|
RegisterNetEvent('qbx_admin:server:playerAdministration', function(selected, selectedPlayer, input)
|
||
|
|
administrationOptions[selected](source, selectedPlayer, input)
|
||
|
|
end)
|
||
|
|
|
||
|
|
local playerDataOptions = {
|
||
|
|
name = function(target, input)
|
||
|
|
if input[1] then target.PlayerData.charinfo.firstname = input[1] end
|
||
|
|
if input[2] then target.PlayerData.charinfo.lastname = input[2] end
|
||
|
|
target.Functions.SetPlayerData('charinfo', target.PlayerData.charinfo)
|
||
|
|
end,
|
||
|
|
food = function(target, input) target.Functions.SetMetaData('hunger', input[1]) end,
|
||
|
|
thirst = function(target, input) target.Functions.SetMetaData('thirst', input[1]) end,
|
||
|
|
stress = function(target, input) target.Functions.SetMetaData('stress', input[1]) end,
|
||
|
|
armor = function(target, input) target.Functions.SetMetaData('armor', input[1]) SetPedArmour(GetPlayerPed(target.PlayerData.source), input[1]) end,
|
||
|
|
phone = function(target, input)
|
||
|
|
target.PlayerData.charinfo.phone = input[1]
|
||
|
|
target.Functions.SetPlayerData('charinfo', target.PlayerData.charinfo)
|
||
|
|
end,
|
||
|
|
crafting = function(target, input) target.Functions.SetMetaData('craftingrep', input[1]) end,
|
||
|
|
dealer = function(target, input) target.Functions.SetMetaData('dealerrep', input[1]) end,
|
||
|
|
cash = function(target, input)
|
||
|
|
target.Functions.SetMoney('cash', input[1], 'qbx_adminmenu')
|
||
|
|
end,
|
||
|
|
bank = function(target, input)
|
||
|
|
target.Functions.SetMoney('bank', input[1], 'qbx_adminmenu')
|
||
|
|
end,
|
||
|
|
job = function(target, input)
|
||
|
|
target.Functions.SetJob(input[1], input[2])
|
||
|
|
end,
|
||
|
|
gang = function(target, input)
|
||
|
|
target.Functions.SetGang(input[1], input[2])
|
||
|
|
end,
|
||
|
|
radio = function(target, input)
|
||
|
|
exports['pma-voice']:setPlayerRadio(target.PlayerData.source, input[1])
|
||
|
|
end,
|
||
|
|
}
|
||
|
|
RegisterNetEvent('qbx_admin:server:changePlayerData', function(selected, selectedPlayer, input)
|
||
|
|
local target = exports.qbx_core:GetPlayer(selectedPlayer.id)
|
||
|
|
|
||
|
|
if not IsPlayerAceAllowed(source, config.eventPerms.changePlayerData) then exports.qbx_core:Notify(source, locale('error.no_perms'), 'error') return end
|
||
|
|
if not target then return end
|
||
|
|
|
||
|
|
playerDataOptions[selected](target, input)
|
||
|
|
end)
|
||
|
|
|
||
|
|
RegisterNetEvent('qbx_admin:server:giveAllWeapons', function(weaponType, playerID)
|
||
|
|
local src = playerID or source
|
||
|
|
local target = exports.qbx_core:GetPlayer(src)
|
||
|
|
|
||
|
|
if not IsPlayerAceAllowed(source, config.eventPerms.giveAllWeapons) then exports.qbx_core:Notify(source, locale('error.no_perms'), 'error') return end
|
||
|
|
|
||
|
|
for i = 1, #config.weaponList[weaponType], 1 do
|
||
|
|
target.Functions.AddItem(config.weaponList[weaponType][i], 1)
|
||
|
|
end
|
||
|
|
end)
|
||
|
|
|
||
|
|
lib.callback.register('qbx_admin:callback:getradiolist', function(source, frequency)
|
||
|
|
local list = exports['pma-voice']:getPlayersInRadioChannel(tonumber(frequency))
|
||
|
|
local players = {}
|
||
|
|
|
||
|
|
if not IsPlayerAceAllowed(source, config.eventPerms.getRadioList) then exports.qbx_core:Notify(source, locale('error.no_perms'), 'error') return end
|
||
|
|
|
||
|
|
for targetSource, _ in pairs(list) do -- cheers Knight who shall not be named
|
||
|
|
local player = exports.qbx_core:GetPlayer(targetSource)
|
||
|
|
players[#players + 1] = {
|
||
|
|
id = targetSource,
|
||
|
|
name = player.PlayerData.charinfo.firstname .. ' ' .. player.PlayerData.charinfo.lastname .. ' | (' .. GetPlayerName(targetSource) .. ')'
|
||
|
|
}
|
||
|
|
end
|
||
|
|
return players, frequency
|
||
|
|
end)
|
||
|
|
|
||
|
|
lib.callback.register('qbx_admin:server:getPlayers', function(source)
|
||
|
|
if not IsPlayerAceAllowed(source, config.eventPerms.useMenu) then exports.qbx_core:Notify(source, locale('error.no_perms'), 'error') return end
|
||
|
|
|
||
|
|
local players = {}
|
||
|
|
for k, v in pairs(exports.qbx_core:GetQBPlayers()) do
|
||
|
|
players[#players + 1] = {
|
||
|
|
id = k,
|
||
|
|
cid = v.PlayerData.citizenid,
|
||
|
|
name = v.PlayerData.charinfo.firstname .. ' ' .. v.PlayerData.charinfo.lastname .. ' | (' .. GetPlayerName(k) .. ')',
|
||
|
|
food = Player(v.PlayerData.source).state.hunger,
|
||
|
|
water = Player(v.PlayerData.source).state.thirst,
|
||
|
|
stress = Player(v.PlayerData.source).state.stress,
|
||
|
|
armor = v.PlayerData.metadata.armor,
|
||
|
|
phone = v.PlayerData.charinfo.phone,
|
||
|
|
craftingrep = v.PlayerData.metadata.craftingrep,
|
||
|
|
dealerrep = v.PlayerData.metadata.dealerrep,
|
||
|
|
cash = v.PlayerData.money.cash,
|
||
|
|
bank = v.PlayerData.money.bank,
|
||
|
|
job = v.PlayerData.job.label .. ' | ' .. v.PlayerData.job.grade.level,
|
||
|
|
gang = v.PlayerData.gang.label,
|
||
|
|
license = GetPlayerIdentifierByType(k, 'license') or 'Unknown',
|
||
|
|
discord = GetPlayerIdentifierByType(k, 'discord') or 'Not Linked',
|
||
|
|
steam = GetPlayerIdentifierByType(k, 'steam') or 'Not Linked',
|
||
|
|
}
|
||
|
|
end
|
||
|
|
table.sort(players, function(a, b) return a.id < b.id end)
|
||
|
|
return players
|
||
|
|
end)
|
||
|
|
|
||
|
|
lib.callback.register('qbx_admin:server:getPlayer', function(source, playerToGet)
|
||
|
|
if not IsPlayerAceAllowed(source, config.eventPerms.useMenu) then exports.qbx_core:Notify(source, locale('error.no_perms'), 'error') return end
|
||
|
|
|
||
|
|
local playerData = exports.qbx_core:GetPlayer(playerToGet).PlayerData
|
||
|
|
local player = {
|
||
|
|
id = playerToGet,
|
||
|
|
cid = playerData.citizenid,
|
||
|
|
name = playerData.charinfo.firstname .. ' ' .. playerData.charinfo.lastname .. ' | (' .. GetPlayerName(playerToGet) .. ')',
|
||
|
|
food = Player(playerData.source).state.hunger,
|
||
|
|
water = Player(playerData.source).state.thirst,
|
||
|
|
stress = Player(playerData.source).state.stress,
|
||
|
|
armor = playerData.metadata.armor,
|
||
|
|
phone = playerData.charinfo.phone,
|
||
|
|
craftingrep = playerData.metadata.craftingrep,
|
||
|
|
dealerrep = playerData.metadata.dealerrep,
|
||
|
|
cash = playerData.money.cash,
|
||
|
|
bank = playerData.money.bank,
|
||
|
|
job = playerData.job.label .. ' | ' .. playerData.job.grade.level,
|
||
|
|
gang = playerData.gang.label,
|
||
|
|
license = GetPlayerIdentifierByType(playerToGet, 'license') or 'Unknown',
|
||
|
|
discord = GetPlayerIdentifierByType(playerToGet, 'discord') or 'Not Linked',
|
||
|
|
steam = GetPlayerIdentifierByType(playerToGet, 'steam') or 'Not Linked',
|
||
|
|
}
|
||
|
|
return player
|
||
|
|
end)
|
||
|
|
|
||
|
|
lib.callback.register('qbx_admin:server:clothingMenu', function(source, target)
|
||
|
|
if not IsPlayerAceAllowed(source, config.eventPerms.clothingMenu) then
|
||
|
|
exports.qbx_core:Notify(source, locale('error.no_perms'), 'error')
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
|
||
|
|
TriggerClientEvent('qb-clothing:client:openMenu', target)
|
||
|
|
|
||
|
|
return true
|
||
|
|
end)
|
||
|
|
|
||
|
|
lib.callback.register('qbx_admin:server:canUseMenu', function(source)
|
||
|
|
if not IsPlayerAceAllowed(source, config.eventPerms.useMenu) then
|
||
|
|
exports.qbx_core:Notify(source, locale('error.no_perms'), 'error')
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
|
||
|
|
return true
|
||
|
|
end)
|
||
|
|
|
||
|
|
lib.callback.register('qbx_admin:server:spawnVehicle', function(source, model)
|
||
|
|
local ped = GetPlayerPed(source)
|
||
|
|
local netId, vehicle = qbx.spawnVehicle({
|
||
|
|
model = model,
|
||
|
|
spawnSource = ped,
|
||
|
|
warp = true,
|
||
|
|
})
|
||
|
|
|
||
|
|
exports.qbx_vehiclekeys:GiveKeys(source, vehicle)
|
||
|
|
return netId
|
||
|
|
end)
|
||
|
|
|
||
|
|
lib.callback.register('qbx_admin:server:getReports', function(source)
|
||
|
|
if not IsPlayerAceAllowed(source, config.commandPerms.reportReply) then exports.qbx_core:Notify(source, locale('error.no_perms'), 'error') return end
|
||
|
|
|
||
|
|
return REPORTS
|
||
|
|
end)
|