forked from Simnation/Main
598 lines
22 KiB
Lua
598 lines
22 KiB
Lua
local QBCore = exports['qb-core']:GetCoreObject()
|
|
local vehicles = {}
|
|
local activeSpawns = {} -- Track active spawn requests to prevent duplicates
|
|
|
|
-- Debug Funktion
|
|
local function Debug(msg)
|
|
if Config.Debug then
|
|
print("[AntiDespawn] " .. msg)
|
|
end
|
|
end
|
|
|
|
-- Erstelle Tabelle bei Serverstart
|
|
CreateThread(function()
|
|
-- Prüfe ob die Tabelle existiert
|
|
MySQL.query("SHOW TABLES LIKE 'vehicle_antidespawn'", {}, function(result)
|
|
if result and #result > 0 then
|
|
-- Tabelle existiert, prüfe ob das mods-Feld existiert
|
|
MySQL.query("SHOW COLUMNS FROM vehicle_antidespawn LIKE 'mods'", {}, function(columns)
|
|
if columns and #columns == 0 then
|
|
-- mods-Feld existiert nicht, füge es hinzu
|
|
Debug("Füge mods-Feld zur Tabelle hinzu...")
|
|
MySQL.query("ALTER TABLE vehicle_antidespawn ADD COLUMN mods LONGTEXT DEFAULT NULL", {})
|
|
end
|
|
end)
|
|
|
|
-- Prüfe ob das owner-Feld existiert
|
|
MySQL.query("SHOW COLUMNS FROM vehicle_antidespawn LIKE 'owner'", {}, function(columns)
|
|
if columns and #columns == 0 then
|
|
-- owner-Feld existiert nicht, füge es hinzu
|
|
Debug("Füge owner-Feld zur Tabelle hinzu...")
|
|
MySQL.query("ALTER TABLE vehicle_antidespawn ADD COLUMN owner VARCHAR(50) DEFAULT NULL", {})
|
|
end
|
|
end)
|
|
else
|
|
-- Tabelle existiert nicht, erstelle sie
|
|
Debug("Erstelle Datenbank-Tabelle...")
|
|
MySQL.query([[
|
|
CREATE TABLE IF NOT EXISTS `vehicle_antidespawn` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`plate` varchar(50) NOT NULL,
|
|
`model` varchar(50) NOT NULL,
|
|
`coords` longtext NOT NULL,
|
|
`heading` float NOT NULL,
|
|
`fuel` int(11) DEFAULT 100,
|
|
`mods` longtext DEFAULT NULL,
|
|
`owner` varchar(50) DEFAULT NULL,
|
|
`last_updated` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `plate` (`plate`)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
]])
|
|
end
|
|
end)
|
|
|
|
Debug("Datenbank initialisiert")
|
|
|
|
-- Warte kurz, bis die Tabelle aktualisiert wurde
|
|
Wait(1000)
|
|
|
|
-- Lade alle Fahrzeuge aus der Datenbank
|
|
MySQL.query("SELECT * FROM vehicle_antidespawn", {}, function(results)
|
|
if results and #results > 0 then
|
|
Debug("Lade " .. #results .. " Fahrzeuge aus der Datenbank")
|
|
|
|
for _, vehicle in pairs(results) do
|
|
vehicles[vehicle.plate] = {
|
|
model = vehicle.model,
|
|
coords = json.decode(vehicle.coords),
|
|
heading = vehicle.heading,
|
|
fuel = vehicle.fuel,
|
|
mods = vehicle.mods and json.decode(vehicle.mods) or nil,
|
|
owner = vehicle.owner,
|
|
last_updated = vehicle.last_updated
|
|
}
|
|
end
|
|
end
|
|
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
|
|
local Player = QBCore.Functions.GetPlayer(src)
|
|
|
|
if not Player then
|
|
TriggerClientEvent('antidespawn:client:vehicleOwnershipResult', src, false, 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)
|
|
end)
|
|
end)
|
|
|
|
-- Register a vehicle (track all vehicles, regardless of ownership)
|
|
RegisterNetEvent('antidespawn:server:registerVehicle', function(plate, model, coords, heading, mods)
|
|
local src = source
|
|
local Player = QBCore.Functions.GetPlayer(src)
|
|
|
|
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
|
|
Debug("Vehicle not found in database: " .. plate)
|
|
return
|
|
end
|
|
|
|
-- Check if vehicle is in garage
|
|
local inGarage = false
|
|
local ownerId = nil
|
|
|
|
for _, veh in ipairs(result) do
|
|
if veh.state == 1 then
|
|
inGarage = true
|
|
end
|
|
ownerId = veh.citizenid -- Store the owner ID
|
|
end
|
|
|
|
if inGarage then
|
|
Debug("Fahrzeug ist in der Garage, nicht registrieren: " .. plate)
|
|
|
|
-- Remove from Anti-Despawn database if present
|
|
if vehicles[plate] then
|
|
vehicles[plate] = nil
|
|
MySQL.query("DELETE FROM vehicle_antidespawn WHERE plate = ?", {plate})
|
|
Debug("Fahrzeug aus Anti-Despawn entfernt: " .. plate)
|
|
end
|
|
return
|
|
end
|
|
|
|
-- Continue with registration as before
|
|
vehicles[plate] = {
|
|
model = model,
|
|
coords = coords,
|
|
heading = heading,
|
|
fuel = 100,
|
|
mods = mods,
|
|
owner = ownerId,
|
|
last_updated = os.time()
|
|
}
|
|
|
|
MySQL.query("INSERT INTO vehicle_antidespawn (plate, model, coords, heading, fuel, mods, owner) VALUES (?, ?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE coords = VALUES(coords), heading = VALUES(heading), mods = VALUES(mods), owner = VALUES(owner), last_updated = CURRENT_TIMESTAMP", {
|
|
plate,
|
|
tostring(model),
|
|
json.encode(coords),
|
|
heading,
|
|
100,
|
|
json.encode(mods),
|
|
ownerId
|
|
})
|
|
|
|
Debug("Fahrzeug registriert: " .. plate .. " (Modell: " .. tostring(model) .. ", Besitzer: " .. tostring(ownerId) .. ")")
|
|
end)
|
|
end)
|
|
|
|
-- Update a vehicle
|
|
RegisterNetEvent('antidespawn:server:updateVehicle', function(plate, coords, heading, mods)
|
|
local src = source
|
|
local Player = QBCore.Functions.GetPlayer(src)
|
|
|
|
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
|
|
|
|
-- Check if vehicle is in garage
|
|
local inGarage = false
|
|
for _, veh in ipairs(result) do
|
|
if veh.state == 1 then
|
|
inGarage = true
|
|
break
|
|
end
|
|
end
|
|
|
|
if inGarage then
|
|
Debug("Fahrzeug ist in der Garage, entferne aus Tracking: " .. plate)
|
|
vehicles[plate] = nil
|
|
|
|
MySQL.query("DELETE FROM vehicle_antidespawn WHERE plate = ?", {
|
|
plate
|
|
})
|
|
return
|
|
end
|
|
|
|
vehicles[plate].coords = coords
|
|
vehicles[plate].heading = heading
|
|
vehicles[plate].mods = mods
|
|
vehicles[plate].last_updated = os.time()
|
|
|
|
MySQL.query("UPDATE vehicle_antidespawn SET coords = ?, heading = ?, mods = ?, last_updated = CURRENT_TIMESTAMP WHERE plate = ?", {
|
|
json.encode(coords),
|
|
heading,
|
|
json.encode(mods),
|
|
plate
|
|
})
|
|
|
|
Debug("Fahrzeug aktualisiert: " .. plate)
|
|
end)
|
|
end)
|
|
|
|
-- Remove a vehicle
|
|
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 = ?", {
|
|
plate
|
|
})
|
|
|
|
Debug("Fahrzeug entfernt: " .. plate)
|
|
end)
|
|
|
|
-- Respawn a vehicle (allow respawning any tracked vehicle)
|
|
RegisterNetEvent('antidespawn:server:respawnVehicle', function(plate)
|
|
local src = source
|
|
local Player = QBCore.Functions.GetPlayer(src)
|
|
|
|
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)
|
|
return
|
|
end
|
|
|
|
-- Mark as active spawn
|
|
activeSpawns[plate] = true
|
|
|
|
-- Set a timeout to clear the active spawn status
|
|
SetTimeout(10000, function()
|
|
activeSpawns[plate] = nil
|
|
end)
|
|
|
|
-- Check if vehicle exists in database (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)
|
|
activeSpawns[plate] = nil
|
|
return
|
|
end
|
|
|
|
if not vehicles[plate] then
|
|
Debug("Fahrzeug nicht in Datenbank: " .. plate)
|
|
activeSpawns[plate] = nil
|
|
return
|
|
end
|
|
|
|
-- Check if vehicle is in garage
|
|
local inGarage = false
|
|
for _, veh in ipairs(result) do
|
|
if veh.state == 1 then
|
|
inGarage = true
|
|
break
|
|
end
|
|
end
|
|
|
|
if inGarage then
|
|
Debug("Fahrzeug ist in der Garage, nicht respawnen: " .. plate)
|
|
|
|
-- Remove from Anti-Despawn database
|
|
vehicles[plate] = nil
|
|
MySQL.query("DELETE FROM vehicle_antidespawn WHERE plate = ?", {plate})
|
|
activeSpawns[plate] = nil
|
|
return
|
|
end
|
|
|
|
-- Send spawn event back to client
|
|
TriggerClientEvent('antidespawn:client:spawnVehicle', src, {
|
|
plate = plate,
|
|
model = vehicles[plate].model,
|
|
coords = vehicles[plate].coords,
|
|
heading = vehicles[plate].heading,
|
|
fuel = vehicles[plate].fuel,
|
|
mods = vehicles[plate].mods
|
|
})
|
|
|
|
Debug("Fahrzeug Respawn angefordert: " .. plate .. " (Besitzer: " .. tostring(vehicles[plate].owner) .. ")")
|
|
end)
|
|
end)
|
|
|
|
-- Load vehicles for a player (load all vehicles in range, not just owned ones)
|
|
RegisterNetEvent('antidespawn:server:loadVehicles', function()
|
|
local src = source
|
|
local Player = QBCore.Functions.GetPlayer(src)
|
|
|
|
if not Player then
|
|
Debug("Spieler nicht gefunden")
|
|
return
|
|
end
|
|
|
|
Debug("Lade Fahrzeuge für Spieler: " .. Player.PlayerData.citizenid)
|
|
|
|
local playerCoords = GetEntityCoords(GetPlayerPed(src))
|
|
local loadedCount = 0
|
|
local vehiclesToLoad = {}
|
|
|
|
-- 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
|
|
Debug("Fahrzeug existiert nicht in player_vehicles: " .. plate)
|
|
-- Entferne aus Anti-Despawn Datenbank
|
|
vehicles[plate] = nil
|
|
MySQL.query("DELETE FROM vehicle_antidespawn WHERE plate = ?", {plate})
|
|
return
|
|
end
|
|
|
|
-- Check if vehicle is in garage
|
|
local inGarage = false
|
|
for _, veh in ipairs(result) do
|
|
if veh.state == 1 then
|
|
inGarage = true
|
|
break
|
|
end
|
|
end
|
|
|
|
if inGarage then
|
|
Debug("Fahrzeug ist in der Garage, nicht laden: " .. plate)
|
|
-- Entferne aus Anti-Despawn Datenbank
|
|
vehicles[plate] = nil
|
|
MySQL.query("DELETE FROM vehicle_antidespawn WHERE plate = ?", {plate})
|
|
return
|
|
end
|
|
|
|
-- Lade nur Fahrzeuge in der Nähe des Spielers
|
|
local distance = #(playerCoords - vector3(vehicle.coords.x, vehicle.coords.y, vehicle.coords.z))
|
|
|
|
if distance < 100.0 then
|
|
-- Stelle sicher, dass das Modell als Zahl gespeichert ist
|
|
local model = vehicle.model
|
|
if type(model) == "string" then
|
|
model = tonumber(model) or model
|
|
end
|
|
|
|
table.insert(vehiclesToLoad, {
|
|
plate = plate,
|
|
model = model,
|
|
coords = vehicle.coords,
|
|
heading = vehicle.heading,
|
|
fuel = vehicle.fuel,
|
|
mods = vehicle.mods
|
|
})
|
|
|
|
loadedCount = loadedCount + 1
|
|
end
|
|
end)
|
|
::continue::
|
|
end
|
|
|
|
-- Warte kurz und lade dann die Fahrzeuge
|
|
SetTimeout(3000, function()
|
|
for _, vehicleData in ipairs(vehiclesToLoad) do
|
|
-- Anti-Duplication: Check if there's already an active spawn request for this plate
|
|
if not activeSpawns[vehicleData.plate] then
|
|
activeSpawns[vehicleData.plate] = true
|
|
|
|
-- Set a timeout to clear the active spawn status
|
|
SetTimeout(10000, function()
|
|
activeSpawns[vehicleData.plate] = nil
|
|
end)
|
|
|
|
TriggerClientEvent('antidespawn:client:spawnVehicle', src, vehicleData)
|
|
Debug("Fahrzeug für Spieler geladen: " .. vehicleData.plate)
|
|
else
|
|
Debug("Anti-Dupe: Already processing spawn request for: " .. vehicleData.plate)
|
|
end
|
|
end
|
|
|
|
Debug("Fahrzeugladung abgeschlossen. " .. loadedCount .. " Fahrzeuge geladen.")
|
|
end)
|
|
end)
|
|
|
|
|
|
-- Cleanup alte Einträge (älter als 24 Stunden)
|
|
CreateThread(function()
|
|
while true do
|
|
Wait(3600000) -- 1 Stunde
|
|
MySQL.query("DELETE FROM vehicle_antidespawn WHERE last_updated < DATE_SUB(NOW(), INTERVAL 24 HOUR)")
|
|
Debug("Alte Fahrzeugeinträge bereinigt")
|
|
end
|
|
end)
|
|
|
|
-- Registriere jg-advancedgarages Events
|
|
RegisterNetEvent('jg-advancedgarages:server:vehicle-stored', function(data)
|
|
if data and data.plate then
|
|
Debug("Fahrzeug in Garage gespeichert: " .. data.plate)
|
|
|
|
-- Entferne aus Anti-Despawn Datenbank
|
|
if vehicles[data.plate] then
|
|
vehicles[data.plate] = nil
|
|
|
|
MySQL.query("DELETE FROM vehicle_antidespawn WHERE plate = ?", {
|
|
data.plate
|
|
})
|
|
|
|
Debug("Fahrzeug aus Anti-Despawn entfernt: " .. data.plate)
|
|
end
|
|
end
|
|
end)
|
|
|
|
RegisterNetEvent('jg-advancedgarages:server:vehicle-spawned', function(data)
|
|
if data and data.plate then
|
|
Debug("Fahrzeug aus Garage gespawnt: " .. data.plate)
|
|
|
|
-- Entferne aus Anti-Despawn Datenbank, da es jetzt von der Garage verwaltet wird
|
|
if vehicles[data.plate] then
|
|
vehicles[data.plate] = nil
|
|
|
|
MySQL.query("DELETE FROM vehicle_antidespawn WHERE plate = ?", {
|
|
data.plate
|
|
})
|
|
|
|
Debug("Fahrzeug aus Anti-Despawn entfernt: " .. data.plate)
|
|
end
|
|
end
|
|
end)
|
|
|
|
-- Befehl zum Anzeigen aller gespeicherten Fahrzeuge
|
|
RegisterCommand('listvehicles', function(source, args, rawCommand)
|
|
if source == 0 then -- Nur über Konsole ausführbar
|
|
Debug("Gespeicherte Fahrzeuge:")
|
|
local count = 0
|
|
for plate, vehicle in pairs(vehicles) do
|
|
Debug(plate .. " - Modell: " .. tostring(vehicle.model) .. " - Position: " ..
|
|
tostring(vehicle.coords.x) .. ", " .. tostring(vehicle.coords.y) .. ", " .. tostring(vehicle.coords.z) ..
|
|
" - Besitzer: " .. tostring(vehicle.owner))
|
|
count = count + 1
|
|
end
|
|
Debug("Insgesamt " .. count .. " Fahrzeuge gespeichert.")
|
|
end
|
|
end, true)
|
|
|
|
-- Befehl zum Prüfen des Garage-Status eines Fahrzeugs
|
|
RegisterCommand('checkgarage', function(source, args, rawCommand)
|
|
if source == 0 and args[1] then -- Nur über Konsole ausführbar
|
|
local plate = args[1]
|
|
MySQL.query('SELECT * FROM player_vehicles WHERE plate = ?', {plate}, function(result)
|
|
if result and #result > 0 then
|
|
for _, veh in ipairs(result) do
|
|
Debug("Fahrzeug " .. plate .. " - State: " .. veh.state .. " - Owner: " .. veh.citizenid)
|
|
end
|
|
else
|
|
Debug("Fahrzeug " .. plate .. " nicht in player_vehicles gefunden.")
|
|
end
|
|
end)
|
|
end
|
|
end, true)
|
|
|
|
-- Befehl zum manuellen Entfernen eines Fahrzeugs
|
|
RegisterCommand('removevehicle', function(source, args, rawCommand)
|
|
if source == 0 and args[1] then -- Nur über Konsole ausführbar
|
|
local plate = args[1]
|
|
if vehicles[plate] then
|
|
vehicles[plate] = nil
|
|
MySQL.query("DELETE FROM vehicle_antidespawn WHERE plate = ?", {plate})
|
|
Debug("Fahrzeug " .. plate .. " aus Anti-Despawn entfernt.")
|
|
else
|
|
Debug("Fahrzeug " .. plate .. " nicht in Anti-Despawn gefunden.")
|
|
end
|
|
end
|
|
end, true)
|
|
|
|
-- Befehl zum Bereinigen der Datenbank
|
|
RegisterCommand('clearvehicles', function(source, args, rawCommand)
|
|
if source == 0 then -- Nur über Konsole ausführbar
|
|
local count = 0
|
|
|
|
for plate, vehicle in pairs(vehicles) do
|
|
local model = vehicle.model
|
|
|
|
-- Prüfe ob das Modell gültig ist
|
|
if type(model) == "string" and not tonumber(model) then
|
|
-- Ungültiges Modell, entferne aus Datenbank
|
|
MySQL.query("DELETE FROM vehicle_antidespawn WHERE plate = ?", {plate})
|
|
vehicles[plate] = nil
|
|
count = count + 1
|
|
Debug("Ungültiges Modell entfernt: " .. plate .. " (Modell: " .. tostring(model) .. ")")
|
|
end
|
|
end
|
|
|
|
Debug("Bereinigung abgeschlossen. " .. count .. " Fahrzeuge entfernt.")
|
|
end
|
|
end, true)
|
|
|
|
-- Befehl zum Leeren der Datenbank
|
|
RegisterCommand('clearalldespawn', function(source, args, rawCommand)
|
|
if source == 0 then -- Nur über Konsole ausführbar
|
|
MySQL.query("DELETE FROM vehicle_antidespawn", {})
|
|
vehicles = {}
|
|
Debug("Alle Fahrzeuge aus der Datenbank entfernt.")
|
|
end
|
|
end, true)
|
|
|
|
-- Debug command to check active spawns
|
|
RegisterCommand('activespawns', function(source, args, rawCommand)
|
|
if source == 0 then -- Nur über Konsole ausführbar
|
|
local count = 0
|
|
for plate, _ in pairs(activeSpawns) do
|
|
Debug("Active spawn: " .. plate)
|
|
count = count + 1
|
|
end
|
|
Debug("Total active spawns: " .. count)
|
|
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
|
|
Debug("Resource stopping, clearing all data")
|
|
vehicles = {}
|
|
activeSpawns = {}
|
|
end
|
|
end)
|