1
0
Fork 0
forked from Simnation/Main
Main/resources/[carscripts]/nordi_car_admin/server.lua

553 lines
20 KiB
Lua
Raw Normal View History

2025-08-06 10:11:58 +02:00
local QBCore = exports['qb-core']:GetCoreObject()
2025-08-06 12:45:18 +02:00
-- Interne Konfiguration für das Fahrzeugadmin-System
local AdminConfig = {
-- Erlaubte Jobs für das Vehicle Admin System
AllowedJobs = {
['police'] = true,
['admin'] = true,
['mechanic'] = true,
['ambulance'] = true,
['cardealer'] = true,
},
2025-08-06 12:37:47 +02:00
2025-08-06 12:45:18 +02:00
-- Debug-Modus
Debug = false,
-- Log-Einstellungen
Log = {
Enabled = true,
Webhook = "https://discord.com/api/webhooks/1366812966049288192/9ZjJC9_gLX6Fk-acf0YSW_haGWpCqG9zRGWaj0wCKLZefp8FX-GwNZBP77H6K93KfIw3", -- Verwende den gleichen Webhook wie im Garagensystem
Colors = {
green = 56108,
grey = 8421504,
red = 16711680,
orange = 16744192,
blue = 2061822,
purple = 11750815,
},
SystemName = "Evolution_State_life Log [Fahrzeugadmin]",
},
-- Standard-Garagen falls keine in QBCore definiert sind
DefaultGarages = {
['legion'] = { label = 'Legion Square Garage' },
['pillboxgarage'] = { label = 'Pillbox Garage' },
['spanishave'] = { label = 'Spanish Avenue Garage' },
['caears24'] = { label = 'Caears 24 Garage' },
['littleseoul'] = { label = 'Little Seoul Garage' },
['rockfordgarage'] = { label = 'Rockford Garage' },
['lamesamotel'] = { label = 'Lamesa Motel Garage' },
['airportp'] = { label = 'Airport Parking' },
['depot'] = { label = 'Depot' },
['impound'] = { label = 'Impound Lot' },
['pdgarage'] = { label = 'Police Garage' },
['emsgarage'] = { label = 'EMS Garage' },
['mechgarage'] = { label = 'Mechanic Garage' }
}
}
2025-08-06 12:37:47 +02:00
2025-08-06 12:45:18 +02:00
-- Versuche, die Garagen aus dem externen Config zu laden
local ExternalGarages = {}
2025-08-06 11:48:14 +02:00
-- Job Permission Check
local function HasPermission(source)
2025-08-06 10:11:58 +02:00
local Player = QBCore.Functions.GetPlayer(source)
if not Player then return false end
2025-08-06 11:48:14 +02:00
-- Check if player has admin permission
if QBCore.Functions.HasPermission(source, 'admin') then
return true
end
-- Check if player has allowed job
local playerJob = Player.PlayerData.job.name
2025-08-06 12:45:18 +02:00
return AdminConfig.AllowedJobs[playerJob] == true
2025-08-06 10:11:58 +02:00
end
-- Get all players from database
QBCore.Functions.CreateCallback('vehicleadmin:getPlayers', function(source, cb)
2025-08-06 11:48:14 +02:00
if not HasPermission(source) then
2025-08-06 10:11:58 +02:00
cb(false)
return
end
MySQL.Async.fetchAll('SELECT citizenid, charinfo FROM players ORDER BY charinfo', {}, function(result)
2025-08-06 12:21:15 +02:00
if not result then
cb({})
return
end
2025-08-06 10:11:58 +02:00
local players = {}
for i = 1, #result do
local charinfo = json.decode(result[i].charinfo)
2025-08-06 12:21:15 +02:00
if charinfo and charinfo.firstname and charinfo.lastname then
table.insert(players, {
citizenid = result[i].citizenid,
name = charinfo.firstname .. ' ' .. charinfo.lastname
})
end
2025-08-06 10:11:58 +02:00
end
cb(players)
end)
end)
2025-08-06 13:29:54 +02:00
-- Funktion zum Abrufen des Fahrzeugnamens
local function GetVehicleDisplayName(model)
-- Versuche zuerst, den Namen aus QBCore zu bekommen
local vehicleData = QBCore.Shared.Vehicles[model]
if vehicleData and vehicleData.name then
return vehicleData.name
end
2025-08-06 14:00:37 +02:00
-- Wenn kein Name gefunden wurde, gib einfach den Modellnamen zurück
2025-08-06 13:29:54 +02:00
return model
end
2025-08-06 10:11:58 +02:00
-- Get vehicles for specific player
QBCore.Functions.CreateCallback('vehicleadmin:getPlayerVehicles', function(source, cb, citizenid)
2025-08-06 11:48:14 +02:00
if not HasPermission(source) then
2025-08-06 10:11:58 +02:00
cb(false)
return
end
MySQL.Async.fetchAll('SELECT * FROM player_vehicles WHERE citizenid = ?', {citizenid}, function(result)
2025-08-06 12:21:15 +02:00
if not result then
cb({})
return
end
2025-08-06 10:11:58 +02:00
local vehicles = {}
for i = 1, #result do
local vehicle = result[i]
2025-08-06 13:29:54 +02:00
local displayName = vehicle.name
-- Wenn kein Name gesetzt ist, versuche den Namen aus dem Modell zu bekommen
if not displayName or displayName == "" then
displayName = GetVehicleDisplayName(vehicle.vehicle)
end
2025-08-06 10:11:58 +02:00
table.insert(vehicles, {
2025-08-06 12:21:15 +02:00
plate = vehicle.plate or 'UNKNOWN',
vehicle = vehicle.vehicle or 'unknown',
garage = vehicle.garage or 'none',
state = vehicle.garage == "OUT" and 0 or 1, -- Anpassung an euer Garagensystem
fuel = vehicle.fuel or 100,
engine = vehicle.engine or 1000,
body = vehicle.body or 1000,
2025-08-06 10:11:58 +02:00
citizenid = vehicle.citizenid,
2025-08-06 13:29:54 +02:00
name = displayName,
2025-08-06 12:21:15 +02:00
mods = vehicle.mods or "{}"
2025-08-06 10:11:58 +02:00
})
end
cb(vehicles)
end)
end)
2025-08-06 12:21:15 +02:00
-- Get all garages from your config
2025-08-06 10:11:58 +02:00
QBCore.Functions.CreateCallback('vehicleadmin:getGarages', function(source, cb)
2025-08-06 11:48:14 +02:00
if not HasPermission(source) then
2025-08-06 10:11:58 +02:00
cb(false)
return
end
local garages = {}
2025-08-06 12:21:15 +02:00
2025-08-06 13:29:54 +02:00
-- Verwende die externen Garagen aus dem Garagensystem
2025-08-06 12:45:18 +02:00
if next(ExternalGarages) ~= nil then
for k, v in pairs(ExternalGarages) do
2025-08-06 12:37:47 +02:00
table.insert(garages, {
name = v.name,
label = v.name -- Ihr könnt hier auch eine Label-Property hinzufügen
})
end
else
-- Fallback auf Standard-Garagen
2025-08-06 12:45:18 +02:00
for garageName, garageData in pairs(AdminConfig.DefaultGarages) do
2025-08-06 12:37:47 +02:00
table.insert(garages, {
name = garageName,
label = garageData.label or garageName
})
end
2025-08-06 10:11:58 +02:00
end
2025-08-06 12:21:15 +02:00
-- Sortiere alphabetisch
table.sort(garages, function(a, b)
return a.name < b.name
end)
2025-08-06 10:11:58 +02:00
cb(garages)
end)
2025-08-06 11:48:14 +02:00
-- Check player's job and return permissions
QBCore.Functions.CreateCallback('vehicleadmin:getPlayerJob', function(source, cb)
local Player = QBCore.Functions.GetPlayer(source)
if not Player then
cb(false)
return
end
local hasPermission = HasPermission(source)
local jobName = Player.PlayerData.job.name
local jobLabel = Player.PlayerData.job.label
cb({
hasPermission = hasPermission,
jobName = jobName,
jobLabel = jobLabel
})
end)
2025-08-06 10:11:58 +02:00
-- Move vehicle to garage
RegisterNetEvent('vehicleadmin:moveToGarage', function(plate, garage)
local src = source
2025-08-06 11:48:14 +02:00
if not HasPermission(src) then
TriggerClientEvent('ox_lib:notify', src, {
title = 'Keine Berechtigung',
description = 'Du hast keine Berechtigung für diese Aktion',
type = 'error'
})
return
end
2025-08-06 10:11:58 +02:00
-- Delete vehicle from world if it exists
local vehicles = GetAllVehicles()
for i = 1, #vehicles do
local veh = vehicles[i]
2025-08-06 12:21:15 +02:00
if DoesEntityExist(veh) then
local vehPlate = GetVehicleNumberPlateText(veh):gsub("%s+", "")
if vehPlate == plate:gsub("%s+", "") then
DeleteEntity(veh)
break
end
2025-08-06 10:11:58 +02:00
end
end
2025-08-06 12:21:15 +02:00
-- Update database - Anpassung an euer Garagensystem
MySQL.Async.execute('UPDATE player_vehicles SET garage = ? WHERE plate = ?', {garage, plate}, function(affectedRows)
2025-08-06 10:11:58 +02:00
if affectedRows > 0 then
2025-08-06 12:21:15 +02:00
-- Entferne das Fahrzeug aus dem Parking-System, falls vorhanden
MySQL.Async.execute('DELETE FROM vehicle_parking WHERE plate = ?', {plate})
2025-08-06 11:48:14 +02:00
-- Log the action
local Player = QBCore.Functions.GetPlayer(src)
2025-08-06 12:21:15 +02:00
if Player then
print(string.format('[VEHICLE ADMIN] %s (%s) moved vehicle %s to garage %s',
Player.PlayerData.charinfo.firstname .. ' ' .. Player.PlayerData.charinfo.lastname,
Player.PlayerData.job.label,
plate,
garage
))
-- Log für Discord
2025-08-06 12:45:18 +02:00
if AdminConfig.Log and AdminConfig.Log.Enabled then
2025-08-06 12:37:47 +02:00
sendToDiscord("Fahrzeugadmin", Player.PlayerData.charinfo.firstname .. " " .. Player.PlayerData.charinfo.lastname .. " (" .. Player.PlayerData.job.label .. ") hat Fahrzeug " .. plate .. " in Garage " .. garage .. " gestellt.", "blue")
end
2025-08-06 12:21:15 +02:00
end
2025-08-06 11:48:14 +02:00
2025-08-06 10:11:58 +02:00
TriggerClientEvent('ox_lib:notify', src, {
title = 'Fahrzeugverwaltung',
description = 'Fahrzeug wurde in Garage ' .. garage .. ' gestellt',
type = 'success'
})
else
TriggerClientEvent('ox_lib:notify', src, {
title = 'Fahrzeugverwaltung',
description = 'Fehler beim Verschieben des Fahrzeugs',
type = 'error'
})
end
end)
end)
-- Delete vehicle from map
RegisterNetEvent('vehicleadmin:deleteFromMap', function(plate)
local src = source
2025-08-06 11:48:14 +02:00
if not HasPermission(src) then
TriggerClientEvent('ox_lib:notify', src, {
title = 'Keine Berechtigung',
description = 'Du hast keine Berechtigung für diese Aktion',
type = 'error'
})
return
end
2025-08-06 10:11:58 +02:00
local vehicles = GetAllVehicles()
local deleted = false
for i = 1, #vehicles do
local veh = vehicles[i]
2025-08-06 12:21:15 +02:00
if DoesEntityExist(veh) then
local vehPlate = GetVehicleNumberPlateText(veh):gsub("%s+", "")
if vehPlate == plate:gsub("%s+", "") then
DeleteEntity(veh)
deleted = true
break
end
2025-08-06 10:11:58 +02:00
end
end
2025-08-06 11:48:14 +02:00
-- Log the action
local Player = QBCore.Functions.GetPlayer(src)
2025-08-06 12:21:15 +02:00
if Player then
print(string.format('[VEHICLE ADMIN] %s (%s) deleted vehicle %s from map',
Player.PlayerData.charinfo.firstname .. ' ' .. Player.PlayerData.charinfo.lastname,
Player.PlayerData.job.label,
plate
))
-- Log für Discord
2025-08-06 12:45:18 +02:00
if AdminConfig.Log and AdminConfig.Log.Enabled then
2025-08-06 12:37:47 +02:00
sendToDiscord("Fahrzeugadmin", Player.PlayerData.charinfo.firstname .. " " .. Player.PlayerData.charinfo.lastname .. " (" .. Player.PlayerData.job.label .. ") hat Fahrzeug " .. plate .. " von der Map gelöscht.", "orange")
end
2025-08-06 12:21:15 +02:00
end
2025-08-06 11:48:14 +02:00
2025-08-06 10:11:58 +02:00
if deleted then
TriggerClientEvent('ox_lib:notify', src, {
title = 'Fahrzeugverwaltung',
description = 'Fahrzeug wurde von der Map gelöscht',
type = 'success'
})
else
TriggerClientEvent('ox_lib:notify', src, {
title = 'Fahrzeugverwaltung',
description = 'Fahrzeug nicht auf der Map gefunden',
2025-08-06 11:48:14 +02:00
type = 'info'
2025-08-06 10:11:58 +02:00
})
end
end)
-- Repair vehicle
RegisterNetEvent('vehicleadmin:repairVehicle', function(plate)
local src = source
2025-08-06 11:48:14 +02:00
if not HasPermission(src) then
TriggerClientEvent('ox_lib:notify', src, {
title = 'Keine Berechtigung',
description = 'Du hast keine Berechtigung für diese Aktion',
type = 'error'
})
return
end
2025-08-06 10:11:58 +02:00
2025-08-06 12:21:15 +02:00
-- Get vehicle mods first
MySQL.Async.fetchAll('SELECT mods FROM player_vehicles WHERE plate = ?', {plate}, function(result)
if result and result[1] and result[1].mods then
local mods = json.decode(result[1].mods)
-- Update mods with repaired values
mods.engineHealth = 1000
mods.bodyHealth = 1000
mods.fuelLevel = 100
-- Reset door and window status if they exist
if mods.doorStatus then
mods.doorStatus = {}
2025-08-06 10:11:58 +02:00
end
2025-08-06 11:48:14 +02:00
2025-08-06 12:21:15 +02:00
if mods.windowStatus then
mods.windowStatus = {}
for i = 0, 7 do
mods.windowStatus[tostring(i)] = true
end
end
2025-08-06 11:48:14 +02:00
2025-08-06 12:21:15 +02:00
-- Update database with repaired mods
MySQL.Async.execute('UPDATE player_vehicles SET mods = ? WHERE plate = ?', {json.encode(mods), plate}, function(affectedRows)
-- Also repair if vehicle is on map
local vehicles = GetAllVehicles()
for i = 1, #vehicles do
local veh = vehicles[i]
if DoesEntityExist(veh) then
local vehPlate = GetVehicleNumberPlateText(veh):gsub("%s+", "")
if vehPlate == plate:gsub("%s+", "") then
SetVehicleFixed(veh)
SetVehicleDeformationFixed(veh)
SetVehicleUndriveable(veh, false)
SetVehicleEngineOn(veh, true, true)
SetVehicleFuelLevel(veh, 100.0)
2025-08-06 12:45:18 +02:00
-- Versuche, den Kraftstoff über das lc_fuel-Export zu setzen, falls verfügbar
pcall(function()
exports["lc_fuel"]:SetFuel(veh, 100)
end)
2025-08-06 12:21:15 +02:00
break
end
end
end
-- Log the action
local Player = QBCore.Functions.GetPlayer(src)
if Player then
print(string.format('[VEHICLE ADMIN] %s (%s) repaired vehicle %s',
Player.PlayerData.charinfo.firstname .. ' ' .. Player.PlayerData.charinfo.lastname,
Player.PlayerData.job.label,
plate
))
-- Log für Discord
2025-08-06 12:45:18 +02:00
if AdminConfig.Log and AdminConfig.Log.Enabled then
2025-08-06 12:37:47 +02:00
sendToDiscord("Fahrzeugadmin", Player.PlayerData.charinfo.firstname .. " " .. Player.PlayerData.charinfo.lastname .. " (" .. Player.PlayerData.job.label .. ") hat Fahrzeug " .. plate .. " repariert.", "green")
end
2025-08-06 12:21:15 +02:00
end
if affectedRows > 0 then
TriggerClientEvent('ox_lib:notify', src, {
title = 'Fahrzeugverwaltung',
description = 'Fahrzeug wurde repariert',
type = 'success'
})
else
TriggerClientEvent('ox_lib:notify', src, {
title = 'Fahrzeugverwaltung',
description = 'Fehler beim Reparieren des Fahrzeugs',
type = 'error'
})
end
end)
2025-08-06 11:48:14 +02:00
else
TriggerClientEvent('ox_lib:notify', src, {
title = 'Fahrzeugverwaltung',
2025-08-06 12:21:15 +02:00
description = 'Fahrzeug nicht gefunden',
2025-08-06 11:48:14 +02:00
type = 'error'
})
end
end)
end)
2025-08-06 12:37:47 +02:00
-- Discord Log Funktion
function sendToDiscord(title, message, color)
2025-08-06 12:45:18 +02:00
if not AdminConfig.Log or not AdminConfig.Log.Enabled or not AdminConfig.Log.Webhook then return end
2025-08-06 12:37:47 +02:00
local embed = {
{
["title"] = message,
["type"] = "rich",
2025-08-06 12:45:18 +02:00
["color"] = AdminConfig.Log.Colors[color] or AdminConfig.Log.Colors.blue,
2025-08-06 12:37:47 +02:00
["footer"] = {
2025-08-06 12:45:18 +02:00
["text"] = AdminConfig.Log.SystemName or "Fahrzeugadmin",
2025-08-06 12:37:47 +02:00
},
}
}
2025-08-06 12:45:18 +02:00
PerformHttpRequest(AdminConfig.Log.Webhook, function(err, text, headers)
2025-08-06 12:37:47 +02:00
if err and err ~= 204 and err ~= 200 then
print("Fehler beim Discord Webhook [" .. tostring(err) .. "]: " .. tostring(text))
end
end, 'POST', json.encode({
username = title .. " - System",
embeds = embed
}), { ['Content-Type'] = 'application/json' })
end
2025-08-06 10:11:58 +02:00
-- Command to open admin menu
QBCore.Commands.Add('vehicleadmin', 'Öffne Fahrzeug Admin Menu', {}, false, function(source, args)
local src = source
2025-08-06 11:48:14 +02:00
if not HasPermission(src) then
local Player = QBCore.Functions.GetPlayer(src)
local jobName = Player and Player.PlayerData.job.name or 'Unbekannt'
2025-08-06 10:11:58 +02:00
TriggerClientEvent('ox_lib:notify', src, {
title = 'Keine Berechtigung',
2025-08-06 11:48:14 +02:00
description = 'Dein Job (' .. jobName .. ') hat keine Berechtigung für dieses System',
2025-08-06 10:11:58 +02:00
type = 'error'
})
return
end
TriggerClientEvent('vehicleadmin:openMenu', src)
2025-08-06 11:48:14 +02:00
end)
-- Alternative command for police
QBCore.Commands.Add('policegarage', 'Öffne Polizei Fahrzeug Menu', {}, false, function(source, args)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if not Player or Player.PlayerData.job.name ~= 'police' then
TriggerClientEvent('ox_lib:notify', src, {
title = 'Keine Berechtigung',
description = 'Nur Polizisten können diesen Befehl verwenden',
type = 'error'
})
return
end
TriggerClientEvent('vehicleadmin:openMenu', src)
end)
-- Alternative command for mechanics
QBCore.Commands.Add('mechanicadmin', 'Öffne Mechaniker Fahrzeug Menu', {}, false, function(source, args)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if not Player or Player.PlayerData.job.name ~= 'mechanic' then
TriggerClientEvent('ox_lib:notify', src, {
title = 'Keine Berechtigung',
description = 'Nur Mechaniker können diesen Befehl verwenden',
type = 'error'
})
return
end
TriggerClientEvent('vehicleadmin:openMenu', src)
end)
-- Alternative command for ambulance
QBCore.Commands.Add('emsadmin', 'Öffne EMS Fahrzeug Menu', {}, false, function(source, args)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if not Player or Player.PlayerData.job.name ~= 'ambulance' then
TriggerClientEvent('ox_lib:notify', src, {
title = 'Keine Berechtigung',
description = 'Nur EMS können diesen Befehl verwenden',
type = 'error'
})
return
end
TriggerClientEvent('vehicleadmin:openMenu', src)
end)
-- Alternative command for cardealer
QBCore.Commands.Add('dealeradmin', 'Öffne Autohändler Fahrzeug Menu', {}, false, function(source, args)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if not Player or Player.PlayerData.job.name ~= 'cardealer' then
TriggerClientEvent('ox_lib:notify', src, {
title = 'Keine Berechtigung',
description = 'Nur Autohändler können diesen Befehl verwenden',
type = 'error'
})
return
end
TriggerClientEvent('vehicleadmin:openMenu', src)
end)
2025-08-06 12:45:18 +02:00
2025-08-06 13:29:54 +02:00
-- Lade die Garagen aus dem Garagensystem
2025-08-06 12:45:18 +02:00
Citizen.CreateThread(function()
2025-08-06 13:29:54 +02:00
Wait(1000) -- Warte kurz, damit das Hauptsystem geladen ist
2025-08-06 12:45:18 +02:00
-- Versuche, die Garagen aus dem Hauptsystem zu laden
if _G.Config and _G.Config.Zonen then
2025-08-06 13:29:54 +02:00
for k, v in pairs(_G.Config.Zonen) do
table.insert(ExternalGarages, v)
end
print("[Fahrzeugadmin] Garagen aus dem Hauptsystem geladen: " .. #ExternalGarages .. " Garagen gefunden.")
else
print("[Fahrzeugadmin] Konnte keine Garagen aus dem Hauptsystem laden, versuche es später erneut.")
end
end)
-- Versuche erneut, die Garagen zu laden, falls sie beim ersten Mal nicht verfügbar waren
Citizen.CreateThread(function()
Wait(5000) -- Warte länger, damit das Hauptsystem sicher geladen ist
if #ExternalGarages == 0 and _G.Config and _G.Config.Zonen then
for k, v in pairs(_G.Config.Zonen) do
table.insert(ExternalGarages, v)
end
2025-08-06 12:45:18 +02:00
print("[Fahrzeugadmin] Garagen aus dem Hauptsystem nachgeladen: " .. #ExternalGarages .. " Garagen gefunden.")
end
end)