1
0
Fork 0
forked from Simnation/Main
This commit is contained in:
Nordi98 2025-08-07 14:00:58 +02:00
parent 187f3ee8ff
commit 07aee0f73e
2 changed files with 377 additions and 120 deletions

View file

@ -4,6 +4,7 @@ local lastKnownCoords = {}
local garagePending = {} -- Fahrzeuge, die gerade in die Garage gestellt werden
local spawnedVehicles = {} -- Track recently spawned vehicles to prevent duplication
local vehicleOwnership = {} -- Cache vehicle ownership status
local vehicleExistsCallbacks = {} -- Callbacks for vehicle existence checks
-- Helper function to count table entries
function tableLength(T)
@ -19,6 +20,44 @@ local function Debug(msg)
end
end
-- Function to check if a vehicle is a temporary/special vehicle (like police cars, ambulances, etc.)
local function IsTemporaryVehicle(vehicle)
local plate = QBCore.Functions.GetPlate(vehicle)
-- Check for common temporary vehicle patterns
if not plate or plate == "" then return true end
-- Some servers use specific patterns for temporary vehicles
if string.match(plate, "^TEMP%d%d%d%d%d$") then return true end
if string.match(plate, "^[A-Z][A-Z][A-Z][A-Z]%d%d%d$") and GetEntityModel(vehicle) == GetHashKey("police") then return true end
-- Add more patterns as needed for your server
return false
end
-- Function to check if a vehicle might be a job vehicle
local function IsLikelyJobVehicle(vehicle)
local model = GetEntityModel(vehicle)
-- List of common job vehicle models
local jobVehicles = {
"police", "police2", "police3", "police4",
"ambulance", "firetruk",
"taxi",
"flatbed", "towtruck", "towtruck2",
-- Add more as needed
}
for _, jobVehicle in ipairs(jobVehicles) do
if model == GetHashKey(jobVehicle) then
return true
end
end
return false
end
-- Anti-Duplication: Check if a vehicle with this plate already exists in the world
local function DoesVehicleExistInWorld(plate)
local vehicles = GetGamePool('CVehicle')
@ -114,6 +153,28 @@ local function DoesPlayerOwnVehicle(plate)
return isOwned == true
end
-- Function to check if a vehicle exists in the database
local function CheckVehicleExists(plate, callback)
vehicleExistsCallbacks[plate] = callback
TriggerServerEvent('antidespawn:server:checkVehicleExists', plate)
-- Set a timeout to clean up the callback if no response is received
SetTimeout(5000, function()
if vehicleExistsCallbacks[plate] then
vehicleExistsCallbacks[plate](false) -- Assume it doesn't exist if no response
vehicleExistsCallbacks[plate] = nil
end
end)
end
-- Register the event handler for vehicle existence check
RegisterNetEvent('antidespawn:client:vehicleExistsResult', function(exists, plate)
if vehicleExistsCallbacks[plate] then
vehicleExistsCallbacks[plate](exists)
vehicleExistsCallbacks[plate] = nil
end
end)
-- Funktion um zu prüfen ob Fahrzeugklasse erlaubt ist
local function IsVehicleClassAllowed(vehicle)
local vehicleClass = GetVehicleClass(vehicle)
@ -388,6 +449,24 @@ CreateThread(function()
goto continue
end
-- Skip temporary vehicles
if IsTemporaryVehicle(currentVehicle) then
Debug("Skipping temporary vehicle")
goto continue
end
-- Skip likely job vehicles
if IsLikelyJobVehicle(currentVehicle) then
Debug("Skipping likely job vehicle")
goto continue
end
-- Skip recently spawned vehicles
if WasVehicleRecentlySpawned(plate) then
Debug("Skipping recently spawned vehicle: " .. plate)
goto continue
end
-- Anti-Duplication: Check if this plate already exists multiple times
if DoesVehicleExistInWorld(plate) then
Debug("Anti-Dupe: Detected duplicate vehicle with plate " .. plate .. ", not tracking")
@ -397,7 +476,7 @@ CreateThread(function()
-- Check if this vehicle is already being tracked
if not trackedVehicles[plate] and not garagePending[plate] then
-- First verify this vehicle exists in the database
TriggerServerEvent('antidespawn:server:checkVehicleExists', plate, function(exists)
CheckVehicleExists(plate, function(exists)
if not exists then
Debug("Vehicle not in database, not tracking: " .. plate)
return
@ -492,6 +571,15 @@ CreateThread(function()
goto continue
end
-- Verify this vehicle still exists in the database before respawning
CheckVehicleExists(plate, function(exists)
if not exists then
Debug("Vehicle no longer in database, not respawning: " .. plate)
trackedVehicles[plate] = nil
lastKnownCoords[plate] = nil
return
end
-- Versuche Fahrzeug wiederherzustellen, aber nur wenn es nicht in die Garage gestellt wird
if lastKnownCoords[plate] and not garagePending[plate] then
Debug("Versuche Fahrzeug wiederherzustellen: " .. plate)
@ -505,6 +593,7 @@ CreateThread(function()
trackedVehicles[plate] = nil
lastKnownCoords[plate] = nil
end
end)
end
::continue::
end
@ -548,6 +637,12 @@ end)
RegisterNetEvent('antidespawn:client:spawnVehicle', function(data)
Debug("Spawne Fahrzeug: " .. data.plate)
-- Skip vehicles with empty or invalid plates
if not data.plate or data.plate == "" or string.len(data.plate) < 2 then
Debug("Skipping spawn of vehicle with invalid plate")
return
end
-- Anti-Duplication: Check if vehicle was recently spawned
if WasVehicleRecentlySpawned(data.plate) then
Debug("Anti-Dupe: Blocking respawn of recently spawned vehicle: " .. data.plate)
@ -570,8 +665,12 @@ RegisterNetEvent('antidespawn:client:spawnVehicle', function(data)
return
end
-- Allow spawning of all vehicles, not just owned ones
-- No ownership check here
-- Verify this vehicle exists in the database before spawning
CheckVehicleExists(data.plate, function(exists)
if not exists then
Debug("Vehicle not in database, not spawning: " .. data.plate)
return
end
-- Konvertiere Modell zu Hash wenn nötig
local modelHash = data.model
@ -661,10 +760,13 @@ RegisterNetEvent('antidespawn:client:spawnVehicle', function(data)
end
SetModelAsNoLongerNeeded(modelHash)
else
Debug("Modell konnte nicht geladen werden: " ..
else
Debug("Modell konnte nicht geladen werden: " .. data.plate .. " (Hash: " .. tostring(modelHash) .. ")")
end
end)
end)
-- Event für Garage Store (wird ausgelöst, wenn der Spieler ein Fahrzeug in die Garage stellen will)
RegisterNetEvent('jg-advancedgarages:client:store-vehicle', function(garageId, garageVehicleType)
@ -674,6 +776,12 @@ RegisterNetEvent('jg-advancedgarages:client:store-vehicle', function(garageId, g
if vehicle ~= 0 then
local plate = QBCore.Functions.GetPlate(vehicle)
-- Skip vehicles with empty or invalid plates
if not plate or plate == "" or string.len(plate) < 2 then
Debug("Skipping garage storage for vehicle with invalid plate")
return
end
-- Markiere Fahrzeug als "wird in Garage gestellt"
garagePending[plate] = true
SetTimeout(10000, function()
@ -695,6 +803,12 @@ end)
-- jg-advanced-garage Events
RegisterNetEvent('jg-advancedgarages:client:vehicle-stored', function(data)
if data and data.plate then
-- Skip vehicles with empty or invalid plates
if not data.plate or data.plate == "" or string.len(data.plate) < 2 then
Debug("Skipping garage storage completion for vehicle with invalid plate")
return
end
-- Markiere Fahrzeug als "in Garage"
garagePending[data.plate] = nil
@ -713,6 +827,12 @@ end)
RegisterNetEvent('jg-advancedgarages:client:vehicle-spawned', function(data)
if data and data.plate then
-- Skip vehicles with empty or invalid plates
if not data.plate or data.plate == "" or string.len(data.plate) < 2 then
Debug("Skipping garage spawn completion for vehicle with invalid plate")
return
end
-- Entferne Markierung "in Garage"
garagePending[data.plate] = nil
@ -758,6 +878,24 @@ RegisterCommand('fixvehicle', function()
if vehicle ~= 0 then
local plate = QBCore.Functions.GetPlate(vehicle)
-- Skip vehicles with empty or invalid plates
if not plate or plate == "" or string.len(plate) < 2 then
Debug("Cannot fix vehicle with invalid plate")
return
end
-- Skip temporary vehicles
if IsTemporaryVehicle(vehicle) then
Debug("Cannot fix temporary vehicle")
return
end
-- Skip likely job vehicles
if IsLikelyJobVehicle(vehicle) then
Debug("Cannot fix likely job vehicle")
return
end
-- Anti-Duplication: Check if this plate already exists multiple times
if DoesVehicleExistInWorld(plate) then
Debug("Anti-Dupe: Detected duplicate vehicle with plate " .. plate .. ", not fixing")
@ -766,7 +904,13 @@ RegisterCommand('fixvehicle', function()
-- Prüfe ob Fahrzeug gerade in die Garage gestellt wird
if not garagePending[plate] then
-- Track all vehicles, regardless of ownership
-- Verify this vehicle exists in the database
CheckVehicleExists(plate, function(exists)
if not exists then
Debug("Vehicle not in database, cannot fix: " .. plate)
return
end
PreventDespawn(vehicle)
trackedVehicles[plate] = vehicle
lastKnownCoords[plate] = GetEntityCoords(vehicle)
@ -780,6 +924,7 @@ RegisterCommand('fixvehicle', function()
TriggerServerEvent('antidespawn:server:registerVehicle', plate, vehicleModel, vehicleCoords, vehicleHeading, vehicleMods)
Debug("Anti-Despawn für Fahrzeug aktiviert: " .. plate)
end)
else
Debug("Fahrzeug wird gerade in Garage gestellt, kann nicht fixiert werden: " .. plate)
end
@ -802,6 +947,7 @@ AddEventHandler('onResourceStop', function(resourceName)
garagePending = {}
spawnedVehicles = {}
vehicleOwnership = {}
vehicleExistsCallbacks = {}
end
end)
@ -813,6 +959,7 @@ RegisterCommand('checkdupes', function()
for _, vehicle in pairs(vehicles) do
local plate = QBCore.Functions.GetPlate(vehicle)
if plate and plate ~= "" then
if plates[plate] then
if not dupes[plate] then
dupes[plate] = 2
@ -823,6 +970,7 @@ RegisterCommand('checkdupes', function()
plates[plate] = true
end
end
end
local dupeCount = 0
for plate, count in pairs(dupes) do
@ -849,3 +997,35 @@ RegisterCommand('clearownership', function()
Debug("Cleared vehicle ownership cache")
end, false)
-- Debug command to list all tracked vehicles
RegisterCommand('listtracked', function()
local count = 0
Debug("Currently tracked vehicles:")
for plate, _ in pairs(trackedVehicles) do
Debug("- " .. plate)
count = count + 1
end
Debug("Total tracked vehicles: " .. count)
end, false)
-- Debug command to delete duplicate vehicles
RegisterCommand('deletedupes', function()
local vehicles = GetGamePool('CVehicle')
local plates = {}
local deleted = 0
for _, vehicle in pairs(vehicles) do
local plate = QBCore.Functions.GetPlate(vehicle)
if plate and plate ~= "" then
if plates[plate] then
DeleteEntity(vehicle)
deleted = deleted + 1
Debug("Deleted duplicate vehicle with plate: " .. plate)
else
plates[plate] = true
end
end
end
Debug("Deleted " .. deleted .. " duplicate vehicles")
end, false)

View file

@ -77,6 +77,22 @@ CreateThread(function()
end)
end)
-- Check if a vehicle exists in the database
RegisterNetEvent('antidespawn:server:checkVehicleExists', function(plate)
local src = source
-- Skip vehicles with empty or invalid plates
if not plate or plate == "" or string.len(plate) < 2 then
TriggerClientEvent('antidespawn:client:vehicleExistsResult', src, false, plate)
return
end
MySQL.query('SELECT * FROM player_vehicles WHERE plate = ?', {plate}, function(result)
local exists = result and #result > 0
TriggerClientEvent('antidespawn:client:vehicleExistsResult', src, exists, plate)
end)
end)
-- Check if a player owns a vehicle
RegisterNetEvent('antidespawn:server:checkVehicleOwnership', function(plate)
local src = source
@ -87,6 +103,12 @@ RegisterNetEvent('antidespawn:server:checkVehicleOwnership', function(plate)
return
end
-- Skip vehicles with empty or invalid plates
if not plate or plate == "" or string.len(plate) < 2 then
TriggerClientEvent('antidespawn:client:vehicleOwnershipResult', src, false, plate)
return
end
MySQL.query('SELECT * FROM player_vehicles WHERE plate = ? AND citizenid = ?', {plate, Player.PlayerData.citizenid}, function(result)
local isOwned = result and #result > 0
TriggerClientEvent('antidespawn:client:vehicleOwnershipResult', src, isOwned, plate)
@ -100,6 +122,12 @@ RegisterNetEvent('antidespawn:server:registerVehicle', function(plate, model, co
if not Player then return end
-- Skip vehicles with empty or invalid plates
if not plate or plate == "" or string.len(plate) < 2 then
Debug("Skipping vehicle with invalid plate")
return
end
-- Check if vehicle exists in player_vehicles (any player)
MySQL.query('SELECT * FROM player_vehicles WHERE plate = ?', {plate}, function(result)
if not result or #result == 0 then
@ -163,10 +191,19 @@ RegisterNetEvent('antidespawn:server:updateVehicle', function(plate, coords, hea
if not Player then return end
if not vehicles[plate] then return end
-- Skip vehicles with empty or invalid plates
if not plate or plate == "" or string.len(plate) < 2 then
Debug("Skipping update for vehicle with invalid plate")
return
end
-- Check if vehicle exists in player_vehicles (any player)
MySQL.query('SELECT * FROM player_vehicles WHERE plate = ?', {plate}, function(result)
if not result or #result == 0 then
Debug("Vehicle not found in database: " .. plate)
-- Remove from tracking as it no longer exists in the database
vehicles[plate] = nil
MySQL.query("DELETE FROM vehicle_antidespawn WHERE plate = ?", {plate})
return
end
@ -210,6 +247,12 @@ RegisterNetEvent('antidespawn:server:removeVehicle', function(plate)
local src = source
if not vehicles[plate] then return end
-- Skip vehicles with empty or invalid plates
if not plate or plate == "" or string.len(plate) < 2 then
Debug("Skipping removal for vehicle with invalid plate")
return
end
vehicles[plate] = nil
MySQL.query("DELETE FROM vehicle_antidespawn WHERE plate = ?", {
@ -226,6 +269,12 @@ RegisterNetEvent('antidespawn:server:respawnVehicle', function(plate)
if not Player then return end
-- Skip vehicles with empty or invalid plates
if not plate or plate == "" or string.len(plate) < 2 then
Debug("Skipping respawn for vehicle with invalid plate")
return
end
-- Anti-Duplication: Check if there's already an active spawn request for this plate
if activeSpawns[plate] then
Debug("Anti-Dupe: Already processing spawn request for: " .. plate)
@ -305,6 +354,14 @@ RegisterNetEvent('antidespawn:server:loadVehicles', function()
-- Load all vehicles in the database, not just owned ones
for plate, vehicle in pairs(vehicles) do
-- Skip vehicles with empty or invalid plates
if not plate or plate == "" or string.len(plate) < 2 then
Debug("Skipping load for vehicle with invalid plate")
vehicles[plate] = nil
MySQL.query("DELETE FROM vehicle_antidespawn WHERE plate = ?", {plate})
goto continue
end
-- Check if vehicle is in garage by querying the database
MySQL.query('SELECT * FROM player_vehicles WHERE plate = ?', {plate}, function(result)
if not result or #result == 0 then
@ -354,6 +411,7 @@ RegisterNetEvent('antidespawn:server:loadVehicles', function()
loadedCount = loadedCount + 1
end
end)
::continue::
end
-- Warte kurz und lade dann die Fahrzeuge
@ -379,6 +437,7 @@ RegisterNetEvent('antidespawn:server:loadVehicles', function()
end)
end)
-- Cleanup alte Einträge (älter als 24 Stunden)
CreateThread(function()
while true do
@ -511,6 +570,24 @@ RegisterCommand('activespawns', function(source, args, rawCommand)
end
end, true)
-- Check if a vehicle exists in the database
RegisterNetEvent('antidespawn:server:checkVehicleExists', function(plate, callback)
local src = source
MySQL.query('SELECT * FROM player_vehicles WHERE plate = ?', {plate}, function(result)
local exists = result and #result > 0
TriggerClientEvent('antidespawn:client:vehicleExistsResult', src, exists, plate)
end)
end)
-- Client callback for vehicle existence check
RegisterNetEvent('antidespawn:client:vehicleExistsResult', function(exists, plate)
-- This event will be handled by the callback system
end)
-- Clean up when resource stops
AddEventHandler('onResourceStop', function(resourceName)
if resourceName == GetCurrentResourceName() then