local QBCore = exports['qb-core']:GetCoreObject() local trackedVehicles = {} local lastKnownCoords = {} local garagePending = {} -- Fahrzeuge, die gerade in die Garage gestellt werden -- Helper function to count table entries function tableLength(T) local count = 0 for _ in pairs(T) do count = count + 1 end return count end -- Debug Funktion local function Debug(msg) if Config.Debug then print("[AntiDespawn] " .. msg) end end -- Function to check if player owns the vehicle local function DoesPlayerOwnVehicle(plate) local playerData = QBCore.Functions.GetPlayerData() if not playerData then return false end -- Trigger server event to check ownership and wait for response local isOwned = nil -- Request ownership check from server TriggerServerEvent('antidespawn:server:checkVehicleOwnership', plate) -- Register one-time event handler for the response RegisterNetEvent('antidespawn:client:vehicleOwnershipResult') local eventHandler = AddEventHandler('antidespawn:client:vehicleOwnershipResult', function(result, checkPlate) if plate == checkPlate then isOwned = result end end) -- Wait for response with timeout local timeout = 0 while isOwned == nil and timeout < 50 do Wait(10) timeout = timeout + 1 end -- Remove event handler RemoveEventHandler(eventHandler) return isOwned == true end -- Funktion um zu prüfen ob Fahrzeugklasse erlaubt ist local function IsVehicleClassAllowed(vehicle) local vehicleClass = GetVehicleClass(vehicle) -- Prüfe Blacklist for _, blacklistedClass in pairs(Config.BlacklistedVehicleClasses) do if vehicleClass == blacklistedClass then return false end end -- Prüfe Whitelist for _, allowedClass in pairs(Config.AllowedVehicleClasses) do if vehicleClass == allowedClass then return true end end return false end -- Rest of your functions remain the same... -- Event Handler für Fahrzeug betreten (nur Fahrersitz) CreateThread(function() while true do Wait(1000) local playerPed = PlayerPedId() local currentVehicle = GetVehiclePedIsIn(playerPed, false) -- Spieler ist als Fahrer in ein Fahrzeug eingestiegen if currentVehicle ~= 0 then -- Prüfe ob Spieler auf Fahrersitz ist local driver = GetPedInVehicleSeat(currentVehicle, -1) -- Nur wenn Spieler der Fahrer ist (Seat -1) if driver == playerPed and IsVehicleClassAllowed(currentVehicle) then local plate = QBCore.Functions.GetPlate(currentVehicle) -- Check if this vehicle is already being tracked if not trackedVehicles[plate] and not garagePending[plate] then -- Check if player owns this vehicle if DoesPlayerOwnVehicle(plate) then -- Check if maximum tracked vehicles limit is reached local maxTrackedVehicles = 100 -- Adjust as needed if tableLength(trackedVehicles) >= maxTrackedVehicles then Debug("Maximum number of tracked vehicles reached") -- You could implement logic to remove the oldest vehicle here else trackedVehicles[plate] = currentVehicle -- Speichere letzte bekannte Position lastKnownCoords[plate] = GetEntityCoords(currentVehicle) -- Sofort starke Despawn-Verhinderung PreventDespawn(currentVehicle) Debug("Fahrzeug wird nun getrackt: " .. plate) -- Hole Fahrzeugmods local vehicleMods = GetVehicleMods(currentVehicle) -- Registriere Fahrzeug beim Server local vehicleCoords = GetEntityCoords(currentVehicle) local vehicleHeading = GetEntityHeading(currentVehicle) local vehicleModel = GetEntityModel(currentVehicle) TriggerServerEvent('antidespawn:server:registerVehicle', plate, vehicleModel, vehicleCoords, vehicleHeading, vehicleMods) end else Debug("Fahrzeug gehört nicht dem Spieler, wird nicht getrackt: " .. plate) end end end end end end) -- Kontinuierliche Despawn-Verhinderung für alle getrackten Fahrzeuge CreateThread(function() while true do Wait(5000) -- Alle 5 Sekunden local playerPed = PlayerPedId() local playerPos = GetEntityCoords(playerPed) for plate, vehicle in pairs(trackedVehicles) do -- Prüfe ob Fahrzeug gerade in die Garage gestellt wird if garagePending[plate] then Debug("Fahrzeug wird gerade in Garage gestellt, entferne aus Tracking: " .. plate) trackedVehicles[plate] = nil lastKnownCoords[plate] = nil TriggerServerEvent('antidespawn:server:removeVehicle', plate) elseif DoesEntityExist(vehicle) then -- Check distance to player local vehiclePos = GetEntityCoords(vehicle) local distance = #(playerPos - vehiclePos) if distance > 500.0 then -- 500 units = about 500 meters Debug("Fahrzeug zu weit entfernt, entferne aus Tracking: " .. plate) trackedVehicles[plate] = nil lastKnownCoords[plate] = nil TriggerServerEvent('antidespawn:server:removeVehicle', plate) else PreventDespawn(vehicle) -- Aktualisiere letzte bekannte Position lastKnownCoords[plate] = vehiclePos -- Hole Fahrzeugmods local vehicleMods = GetVehicleMods(vehicle) -- Aktualisiere Position local vehicleHeading = GetEntityHeading(vehicle) TriggerServerEvent('antidespawn:server:updateVehicle', plate, vehiclePos, vehicleHeading, vehicleMods) Debug("Aktualisiere Fahrzeug: " .. plate) end else Debug("Fahrzeug existiert nicht mehr: " .. plate) -- 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) TriggerServerEvent('antidespawn:server:respawnVehicle', plate) -- Entferne aus lokaler Tracking-Liste, wird nach Respawn wieder hinzugefügt trackedVehicles[plate] = nil lastKnownCoords[plate] = nil else -- Entferne aus Tracking trackedVehicles[plate] = nil lastKnownCoords[plate] = nil end end end end end) -- Lade Fahrzeuge beim Spawn RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function() Debug("Spieler geladen, warte vor dem Laden der Fahrzeuge...") -- Längere Wartezeit, um sicherzustellen, dass alles geladen ist Wait(15000) TriggerServerEvent('antidespawn:server:loadVehicles') end) -- Automatisches Laden beim Resource Start CreateThread(function() -- Längere Wartezeit beim Serverstart Wait(20000) -- Prüfe ob Spieler eingeloggt ist local playerData = QBCore.Functions.GetPlayerData() if playerData and playerData.citizenid then Debug("Resource gestartet, lade Fahrzeuge...") TriggerServerEvent('antidespawn:server:loadVehicles') else -- Warte auf Login, wenn Spieler noch nicht eingeloggt ist Debug("Warte auf Spieler-Login...") while true do Wait(5000) playerData = QBCore.Functions.GetPlayerData() if playerData and playerData.citizenid then Debug("Spieler jetzt eingeloggt, lade Fahrzeuge...") TriggerServerEvent('antidespawn:server:loadVehicles') break end end end end) -- Spawne ein Fahrzeug RegisterNetEvent('antidespawn:client:spawnVehicle', function(data) Debug("Spawne Fahrzeug: " .. data.plate) -- Prüfe ob Fahrzeug bereits existiert local existingVehicle = GetVehicleByPlate(data.plate) if existingVehicle then Debug("Fahrzeug existiert bereits: " .. data.plate) trackedVehicles[data.plate] = existingVehicle lastKnownCoords[data.plate] = GetEntityCoords(existingVehicle) PreventDespawn(existingVehicle) return end -- Prüfe ob Fahrzeug gerade in die Garage gestellt wird if garagePending[data.plate] then Debug("Fahrzeug wird gerade in Garage gestellt, nicht spawnen: " .. data.plate) return end -- Konvertiere Modell zu Hash wenn nötig local modelHash = data.model if type(modelHash) == "string" then -- Versuche den String als Hash zu interpretieren if tonumber(modelHash) then modelHash = tonumber(modelHash) else -- Versuche den String als Modellnamen zu interpretieren modelHash = GetHashKey(modelHash) end end Debug("Versuche Modell zu laden: " .. tostring(modelHash)) -- Prüfe ob Modell existiert if not IsModelInCdimage(modelHash) then Debug("Modell existiert nicht in CD Image: " .. tostring(modelHash)) return end RequestModel(modelHash) local timeout = 0 while not HasModelLoaded(modelHash) and timeout < 100 do Wait(100) timeout = timeout + 1 Debug("Warte auf Modell: " .. tostring(timeout) .. "/100") end if HasModelLoaded(modelHash) then Debug("Modell geladen, erstelle Fahrzeug...") -- Verwende CREATE_AUTOMOBILE für bessere Persistenz local vehicle if Citizen and Citizen.InvokeNative then -- OneSync Methode Debug("Verwende OneSync Methode") vehicle = Citizen.InvokeNative(0xAF35D0D2583051B0, modelHash, data.coords.x, data.coords.y, data.coords.z, data.heading, true, true) else -- Fallback Debug("Verwende Fallback Methode") vehicle = CreateVehicle(modelHash, data.coords.x, data.coords.y, data.coords.z, data.heading, true, false) end if DoesEntityExist(vehicle) then -- Warte bis Fahrzeug vollständig geladen ist Wait(500) -- Setze Kennzeichen SetVehicleNumberPlateText(vehicle, data.plate) -- Setze Mods if data.mods then Debug("Setze Fahrzeugmods...") SetVehicleMods(vehicle, data.mods) end -- Setze Fuel if GetResourceState(Config.FuelSystem) == 'started' then exports[Config.FuelSystem]:SetFuel(vehicle, data.fuel or 100) end -- Verhindere Despawn PreventDespawn(vehicle) -- Füge zu getrackten Fahrzeugen hinzu trackedVehicles[data.plate] = vehicle lastKnownCoords[data.plate] = GetEntityCoords(vehicle) -- Registriere beim Server TriggerServerEvent('antidespawn:server:registerVehicle', data.plate, modelHash, GetEntityCoords(vehicle), GetEntityHeading(vehicle), GetVehicleMods(vehicle)) Debug("Fahrzeug erfolgreich gespawnt: " .. data.plate) else Debug("Fehler beim Spawnen des Fahrzeugs: " .. data.plate) end SetModelAsNoLongerNeeded(modelHash) else Debug("Modell konnte nicht geladen werden: " .. data.plate .. " (Hash: " .. tostring(modelHash) .. ")") end end) -- Hilfsfunktion um Fahrzeug anhand Kennzeichen zu finden function GetVehicleByPlate(plate) local vehicles = GetGamePool('CVehicle') for _, vehicle in pairs(vehicles) do if QBCore.Functions.GetPlate(vehicle) == plate then return vehicle end end return nil 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) local playerPed = PlayerPedId() local vehicle = GetVehiclePedIsIn(playerPed, false) if vehicle ~= 0 then local plate = QBCore.Functions.GetPlate(vehicle) -- Markiere Fahrzeug als "wird in Garage gestellt" garagePending[plate] = true SetTimeout(10000, function() if garagePending[plate] then Debug("Garage storage timeout for vehicle: " .. plate) garagePending[plate] = nil end end) -- Entferne aus Tracking if trackedVehicles[plate] then Debug("Fahrzeug wird in Garage gestellt, entferne aus Tracking: " .. plate) trackedVehicles[plate] = nil lastKnownCoords[plate] = nil TriggerServerEvent('antidespawn:server:removeVehicle', plate) end end end) -- jg-advanced-garage Events RegisterNetEvent('jg-advancedgarages:client:vehicle-stored', function(data) if data and data.plate then -- Markiere Fahrzeug als "in Garage" garagePending[data.plate] = nil -- Entferne aus Tracking if trackedVehicles[data.plate] then trackedVehicles[data.plate] = nil lastKnownCoords[data.plate] = nil end -- Entferne aus Datenbank TriggerServerEvent('antidespawn:server:removeVehicle', data.plate) Debug("Fahrzeug in Garage gespeichert, aus DB entfernt: " .. data.plate) end end) RegisterNetEvent('jg-advancedgarages:client:vehicle-spawned', function(data) if data and data.plate then -- Entferne Markierung "in Garage" garagePending[data.plate] = nil Debug("Fahrzeug aus Garage gespawnt: " .. data.plate) -- Warte kurz bis das Fahrzeug vollständig gespawnt ist Wait(1000) -- Finde das Fahrzeug local vehicle = GetVehicleByPlate(data.plate) if vehicle then -- Füge zu getrackten Fahrzeugen hinzu trackedVehicles[data.plate] = vehicle lastKnownCoords[data.plate] = GetEntityCoords(vehicle) -- Verhindere Despawn PreventDespawn(vehicle) Debug("Fahrzeug aus Garage zum Tracking hinzugefügt: " .. data.plate) end end end) -- Öffnen der Garage RegisterNetEvent('jg-advancedgarages:client:open-garage', function(garageId, vehicleType, spawnCoords) Debug("Garage geöffnet: " .. garageId) -- No need to mark vehicles as potentially being stored here -- Let the actual store-vehicle event handle this end) -- Manuelle Lade-Funktion RegisterCommand('loadvehicles', function() Debug("Manuelles Laden der Fahrzeuge...") TriggerServerEvent('antidespawn:server:loadVehicles') end, false) -- Debug Command RegisterCommand('fixvehicle', function() local playerPed = PlayerPedId() local vehicle = GetVehiclePedIsIn(playerPed, false) if vehicle ~= 0 then local plate = QBCore.Functions.GetPlate(vehicle) -- Prüfe ob Fahrzeug gerade in die Garage gestellt wird if not garagePending[plate] then PreventDespawn(vehicle) trackedVehicles[plate] = vehicle lastKnownCoords[plate] = GetEntityCoords(vehicle) -- Registriere Fahrzeug beim Server local vehicleCoords = GetEntityCoords(vehicle) local vehicleHeading = GetEntityHeading(vehicle) local vehicleModel = GetEntityModel(vehicle) local vehicleMods = GetVehicleMods(vehicle) TriggerServerEvent('antidespawn:server:registerVehicle', plate, vehicleModel, vehicleCoords, vehicleHeading, vehicleMods) Debug("Anti-Despawn für Fahrzeug aktiviert: " .. plate) else Debug("Fahrzeug wird gerade in Garage gestellt, kann nicht fixiert werden: " .. plate) end else Debug("Du musst in einem Fahrzeug sitzen!") end end, false) AddEventHandler('onResourceStop', function(resourceName) if resourceName == GetCurrentResourceName() then Debug("Resource stopping, clearing all data") trackedVehicles = {} lastKnownCoords = {} garagePending = {} end end)