From 259e1eb56f267621ee6335ab90219377eb723e22 Mon Sep 17 00:00:00 2001 From: Nordi98 Date: Wed, 6 Aug 2025 10:11:58 +0200 Subject: [PATCH] ed --- .../[carscripts]/nordi_car_admin/client.lua | 165 +++++++++++++++ .../nordi_car_admin/fxmanifest.lua | 25 +++ .../[carscripts]/nordi_car_admin/server.lua | 194 ++++++++++++++++++ 3 files changed, 384 insertions(+) create mode 100644 resources/[carscripts]/nordi_car_admin/client.lua create mode 100644 resources/[carscripts]/nordi_car_admin/fxmanifest.lua create mode 100644 resources/[carscripts]/nordi_car_admin/server.lua diff --git a/resources/[carscripts]/nordi_car_admin/client.lua b/resources/[carscripts]/nordi_car_admin/client.lua new file mode 100644 index 000000000..05029e914 --- /dev/null +++ b/resources/[carscripts]/nordi_car_admin/client.lua @@ -0,0 +1,165 @@ +local QBCore = exports['qb-core']:GetCoreObject() + +-- Get vehicle state text +local function GetStateText(state) + if state == 0 then + return "Ausgefahren" + elseif state == 1 then + return "In Garage" + elseif state == 2 then + return "Beschlagnahmt" + else + return "Unbekannt" + end +end + +-- Get vehicle condition text +local function GetConditionText(value) + if value >= 900 then + return "Sehr gut" + elseif value >= 700 then + return "Gut" + elseif value >= 500 then + return "Mittelmäßig" + elseif value >= 300 then + return "Schlecht" + else + return "Sehr schlecht" + end +end + +-- Show vehicle actions menu +local function ShowVehicleActions(vehicle) + QBCore.Functions.TriggerCallback('vehicleadmin:getGarages', function(garages) + if not garages then return end + + local garageOptions = {} + for i = 1, #garages do + table.insert(garageOptions, { + value = garages[i].name, + label = garages[i].label + }) + end + + local input = lib.inputDialog('Fahrzeug Aktionen - ' .. vehicle.plate, { + { + type = 'select', + label = 'Aktion wählen', + options = { + {value = 'move', label = 'In Garage stellen'}, + {value = 'delete', label = 'Von Map löschen'}, + {value = 'repair', label = 'Reparieren'} + }, + required = true + }, + { + type = 'select', + label = 'Garage auswählen (nur für "In Garage stellen")', + options = garageOptions, + required = false + } + }) + + if input then + local action = input[1] + local garage = input[2] + + if action == 'move' then + if not garage then + lib.notify({ + title = 'Fehler', + description = 'Bitte wähle eine Garage aus', + type = 'error' + }) + return + end + TriggerServerEvent('vehicleadmin:moveToGarage', vehicle.plate, garage) + elseif action == 'delete' then + TriggerServerEvent('vehicleadmin:deleteFromMap', vehicle.plate) + elseif action == 'repair' then + TriggerServerEvent('vehicleadmin:repairVehicle', vehicle.plate) + end + end + end) +end + +-- Show vehicles for selected player +local function ShowPlayerVehicles(citizenid, playerName) + QBCore.Functions.TriggerCallback('vehicleadmin:getPlayerVehicles', function(vehicles) + if not vehicles then return end + + if #vehicles == 0 then + lib.notify({ + title = 'Keine Fahrzeuge', + description = 'Dieser Spieler hat keine Fahrzeuge', + type = 'info' + }) + return + end + + local options = {} + for i = 1, #vehicles do + local vehicle = vehicles[i] + local vehicleLabel = QBCore.Shared.Vehicles[vehicle.vehicle]?.name or vehicle.vehicle + + table.insert(options, { + title = vehicleLabel .. ' (' .. vehicle.plate .. ')', + description = 'Zustand: ' .. GetStateText(vehicle.state) .. ' | Garage: ' .. (vehicle.garage or 'Keine') .. + '\nMotor: ' .. GetConditionText(vehicle.engine) .. ' | Karosserie: ' .. GetConditionText(vehicle.body) .. + '\nSprit: ' .. math.floor(vehicle.fuel) .. '%', + icon = 'car', + onSelect = function() + ShowVehicleActions(vehicle) + end + }) + end + + lib.registerContext({ + id = 'vehicle_list', + title = 'Fahrzeuge von ' .. playerName, + options = options + }) + + lib.showContext('vehicle_list') + end, citizenid) +end + +-- Show player selection menu +local function ShowPlayerMenu() + QBCore.Functions.TriggerCallback('vehicleadmin:getPlayers', function(players) + if not players then + lib.notify({ + title = 'Fehler', + description = 'Keine Berechtigung oder Fehler beim Laden', + type = 'error' + }) + return + end + + local options = {} + for i = 1, #players do + local player = players[i] + table.insert(options, { + title = player.name, + description = 'Citizen ID: ' .. player.citizenid, + icon = 'user', + onSelect = function() + ShowPlayerVehicles(player.citizenid, player.name) + end + }) + end + + lib.registerContext({ + id = 'player_selection', + title = 'Spieler auswählen', + options = options + }) + + lib.showContext('player_selection') + end) +end + +-- Event to open main menu +RegisterNetEvent('vehicleadmin:openMenu', function() + ShowPlayerMenu() +end) diff --git a/resources/[carscripts]/nordi_car_admin/fxmanifest.lua b/resources/[carscripts]/nordi_car_admin/fxmanifest.lua new file mode 100644 index 000000000..0ff3570e7 --- /dev/null +++ b/resources/[carscripts]/nordi_car_admin/fxmanifest.lua @@ -0,0 +1,25 @@ +fx_version 'cerulean' +game 'gta5' + +author 'YourName' +description 'Vehicle Admin Script for QBCore' +version '1.0.0' + +shared_scripts { + '@ox_lib/init.lua' +} + +client_scripts { + 'client.lua' +} + +server_scripts { + '@oxmysql/lib/MySQL.lua', + 'server.lua' +} + +dependencies { + 'qb-core', + 'ox_lib', + 'oxmysql' +} diff --git a/resources/[carscripts]/nordi_car_admin/server.lua b/resources/[carscripts]/nordi_car_admin/server.lua new file mode 100644 index 000000000..98ba641f4 --- /dev/null +++ b/resources/[carscripts]/nordi_car_admin/server.lua @@ -0,0 +1,194 @@ +local QBCore = exports['qb-core']:GetCoreObject() + +-- Admin Permission Check +local function IsAdmin(source) + local Player = QBCore.Functions.GetPlayer(source) + if not Player then return false end + return QBCore.Functions.HasPermission(source, 'admin') or Player.PlayerData.job.name == 'admin' +end + +-- Get all players from database +QBCore.Functions.CreateCallback('vehicleadmin:getPlayers', function(source, cb) + if not IsAdmin(source) then + cb(false) + return + end + + MySQL.Async.fetchAll('SELECT citizenid, charinfo FROM players ORDER BY charinfo', {}, function(result) + local players = {} + for i = 1, #result do + local charinfo = json.decode(result[i].charinfo) + table.insert(players, { + citizenid = result[i].citizenid, + name = charinfo.firstname .. ' ' .. charinfo.lastname + }) + end + cb(players) + end) +end) + +-- Get vehicles for specific player +QBCore.Functions.CreateCallback('vehicleadmin:getPlayerVehicles', function(source, cb, citizenid) + if not IsAdmin(source) then + cb(false) + return + end + + MySQL.Async.fetchAll('SELECT * FROM player_vehicles WHERE citizenid = ?', {citizenid}, function(result) + local vehicles = {} + for i = 1, #result do + local vehicle = result[i] + local vehicleData = json.decode(vehicle.mods) + + table.insert(vehicles, { + plate = vehicle.plate, + vehicle = vehicle.vehicle, + garage = vehicle.garage, + state = vehicle.state, + fuel = vehicle.fuel, + engine = vehicle.engine, + body = vehicle.body, + citizenid = vehicle.citizenid, + depotprice = vehicle.depotprice, + drivingdistance = vehicle.drivingdistance + }) + end + cb(vehicles) + end) +end) + +-- Get all garages +QBCore.Functions.CreateCallback('vehicleadmin:getGarages', function(source, cb) + if not IsAdmin(source) then + cb(false) + return + end + + local garages = {} + for garageName, garageData in pairs(QBCore.Shared.Garages) do + table.insert(garages, { + name = garageName, + label = garageData.label or garageName + }) + end + cb(garages) +end) + +-- Move vehicle to garage +RegisterNetEvent('vehicleadmin:moveToGarage', function(plate, garage) + local src = source + if not IsAdmin(src) then return end + + -- Delete vehicle from world if it exists + local vehicles = GetAllVehicles() + for i = 1, #vehicles do + local veh = vehicles[i] + local vehPlate = GetVehicleNumberPlateText(veh):gsub("%s+", "") + if vehPlate == plate:gsub("%s+", "") then + DeleteEntity(veh) + break + end + end + + -- Update database + MySQL.Async.execute('UPDATE player_vehicles SET state = ?, garage = ? WHERE plate = ?', {1, garage, plate}, function(affectedRows) + if affectedRows > 0 then + 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 + if not IsAdmin(src) then return end + + local vehicles = GetAllVehicles() + local deleted = false + + for i = 1, #vehicles do + local veh = vehicles[i] + local vehPlate = GetVehicleNumberPlateText(veh):gsub("%s+", "") + if vehPlate == plate:gsub("%s+", "") then + DeleteEntity(veh) + deleted = true + break + end + end + + 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', + type = 'error' + }) + end +end) + +-- Repair vehicle +RegisterNetEvent('vehicleadmin:repairVehicle', function(plate) + local src = source + if not IsAdmin(src) then return end + + -- Update database + MySQL.Async.execute('UPDATE player_vehicles SET engine = ?, body = ? WHERE plate = ?', {1000, 1000, plate}, function(affectedRows) + -- Also repair if vehicle is on map + local vehicles = GetAllVehicles() + for i = 1, #vehicles do + local veh = vehicles[i] + local vehPlate = GetVehicleNumberPlateText(veh):gsub("%s+", "") + if vehPlate == plate:gsub("%s+", "") then + SetVehicleFixed(veh) + SetVehicleDeformationFixed(veh) + SetVehicleUndriveable(veh, false) + SetVehicleEngineOn(veh, true, true) + break + end + 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) +end) + +-- Command to open admin menu +QBCore.Commands.Add('vehicleadmin', 'Öffne Fahrzeug Admin Menu', {}, false, function(source, args) + local src = source + if not IsAdmin(src) then + TriggerClientEvent('ox_lib:notify', src, { + title = 'Keine Berechtigung', + description = 'Du hast keine Admin-Rechte', + type = 'error' + }) + return + end + + TriggerClientEvent('vehicleadmin:openMenu', src) +end, 'admin')