From d5aace907a580bd822e90d6f3bf6760825c14e3c Mon Sep 17 00:00:00 2001 From: Nordi98 Date: Thu, 7 Aug 2025 13:35:00 +0200 Subject: [PATCH] ed --- .../nordi_antidespawn/client/main.lua | 93 +++----- .../nordi_antidespawn/server/main.lua | 223 ++++++++---------- 2 files changed, 132 insertions(+), 184 deletions(-) diff --git a/resources/[carscripts]/nordi_antidespawn/client/main.lua b/resources/[carscripts]/nordi_antidespawn/client/main.lua index 4c2ec22bc..59d0d35ce 100644 --- a/resources/[carscripts]/nordi_antidespawn/client/main.lua +++ b/resources/[carscripts]/nordi_antidespawn/client/main.lua @@ -385,43 +385,31 @@ CreateThread(function() -- 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") - -- Optionally, you could delete the duplicate here - -- DeleteEntity(currentVehicle) goto continue end -- 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") - 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 + -- Track all vehicles, regardless of ownership + 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 end end @@ -568,11 +556,8 @@ RegisterNetEvent('antidespawn:client:spawnVehicle', function(data) return end - -- Anti-Duplication: Check if player owns this vehicle - if not DoesPlayerOwnVehicle(data.plate) then - Debug("Anti-Dupe: Player does not own vehicle, not spawning: " .. data.plate) - return - end + -- Allow spawning of all vehicles, not just owned ones + -- No ownership check here -- Konvertiere Modell zu Hash wenn nötig local modelHash = data.model @@ -767,24 +752,20 @@ RegisterCommand('fixvehicle', function() -- Prüfe ob Fahrzeug gerade in die Garage gestellt wird if not garagePending[plate] then - -- Check if player owns this vehicle - if DoesPlayerOwnVehicle(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 gehört nicht dem Spieler, kann nicht fixiert werden: " .. plate) - end + -- Track all vehicles, regardless of ownership + 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 @@ -854,5 +835,3 @@ RegisterCommand('clearownership', function() Debug("Cleared vehicle ownership cache") end, false) - - diff --git a/resources/[carscripts]/nordi_antidespawn/server/main.lua b/resources/[carscripts]/nordi_antidespawn/server/main.lua index 1e7eef80b..5e94fd63f 100644 --- a/resources/[carscripts]/nordi_antidespawn/server/main.lua +++ b/resources/[carscripts]/nordi_antidespawn/server/main.lua @@ -22,6 +22,15 @@ CreateThread(function() 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...") @@ -34,6 +43,7 @@ CreateThread(function() `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`) @@ -59,6 +69,7 @@ CreateThread(function() 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 @@ -82,41 +93,29 @@ RegisterNetEvent('antidespawn:server:checkVehicleOwnership', function(plate) end) end) --- Enhanced anti-duplication for vehicle registration +-- 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 - -- Verify ownership before registering + -- 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 player owns the vehicle - local isOwner = false - for _, veh in ipairs(result) do - if veh.citizenid == Player.PlayerData.citizenid then - isOwner = true - break - end - end - - if not isOwner then - Debug("Player does not own vehicle: " .. 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 - break end + ownerId = veh.citizenid -- Store the owner ID end if inGarage then @@ -138,23 +137,25 @@ RegisterNetEvent('antidespawn:server:registerVehicle', function(plate, model, co heading = heading, fuel = 100, mods = mods, + owner = ownerId, last_updated = os.time() } - MySQL.query("INSERT INTO vehicle_antidespawn (plate, model, coords, heading, fuel, mods) VALUES (?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE coords = VALUES(coords), heading = VALUES(heading), mods = VALUES(mods), last_updated = CURRENT_TIMESTAMP", { + 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) + json.encode(mods), + ownerId }) - Debug("Fahrzeug registriert: " .. plate .. " (Modell: " .. tostring(model) .. ")") + Debug("Fahrzeug registriert: " .. plate .. " (Modell: " .. tostring(model) .. ", Besitzer: " .. tostring(ownerId) .. ")") end) end) --- Aktualisiere ein Fahrzeug +-- Update a vehicle RegisterNetEvent('antidespawn:server:updateVehicle', function(plate, coords, heading, mods) local src = source local Player = QBCore.Functions.GetPlayer(src) @@ -162,27 +163,13 @@ RegisterNetEvent('antidespawn:server:updateVehicle', function(plate, coords, hea if not Player then return end if not vehicles[plate] then return end - -- Verify ownership before updating + -- 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 player owns the vehicle - local isOwner = false - for _, veh in ipairs(result) do - if veh.citizenid == Player.PlayerData.citizenid then - isOwner = true - break - end - end - - if not isOwner then - Debug("Player does not own vehicle: " .. plate) - return - end - -- Check if vehicle is in garage local inGarage = false for _, veh in ipairs(result) do @@ -218,7 +205,7 @@ RegisterNetEvent('antidespawn:server:updateVehicle', function(plate, coords, hea end) end) --- Entferne ein Fahrzeug +-- Remove a vehicle RegisterNetEvent('antidespawn:server:removeVehicle', function(plate) local src = source if not vehicles[plate] then return end @@ -232,7 +219,7 @@ RegisterNetEvent('antidespawn:server:removeVehicle', function(plate) Debug("Fahrzeug entfernt: " .. plate) end) --- Enhanced anti-duplication for vehicle respawning +-- Respawn a vehicle (allow respawning any tracked vehicle) RegisterNetEvent('antidespawn:server:respawnVehicle', function(plate) local src = source local Player = QBCore.Functions.GetPlayer(src) @@ -253,7 +240,7 @@ RegisterNetEvent('antidespawn:server:respawnVehicle', function(plate) activeSpawns[plate] = nil end) - -- Verify ownership before respawning + -- 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) @@ -261,21 +248,6 @@ RegisterNetEvent('antidespawn:server:respawnVehicle', function(plate) return end - -- Check if player owns the vehicle - local isOwner = false - for _, veh in ipairs(result) do - if veh.citizenid == Player.PlayerData.citizenid then - isOwner = true - break - end - end - - if not isOwner then - Debug("Player does not own vehicle: " .. plate) - activeSpawns[plate] = nil - return - end - if not vehicles[plate] then Debug("Fahrzeug nicht in Datenbank: " .. plate) activeSpawns[plate] = nil @@ -311,11 +283,11 @@ RegisterNetEvent('antidespawn:server:respawnVehicle', function(plate) mods = vehicles[plate].mods }) - Debug("Fahrzeug Respawn angefordert: " .. plate) + Debug("Fahrzeug Respawn angefordert: " .. plate .. " (Besitzer: " .. tostring(vehicles[plate].owner) .. ")") end) end) --- Lade Fahrzeuge für einen Spieler +-- 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) @@ -331,83 +303,79 @@ RegisterNetEvent('antidespawn:server:loadVehicles', function() local loadedCount = 0 local vehiclesToLoad = {} - -- Get all vehicles owned by this player - MySQL.query('SELECT * FROM player_vehicles WHERE citizenid = ?', {Player.PlayerData.citizenid}, function(ownedVehicles) - if not ownedVehicles or #ownedVehicles == 0 then - Debug("Spieler besitzt keine Fahrzeuge") - return - end - - -- Create a lookup table for owned vehicles - local ownedPlates = {} - for _, veh in ipairs(ownedVehicles) do - ownedPlates[veh.plate] = veh.state - end - - -- Sammle alle Fahrzeuge, die geladen werden sollen - for plate, vehicle in pairs(vehicles) do - -- Check if player owns this vehicle - if ownedPlates[plate] then - -- Skip if vehicle is in garage (state = 1) - if ownedPlates[plate] == 1 then - Debug("Fahrzeug ist in der Garage, nicht laden: " .. plate) - -- Remove from Anti-Despawn database - vehicles[plate] = nil - MySQL.query("DELETE FROM vehicle_antidespawn WHERE plate = ?", {plate}) - goto continue - 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 - else - -- Vehicle not owned by this player, remove from tracking - Debug("Fahrzeug gehört nicht dem Spieler, entferne aus Tracking: " .. plate) + -- Load all vehicles in the database, not just owned ones + for plate, vehicle in pairs(vehicles) do + -- 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 - ::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) + + -- 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 - Debug("Fahrzeugladung abgeschlossen. " .. loadedCount .. " Fahrzeuge geladen.") + 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) + 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) @@ -462,7 +430,8 @@ RegisterCommand('listvehicles', function(source, args, rawCommand) 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)) + 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.")