forked from Simnation/Main
ed
This commit is contained in:
parent
187f3ee8ff
commit
07aee0f73e
2 changed files with 377 additions and 120 deletions
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue