From 9520ad1b0760f2d0e393e8ebdf4f2f63926afdf2 Mon Sep 17 00:00:00 2001 From: Nordi98 Date: Wed, 6 Aug 2025 18:32:55 +0200 Subject: [PATCH] ed --- .../nordi_antidespawn/client/main.lua | 158 +++++++++++++-- .../nordi_antidespawn/server/main.lua | 189 ++++++++++++++---- 2 files changed, 284 insertions(+), 63 deletions(-) diff --git a/resources/[carscripts]/nordi_antidespawn/client/main.lua b/resources/[carscripts]/nordi_antidespawn/client/main.lua index 6a5364478..2725a0380 100644 --- a/resources/[carscripts]/nordi_antidespawn/client/main.lua +++ b/resources/[carscripts]/nordi_antidespawn/client/main.lua @@ -1,5 +1,6 @@ local QBCore = exports['qb-core']:GetCoreObject() local trackedVehicles = {} +local lastKnownCoords = {} -- Debug Funktion local function Debug(msg) @@ -29,27 +30,35 @@ local function IsVehicleClassAllowed(vehicle) return false end --- Starke Anti-Despawn Funktion +-- Extrem starke Anti-Despawn Funktion local function PreventDespawn(vehicle) - if DoesEntityExist(vehicle) then - -- Grundlegende Persistenz - SetEntityAsMissionEntity(vehicle, true, true) - SetVehicleHasBeenOwnedByPlayer(vehicle, true) - SetVehicleNeedsToBeHotwired(vehicle, false) - - -- Zusätzliche Flags - SetEntityLoadCollisionFlag(vehicle, true) - SetVehicleIsStolen(vehicle, false) - SetVehicleIsWanted(vehicle, false) - - -- Verhindere dass das Fahrzeug als "abandoned" markiert wird - if DecorExistOn(vehicle, "IgnoredByQuickSave") then - DecorSetBool(vehicle, "IgnoredByQuickSave", false) - end - - return true + if not DoesEntityExist(vehicle) then return false end + + -- Grundlegende Persistenz + SetEntityAsMissionEntity(vehicle, true, true) + SetVehicleHasBeenOwnedByPlayer(vehicle, true) + SetVehicleNeedsToBeHotwired(vehicle, false) + + -- Zusätzliche Flags + SetEntityLoadCollisionFlag(vehicle, true) + SetVehicleIsStolen(vehicle, false) + SetVehicleIsWanted(vehicle, false) + + -- Verhindere dass das Fahrzeug als "abandoned" markiert wird + if DecorIsRegisteredAsType("IgnoredByQuickSave", 2) then + DecorSetBool(vehicle, "IgnoredByQuickSave", false) end - return false + + -- Setze Fahrzeug auf Boden + SetVehicleOnGroundProperly(vehicle) + + -- Verhindere dass das Fahrzeug gelöscht wird + NetworkRegisterEntityAsNetworked(vehicle) + local netID = NetworkGetNetworkIdFromEntity(vehicle) + SetNetworkIdExistsOnAllMachines(netID, true) + SetNetworkIdCanMigrate(netID, true) + + return true end -- Event Handler für Fahrzeug betreten (nur Fahrersitz) @@ -72,6 +81,9 @@ CreateThread(function() local plate = QBCore.Functions.GetPlate(currentVehicle) trackedVehicles[plate] = currentVehicle + -- Speichere letzte bekannte Position + lastKnownCoords[plate] = GetEntityCoords(currentVehicle) + -- Sofort starke Despawn-Verhinderung PreventDespawn(currentVehicle) @@ -93,12 +105,15 @@ end) -- Kontinuierliche Despawn-Verhinderung für alle getrackten Fahrzeuge CreateThread(function() while true do - Wait(10000) -- Alle 10 Sekunden + Wait(5000) -- Alle 5 Sekunden for plate, vehicle in pairs(trackedVehicles) do if DoesEntityExist(vehicle) then PreventDespawn(vehicle) + -- Aktualisiere letzte bekannte Position + lastKnownCoords[plate] = GetEntityCoords(vehicle) + -- Aktualisiere Position local vehicleCoords = GetEntityCoords(vehicle) local vehicleHeading = GetEntityHeading(vehicle) @@ -107,8 +122,16 @@ CreateThread(function() Debug("Aktualisiere Fahrzeug: " .. plate) else - trackedVehicles[plate] = nil Debug("Fahrzeug existiert nicht mehr: " .. plate) + + -- Versuche Fahrzeug wiederherzustellen + if lastKnownCoords[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 + end end end end @@ -130,6 +153,7 @@ RegisterNetEvent('antidespawn:client:spawnVehicle', function(data) if existingVehicle then Debug("Fahrzeug existiert bereits: " .. data.plate) trackedVehicles[data.plate] = existingVehicle + lastKnownCoords[data.plate] = GetEntityCoords(existingVehicle) PreventDespawn(existingVehicle) return end @@ -145,9 +169,21 @@ RegisterNetEvent('antidespawn:client:spawnVehicle', function(data) end if HasModelLoaded(modelHash) then - local vehicle = CreateVehicle(modelHash, data.coords.x, data.coords.y, data.coords.z, data.heading, true, false) + -- Verwende CREATE_AUTOMOBILE für bessere Persistenz + local vehicle + + if Citizen and Citizen.InvokeNative then + -- OneSync Methode + vehicle = Citizen.InvokeNative(0xAF35D0D2583051B0, modelHash, data.coords.x, data.coords.y, data.coords.z, data.heading, true, true) + else + -- Fallback + 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) @@ -161,6 +197,13 @@ RegisterNetEvent('antidespawn:client:spawnVehicle', function(data) -- 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)) + + -- Registriere bei jg-advancedgarages als "draußen" + TriggerEvent("jg-advancedgarages:server:register-vehicle-outside", data.plate, NetworkGetNetworkIdFromEntity(vehicle)) Debug("Fahrzeug erfolgreich gespawnt: " .. data.plate) else @@ -188,14 +231,85 @@ end RegisterNetEvent('jg-advancedgarages:client:vehicle-stored', function(data) if data and data.plate and trackedVehicles[data.plate] then trackedVehicles[data.plate] = nil + lastKnownCoords[data.plate] = nil TriggerServerEvent('antidespawn:server:removeVehicle', data.plate) Debug("Fahrzeug in Garage gespeichert, entferne aus Tracking: " .. data.plate) end end) +RegisterNetEvent('jg-advancedgarages:client:vehicle-spawned', function(data) + if data and data.plate then + 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 - entferne Tracking für Fahrzeuge in der Nähe +RegisterNetEvent('jg-advancedgarages:client:open-garage', function() + Debug("Garage geöffnet, prüfe Fahrzeuge in der Nähe") + + local playerPos = GetEntityCoords(PlayerPedId()) + + -- Prüfe alle getrackten Fahrzeuge + for plate, vehicle in pairs(trackedVehicles) do + if DoesEntityExist(vehicle) then + local vehiclePos = GetEntityCoords(vehicle) + local distance = #(playerPos - vehiclePos) + + -- Wenn Fahrzeug in der Nähe ist (50m), entferne aus Tracking + -- da es wahrscheinlich in die Garage gestellt wird + if distance < 50.0 then + Debug("Fahrzeug in Garagennähe, entferne temporär aus Tracking: " .. plate) + -- Nicht komplett entfernen, nur temporär ignorieren + -- Das Event jg-advancedgarages:client:vehicle-stored wird ausgelöst wenn es eingelagert wird + end + end + end +end) + +-- Debug Command +RegisterCommand('fixvehicle', function() + local playerPed = PlayerPedId() + local vehicle = GetVehiclePedIsIn(playerPed, false) + + if vehicle ~= 0 then + local plate = QBCore.Functions.GetPlate(vehicle) + 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) + + TriggerServerEvent('antidespawn:server:registerVehicle', plate, vehicleModel, vehicleCoords, vehicleHeading) + + Debug("Anti-Despawn für Fahrzeug aktiviert: " .. plate) + else + Debug("Du musst in einem Fahrzeug sitzen!") + end +end, false) + -- Cleanup beim Disconnect AddEventHandler('onResourceStop', function(resourceName) if resourceName == GetCurrentResourceName() then trackedVehicles = {} + lastKnownCoords = {} end end) diff --git a/resources/[carscripts]/nordi_antidespawn/server/main.lua b/resources/[carscripts]/nordi_antidespawn/server/main.lua index 29379d573..160627045 100644 --- a/resources/[carscripts]/nordi_antidespawn/server/main.lua +++ b/resources/[carscripts]/nordi_antidespawn/server/main.lua @@ -53,40 +53,61 @@ RegisterNetEvent('antidespawn:server:registerVehicle', function(plate, model, co 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) + -- 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) end) -- Aktualisiere ein Fahrzeug RegisterNetEvent('antidespawn:server:updateVehicle', function(plate, coords, heading) if not vehicles[plate] then 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) + -- 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) end) -- Entferne ein Fahrzeug @@ -102,6 +123,42 @@ RegisterNetEvent('antidespawn:server:removeVehicle', function(plate) Debug("Fahrzeug entfernt: " .. plate) end) +-- 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) + -- Lade Fahrzeuge für einen Spieler RegisterNetEvent('antidespawn:server:loadVehicles', function() local src = source @@ -111,21 +168,36 @@ RegisterNetEvent('antidespawn:server:loadVehicles', function() local playerCoords = GetEntityCoords(GetPlayerPed(src)) - -- Lade nur Fahrzeuge in der Nähe des Spielers + -- Prüfe für jedes Fahrzeug, ob es in der Garage ist for plate, vehicle in pairs(vehicles) do - 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 - }) + 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 - Debug("Fahrzeug für Spieler geladen: " .. plate) - 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 + 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) end end) @@ -137,3 +209,38 @@ CreateThread(function() 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)