2025-08-06 17:33:26 +02:00
|
|
|
local QBCore = exports['qb-core']:GetCoreObject()
|
2025-08-06 18:18:04 +02:00
|
|
|
local vehicles = {}
|
|
|
|
|
|
|
|
-- Debug Funktion
|
|
|
|
local function Debug(msg)
|
|
|
|
if Config.Debug then
|
|
|
|
print("[AntiDespawn] " .. msg)
|
|
|
|
end
|
|
|
|
end
|
2025-08-06 17:33:26 +02:00
|
|
|
|
|
|
|
-- Erstelle Tabelle bei Serverstart
|
|
|
|
CreateThread(function()
|
|
|
|
MySQL.query([[
|
2025-08-06 18:18:04 +02:00
|
|
|
CREATE TABLE IF NOT EXISTS `vehicle_antidespawn` (
|
2025-08-06 17:33:26 +02:00
|
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
|
|
`plate` varchar(50) NOT NULL,
|
|
|
|
`model` varchar(50) NOT NULL,
|
2025-08-06 18:18:04 +02:00
|
|
|
`coords` longtext NOT NULL,
|
|
|
|
`heading` float NOT NULL,
|
2025-08-06 17:33:26 +02:00
|
|
|
`fuel` int(11) DEFAULT 100,
|
|
|
|
`last_updated` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
|
|
PRIMARY KEY (`id`),
|
|
|
|
UNIQUE KEY `plate` (`plate`)
|
|
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
|
|
]])
|
2025-08-06 18:18:04 +02:00
|
|
|
|
|
|
|
Debug("Datenbank initialisiert")
|
|
|
|
|
|
|
|
-- 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,
|
|
|
|
last_updated = vehicle.last_updated
|
|
|
|
}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end)
|
2025-08-06 17:33:26 +02:00
|
|
|
end)
|
|
|
|
|
2025-08-06 18:18:04 +02:00
|
|
|
-- Registriere ein Fahrzeug
|
|
|
|
RegisterNetEvent('antidespawn:server:registerVehicle', function(plate, model, coords, heading)
|
2025-08-06 17:33:26 +02:00
|
|
|
local src = source
|
|
|
|
|
2025-08-06 18:18:04 +02:00
|
|
|
if not plate or not model or not coords then
|
|
|
|
Debug("Ungültige Daten beim Registrieren eines Fahrzeugs")
|
|
|
|
return
|
|
|
|
end
|
2025-08-06 17:33:26 +02:00
|
|
|
|
2025-08-06 18:32:55 +02:00
|
|
|
-- Prüfe ob Fahrzeug in der Garage ist
|
|
|
|
MySQL.query('SELECT * FROM player_vehicles WHERE plate = ? AND state = ?', {plate, 1}, function(result)
|
|
|
|
if result and #result > 0 then
|
|
|
|
Debug("Fahrzeug ist in der Garage, nicht registrieren: " .. plate)
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
vehicles[plate] = {
|
|
|
|
model = model,
|
|
|
|
coords = coords,
|
|
|
|
heading = heading,
|
|
|
|
fuel = 100,
|
|
|
|
last_updated = os.time()
|
|
|
|
}
|
|
|
|
|
|
|
|
MySQL.query("INSERT INTO vehicle_antidespawn (plate, model, coords, heading, fuel) VALUES (?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE coords = VALUES(coords), heading = VALUES(heading), last_updated = CURRENT_TIMESTAMP", {
|
|
|
|
plate,
|
|
|
|
model,
|
|
|
|
json.encode(coords),
|
|
|
|
heading,
|
|
|
|
100
|
|
|
|
})
|
|
|
|
|
|
|
|
Debug("Fahrzeug registriert: " .. plate)
|
|
|
|
end)
|
2025-08-06 18:18:04 +02:00
|
|
|
end)
|
|
|
|
|
|
|
|
-- Aktualisiere ein Fahrzeug
|
|
|
|
RegisterNetEvent('antidespawn:server:updateVehicle', function(plate, coords, heading)
|
|
|
|
if not vehicles[plate] then return end
|
|
|
|
|
2025-08-06 18:32:55 +02:00
|
|
|
-- Prüfe ob Fahrzeug in der Garage ist
|
|
|
|
MySQL.query('SELECT * FROM player_vehicles WHERE plate = ? AND state = ?', {plate, 1}, function(result)
|
|
|
|
if result and #result > 0 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].last_updated = os.time()
|
|
|
|
|
|
|
|
MySQL.query("UPDATE vehicle_antidespawn SET coords = ?, heading = ?, last_updated = CURRENT_TIMESTAMP WHERE plate = ?", {
|
|
|
|
json.encode(coords),
|
|
|
|
heading,
|
|
|
|
plate
|
|
|
|
})
|
|
|
|
|
|
|
|
Debug("Fahrzeug aktualisiert: " .. plate)
|
|
|
|
end)
|
2025-08-06 17:33:26 +02:00
|
|
|
end)
|
|
|
|
|
2025-08-06 18:18:04 +02:00
|
|
|
-- Entferne ein Fahrzeug
|
|
|
|
RegisterNetEvent('antidespawn:server:removeVehicle', function(plate)
|
|
|
|
if not vehicles[plate] then return end
|
|
|
|
|
|
|
|
vehicles[plate] = nil
|
|
|
|
|
|
|
|
MySQL.query("DELETE FROM vehicle_antidespawn WHERE plate = ?", {
|
|
|
|
plate
|
|
|
|
})
|
|
|
|
|
|
|
|
Debug("Fahrzeug entfernt: " .. plate)
|
|
|
|
end)
|
|
|
|
|
2025-08-06 18:32:55 +02:00
|
|
|
-- Respawn ein Fahrzeug
|
|
|
|
RegisterNetEvent('antidespawn:server:respawnVehicle', function(plate)
|
|
|
|
local src = source
|
|
|
|
|
|
|
|
if not vehicles[plate] then
|
|
|
|
Debug("Fahrzeug nicht in Datenbank: " .. plate)
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Prüfe ob Fahrzeug in der Garage ist
|
|
|
|
MySQL.query('SELECT * FROM player_vehicles WHERE plate = ? AND state = ?', {plate, 1}, function(result)
|
|
|
|
if result and #result > 0 then
|
|
|
|
Debug("Fahrzeug ist in der Garage, nicht respawnen: " .. plate)
|
|
|
|
|
|
|
|
-- Entferne aus Anti-Despawn Datenbank
|
|
|
|
vehicles[plate] = nil
|
|
|
|
|
|
|
|
MySQL.query("DELETE FROM vehicle_antidespawn WHERE plate = ?", {
|
|
|
|
plate
|
|
|
|
})
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Sende Spawn-Event zurück an den Client
|
|
|
|
TriggerClientEvent('antidespawn:client:spawnVehicle', src, {
|
|
|
|
plate = plate,
|
|
|
|
model = vehicles[plate].model,
|
|
|
|
coords = vehicles[plate].coords,
|
|
|
|
heading = vehicles[plate].heading,
|
|
|
|
fuel = vehicles[plate].fuel
|
|
|
|
})
|
|
|
|
|
|
|
|
Debug("Fahrzeug Respawn angefordert: " .. plate)
|
|
|
|
end)
|
|
|
|
end)
|
|
|
|
|
2025-08-06 18:18:04 +02:00
|
|
|
-- Lade Fahrzeuge für einen Spieler
|
|
|
|
RegisterNetEvent('antidespawn:server:loadVehicles', function()
|
2025-08-06 17:33:26 +02:00
|
|
|
local src = source
|
|
|
|
local Player = QBCore.Functions.GetPlayer(src)
|
|
|
|
|
|
|
|
if not Player then return end
|
|
|
|
|
2025-08-06 18:18:04 +02:00
|
|
|
local playerCoords = GetEntityCoords(GetPlayerPed(src))
|
2025-08-06 17:33:26 +02:00
|
|
|
|
2025-08-06 18:32:55 +02:00
|
|
|
-- Prüfe für jedes Fahrzeug, ob es in der Garage ist
|
2025-08-06 18:18:04 +02:00
|
|
|
for plate, vehicle in pairs(vehicles) do
|
2025-08-06 18:32:55 +02:00
|
|
|
MySQL.query('SELECT * FROM player_vehicles WHERE plate = ? AND state = ?', {plate, 1}, function(result)
|
|
|
|
if result and #result > 0 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
|
2025-08-06 18:18:04 +02:00
|
|
|
|
2025-08-06 18:32:55 +02:00
|
|
|
-- 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
|
|
|
|
TriggerClientEvent('antidespawn:client:spawnVehicle', src, {
|
|
|
|
plate = plate,
|
|
|
|
model = vehicle.model,
|
|
|
|
coords = vehicle.coords,
|
|
|
|
heading = vehicle.heading,
|
|
|
|
fuel = vehicle.fuel
|
|
|
|
})
|
|
|
|
|
|
|
|
Debug("Fahrzeug für Spieler geladen: " .. plate)
|
|
|
|
end
|
|
|
|
end)
|
2025-08-06 17:33:26 +02:00
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
-- Cleanup alte Einträge (älter als 24 Stunden)
|
|
|
|
CreateThread(function()
|
|
|
|
while true do
|
|
|
|
Wait(3600000) -- 1 Stunde
|
2025-08-06 18:18:04 +02:00
|
|
|
MySQL.query("DELETE FROM vehicle_antidespawn WHERE last_updated < DATE_SUB(NOW(), INTERVAL 24 HOUR)")
|
|
|
|
Debug("Alte Fahrzeugeinträge bereinigt")
|
2025-08-06 17:33:26 +02:00
|
|
|
end
|
|
|
|
end)
|
2025-08-06 18:32:55 +02:00
|
|
|
|
|
|
|
-- 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)
|