770 lines
		
	
	
		
			No EOL
		
	
	
		
			32 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			770 lines
		
	
	
		
			No EOL
		
	
	
		
			32 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
local vehicles = {}
 | 
						|
local DB_vehicles = {}
 | 
						|
 | 
						|
-- Command to delete ALL vehicles from the database table. Needs to be executed twice for security reason.
 | 
						|
local deleteSavedVehicles = false
 | 
						|
RegisterCommand("deleteSavedVehicles", function(source, args, raw)
 | 
						|
    if (deleteSavedVehicles) then
 | 
						|
        MySQL.query("DELETE FROM vehicle_parking", { })
 | 
						|
 | 
						|
        vehicles = {}
 | 
						|
 | 
						|
        Log("Deleted all vehicles from the vehicle_parking table.")
 | 
						|
    else
 | 
						|
        Log("Are you sure that you want to delete all vehicles from the parking list?\nIf yes, type the command a second time!")
 | 
						|
    end
 | 
						|
 | 
						|
    deleteSavedVehicles = not deleteSavedVehicles
 | 
						|
end, true)
 | 
						|
 | 
						|
-- read all vehicles from the database on startup and do a cleanup check
 | 
						|
MySQL.ready(function()
 | 
						|
    -- fetch all database results
 | 
						|
    MySQL.query("SELECT plate, posX, posY, posZ, rotX, rotY, rotZ, modifications, lastUpdate FROM vehicle_parking", {}, function(results)
 | 
						|
        Log("Found " .. #results .. " saved vehicles in vehicle_parking.")
 | 
						|
 | 
						|
        for i = 1, #results do
 | 
						|
            vehicles[results[i].plate] = {
 | 
						|
                handle          = nil,
 | 
						|
                position        = vector3(results[i].posX, results[i].posY, results[i].posZ),
 | 
						|
                rotation        = vector3(results[i].rotX, results[i].rotY, results[i].rotZ),
 | 
						|
                modifications   = json.decode(results[i].modifications),
 | 
						|
                lastUpdate      = results[i].lastUpdate,
 | 
						|
                spawning        = false,
 | 
						|
	            spawningPlayer  = nil,
 | 
						|
                faultyModel     = false
 | 
						|
            }
 | 
						|
        end
 | 
						|
 | 
						|
        --CleanUp()
 | 
						|
    end)
 | 
						|
end)
 | 
						|
 | 
						|
-- Default CleanUp function. Deletes vehicles from the database after a specific amount of time has passed (configurable in config)
 | 
						|
function CleanUp()
 | 
						|
    local currentTime = os.time()
 | 
						|
    local threshold = 60 * 60 * Config.cleanUpThresholdTime
 | 
						|
 | 
						|
    local toDelete = {}
 | 
						|
 | 
						|
    for plate, vehicle in pairs(vehicles) do
 | 
						|
        if (vehicle.lastUpdate < os.difftime(currentTime, threshold)) then
 | 
						|
            
 | 
						|
            MySQL.query("DELETE FROM vehicle_parking WHERE plate = @plate",
 | 
						|
            {
 | 
						|
                ["@plate"] = plate
 | 
						|
            })
 | 
						|
 | 
						|
            table.insert(toDelete, plate)
 | 
						|
        end
 | 
						|
    end
 | 
						|
    
 | 
						|
    for i = 1, #toDelete, 1 do
 | 
						|
        local plate = toDelete[i]
 | 
						|
        vehicles[plate] = nil
 | 
						|
    end
 | 
						|
 | 
						|
    Log("CleanUp complete. Deleted " .. #toDelete .. " entries.")
 | 
						|
end
 | 
						|
 | 
						|
 | 
						|
 | 
						|
-- loop to spawn vehicles near players
 | 
						|
Citizen.CreateThread(function()
 | 
						|
    while (true) do
 | 
						|
        Citizen.Wait(5000)
 | 
						|
 | 
						|
        if (GetActivePlayerCount() > 0) then
 | 
						|
            TrySpawnVehicles()
 | 
						|
        end
 | 
						|
    end
 | 
						|
end)
 | 
						|
 | 
						|
Citizen.CreateThread(function()
 | 
						|
    while (true) do
 | 
						|
        CallDB_Vehicles()
 | 
						|
        Citizen.Wait(60000 * 5)
 | 
						|
    end
 | 
						|
end)
 | 
						|
 | 
						|
-- loop to delete vehicles
 | 
						|
Citizen.CreateThread(function()
 | 
						|
    if (Config.deleteTimer <= 0) then
 | 
						|
        return
 | 
						|
    end
 | 
						|
 | 
						|
    while (true) do
 | 
						|
        Citizen.Wait(60000 * (Config.deleteTimer - Config.deleteNotificationTimes[1]))
 | 
						|
 | 
						|
        TriggerClientEvent("mh_Parking:notification", -1, string.format(Config.timeLeftNotification, Config.deleteNotificationTimes[1]))
 | 
						|
        for i = 2, #Config.deleteNotificationTimes, 1 do
 | 
						|
            Citizen.Wait(60000 * (Config.deleteNotificationTimes[i - 1] - Config.deleteNotificationTimes[i]))
 | 
						|
            TriggerClientEvent("mh_Parking:notification", -1, string.format(Config.timeLeftNotification, Config.deleteNotificationTimes[i]))
 | 
						|
        end
 | 
						|
        Citizen.Wait(60000 * Config.deleteNotificationTimes[#Config.deleteNotificationTimes])
 | 
						|
 | 
						|
        DeleteAllVehicles()
 | 
						|
    end
 | 
						|
end)
 | 
						|
 | 
						|
 | 
						|
 | 
						|
-- sync player position
 | 
						|
RegisterServerEvent("mh_Parking:syncPlayerPosition")
 | 
						|
AddEventHandler("mh_Parking:syncPlayerPosition", function(position)
 | 
						|
    activePlayerPositions[source] = position
 | 
						|
end)
 | 
						|
 | 
						|
-- player disconnected
 | 
						|
AddEventHandler("playerDropped", function(disconnectReason)
 | 
						|
    activePlayerPositions[source] = nil
 | 
						|
end)
 | 
						|
 | 
						|
-- player entered a vehicle
 | 
						|
RegisterServerEvent("mh_Parking:enteredVehicle")
 | 
						|
AddEventHandler("mh_Parking:enteredVehicle", function(networkId, plate, modifications)
 | 
						|
    local vehicle = NetworkGetEntityFromNetworkId(networkId)
 | 
						|
 | 
						|
    if (DoesEntityExist(vehicle)) then
 | 
						|
        local currentTime = os.time()
 | 
						|
        
 | 
						|
        local position = GetEntityCoords(vehicle)
 | 
						|
        position = vector3(math.floor(position.x * 100.0) / 100.0, math.floor(position.y * 100.0) / 100.0, math.floor(position.z * 100.0) / 100.0)
 | 
						|
        local rotation = GetEntityRotation(vehicle)
 | 
						|
        rotation = vector3(math.floor(rotation.x * 100.0) / 100.0, math.floor(rotation.y * 100.0) / 100.0, math.floor(rotation.z * 100.0) / 100.0)
 | 
						|
        
 | 
						|
        if (vehicles[plate]) then
 | 
						|
            -- already on server list
 | 
						|
 | 
						|
            Log("Entered vehicle " .. plate .. ". Updating...")
 | 
						|
            
 | 
						|
            if (vehicles[plate].handle ~= vehicle) then
 | 
						|
                if (DoesEntityExist(vehicles[plate].handle)) then
 | 
						|
                    DeleteEntity(vehicles[plate].handle)
 | 
						|
                end
 | 
						|
                
 | 
						|
                vehicles[plate].handle = vehicle
 | 
						|
            end
 | 
						|
 | 
						|
            vehicles[plate].position = position
 | 
						|
            vehicles[plate].rotation = rotation
 | 
						|
            vehicles[plate].modifications = modifications
 | 
						|
            vehicles[plate].lastUpdate = currentTime
 | 
						|
            
 | 
						|
            MySQL.query("UPDATE vehicle_parking SET posX = @posX, posY = @posY, posZ = @posZ, rotX = @rotX, rotY = @rotY, rotZ = @rotZ, modifications = @modifications, lastUpdate = @lastUpdate WHERE plate = @plate", {
 | 
						|
                ["@plate"]          = plate,
 | 
						|
                ["@posX"]           = vehicles[plate].position.x,
 | 
						|
                ["@posY"]           = vehicles[plate].position.y,
 | 
						|
                ["@posZ"]           = vehicles[plate].position.z,
 | 
						|
                ["@rotX"]           = vehicles[plate].rotation.x,
 | 
						|
                ["@rotY"]           = vehicles[plate].rotation.y,
 | 
						|
                ["@rotZ"]           = vehicles[plate].rotation.z,
 | 
						|
                ["@modifications"]  = json.encode(vehicles[plate].modifications),
 | 
						|
                ["@lastUpdate"]     = vehicles[plate].lastUpdate
 | 
						|
            })
 | 
						|
        else
 | 
						|
            -- insert in db
 | 
						|
            
 | 
						|
            Log("Entered vehicle " .. plate .. ". Inserting new...")
 | 
						|
 | 
						|
            vehicles[plate] = {
 | 
						|
                handle          = vehicle,
 | 
						|
                position        = position,
 | 
						|
                rotation        = rotation,
 | 
						|
                modifications   = modifications,
 | 
						|
                lastUpdate      = currentTime,
 | 
						|
                spawning        = false,
 | 
						|
	            spawningPlayer  = nil
 | 
						|
            }
 | 
						|
 | 
						|
            MySQL.query('SELECT * FROM player_vehicles WHERE plate = @plate', { ['@plate'] = plate }, function(rs)
 | 
						|
                Log(json.encode(rs))
 | 
						|
                if rs[1] then
 | 
						|
                    Log("FOUND OWNER FROM VEHICLE")
 | 
						|
 | 
						|
                    MySQL.query("INSERT INTO vehicle_parking (plate, posX, posY, posZ, rotX, rotY, rotZ, modifications, lastUpdate) VALUES (@plate, @posX, @posY, @posZ, @rotX, @rotY, @rotZ, @modifications, @lastUpdate)", {
 | 
						|
                        ["@plate"]          = plate,
 | 
						|
                        ["@posX"]           = vehicles[plate].position.x,
 | 
						|
                        ["@posY"]           = vehicles[plate].position.y,
 | 
						|
                        ["@posZ"]           = vehicles[plate].position.z,
 | 
						|
                        ["@rotX"]           = vehicles[plate].rotation.x,
 | 
						|
                        ["@rotY"]           = vehicles[plate].rotation.y,
 | 
						|
                        ["@rotZ"]           = vehicles[plate].rotation.z,
 | 
						|
                        ["@modifications"]  = json.encode(vehicles[plate].modifications),
 | 
						|
                        ["@lastUpdate"]     = vehicles[plate].lastUpdate
 | 
						|
                    })
 | 
						|
                else
 | 
						|
                    Log("1: NO VEHICLE FOUND")
 | 
						|
                end
 | 
						|
            end)
 | 
						|
        end
 | 
						|
    else
 | 
						|
        Log("Vehicle does not exist. Might be a Onesync error.")
 | 
						|
    end
 | 
						|
end)
 | 
						|
 | 
						|
-- player left a vehicle
 | 
						|
RegisterServerEvent("mh_Parking:leftVehicle")
 | 
						|
AddEventHandler("mh_Parking:leftVehicle", function(networkId, modifications)
 | 
						|
    local vehicle = NetworkGetEntityFromNetworkId(networkId)
 | 
						|
 | 
						|
    if (DoesEntityExist(vehicle)) then
 | 
						|
        local currentTime = os.time()
 | 
						|
        
 | 
						|
        local plate = GetVehicleNumberPlateText(vehicle)
 | 
						|
        
 | 
						|
        local position = GetEntityCoords(vehicle)
 | 
						|
        position = vector3(math.floor(position.x * 100.0) / 100.0, math.floor(position.y * 100.0) / 100.0, math.floor(position.z * 100.0) / 100.0)
 | 
						|
        local rotation = GetEntityRotation(vehicle)
 | 
						|
        rotation = vector3(math.floor(rotation.x * 100.0) / 100.0, math.floor(rotation.y * 100.0) / 100.0, math.floor(rotation.z * 100.0) / 100.0)
 | 
						|
        
 | 
						|
        if (vehicles[plate]) then
 | 
						|
            -- already on server list
 | 
						|
            
 | 
						|
            Log("Left vehicle " .. plate .. ". Updating...")
 | 
						|
            
 | 
						|
            if (vehicles[plate].handle ~= vehicle) then
 | 
						|
                if (DoesEntityExist(vehicles[plate].handle)) then
 | 
						|
                    DeleteEntity(vehicles[plate].handle)
 | 
						|
                end
 | 
						|
                
 | 
						|
                vehicles[plate].handle = vehicle
 | 
						|
            end
 | 
						|
 | 
						|
            vehicles[plate].position = position
 | 
						|
            vehicles[plate].rotation = rotation
 | 
						|
            vehicles[plate].modifications = modifications
 | 
						|
            vehicles[plate].lastUpdate = currentTime
 | 
						|
 | 
						|
            MySQL.query("UPDATE vehicle_parking SET posX = @posX, posY = @posY, posZ = @posZ, rotX = @rotX, rotY = @rotY, rotZ = @rotZ, modifications = @modifications, lastUpdate = @lastUpdate WHERE plate = @plate",{
 | 
						|
                ["@plate"]          = plate,
 | 
						|
                ["@posX"]           = vehicles[plate].position.x,
 | 
						|
                ["@posY"]           = vehicles[plate].position.y,
 | 
						|
                ["@posZ"]           = vehicles[plate].position.z,
 | 
						|
                ["@rotX"]           = vehicles[plate].rotation.x,
 | 
						|
                ["@rotY"]           = vehicles[plate].rotation.y,
 | 
						|
                ["@rotZ"]           = vehicles[plate].rotation.z,
 | 
						|
                ["@modifications"]  = json.encode(vehicles[plate].modifications),
 | 
						|
                ["@lastUpdate"]     = currentTime
 | 
						|
            })
 | 
						|
        else
 | 
						|
            -- insert in db
 | 
						|
            
 | 
						|
            Log("Left vehicle " .. plate .. ". Inserting new...")
 | 
						|
            
 | 
						|
            vehicles[plate] = {
 | 
						|
                handle          = vehicle,
 | 
						|
                position        = position,
 | 
						|
                rotation        = rotation,
 | 
						|
                modifications   = modifications,
 | 
						|
                lastUpdate      = currentTime,
 | 
						|
                spawning        = false,
 | 
						|
	            spawningPlayer  = nil
 | 
						|
            }
 | 
						|
 | 
						|
            MySQL.query('SELECT * FROM player_vehicles WHERE plate = @plate', { ['@plate'] = plate }, function(rs)
 | 
						|
                if rs[1] then
 | 
						|
                    Log("FOUND OWNER FROM VEHICLE")
 | 
						|
 | 
						|
                    MySQL.query("INSERT INTO vehicle_parking (plate, posX, posY, posZ, rotX, rotY, rotZ, modifications, lastUpdate) VALUES (@plate, @posX, @posY, @posZ, @rotX, @rotY, @rotZ, @modifications, @lastUpdate)",{
 | 
						|
                        ["@plate"]          = plate,
 | 
						|
                        ["@posX"]           = vehicles[plate].position.x,
 | 
						|
                        ["@posY"]           = vehicles[plate].position.y,
 | 
						|
                        ["@posZ"]           = vehicles[plate].position.z,
 | 
						|
                        ["@rotX"]           = vehicles[plate].rotation.x,
 | 
						|
                        ["@rotY"]           = vehicles[plate].rotation.y,
 | 
						|
                        ["@rotZ"]           = vehicles[plate].rotation.z,
 | 
						|
                        ["@modifications"]  = json.encode(vehicles[plate].modifications),
 | 
						|
                        ["@lastUpdate"]     = vehicles[plate].lastUpdate
 | 
						|
                    })
 | 
						|
                else
 | 
						|
                    Log("2: NO VEHICLE FOUND")
 | 
						|
                end
 | 
						|
            end)
 | 
						|
        end
 | 
						|
    end
 | 
						|
end)
 | 
						|
 | 
						|
-- update a vehicle with its modifications
 | 
						|
RegisterServerEvent("mh_Parking:updateVehicle")
 | 
						|
AddEventHandler("mh_Parking:updateVehicle", function(networkId, modifications)
 | 
						|
    local vehicle = NetworkGetEntityFromNetworkId(networkId)
 | 
						|
    
 | 
						|
    if (DoesEntityExist(vehicle)) then
 | 
						|
        local currentTime = os.time()
 | 
						|
 | 
						|
        local plate = GetVehicleNumberPlateText(vehicle)
 | 
						|
        
 | 
						|
        local position = GetEntityCoords(vehicle)
 | 
						|
        position = vector3(math.floor(position.x * 100.0) / 100.0, math.floor(position.y * 100.0) / 100.0, math.floor(position.z * 100.0) / 100.0)
 | 
						|
        local rotation = GetEntityRotation(vehicle)
 | 
						|
        rotation = vector3(math.floor(rotation.x * 100.0) / 100.0, math.floor(rotation.y * 100.0) / 100.0, math.floor(rotation.z * 100.0) / 100.0)
 | 
						|
        
 | 
						|
        if (vehicles[plate] ~= nil) then
 | 
						|
            -- already on server list
 | 
						|
            
 | 
						|
            Log("Updating vehicle " .. plate)
 | 
						|
            
 | 
						|
            if (vehicles[plate].handle ~= vehicle) then
 | 
						|
                if (DoesEntityExist(vehicles[plate].handle)) then
 | 
						|
                    DeleteEntity(vehicles[plate].handle)
 | 
						|
                end
 | 
						|
 | 
						|
                vehicles[plate].handle = vehicle
 | 
						|
            end
 | 
						|
 | 
						|
            vehicles[plate].position = position
 | 
						|
            vehicles[plate].rotation = rotation
 | 
						|
            vehicles[plate].modifications = modifications
 | 
						|
            vehicles[plate].lastUpdate = currentTime
 | 
						|
 | 
						|
            MySQL.query("UPDATE vehicle_parking SET posX = @posX, posY = @posY, posZ = @posZ, rotX = @rotX, rotY = @rotY, rotZ = @rotZ, modifications = @modifications, lastUpdate = @lastUpdate WHERE plate = @plate",{
 | 
						|
                ["@plate"]          = plate,
 | 
						|
                ["@posX"]           = vehicles[plate].position.x,
 | 
						|
                ["@posY"]           = vehicles[plate].position.y,
 | 
						|
                ["@posZ"]           = vehicles[plate].position.z,
 | 
						|
                ["@rotX"]           = vehicles[plate].rotation.x,
 | 
						|
                ["@rotY"]           = vehicles[plate].rotation.y,
 | 
						|
                ["@rotZ"]           = vehicles[plate].rotation.z,
 | 
						|
                ["@modifications"]  = json.encode(vehicles[plate].modifications),
 | 
						|
                ["@lastUpdate"]     = vehicles[plate].lastUpdate
 | 
						|
            })
 | 
						|
        else
 | 
						|
            -- insert in db
 | 
						|
            
 | 
						|
            Log("Updating vehicle " .. plate .. ". Inserting new...")
 | 
						|
            
 | 
						|
            vehicles[plate] = {
 | 
						|
                handle          = vehicle,
 | 
						|
                position        = position,
 | 
						|
                rotation        = rotation,
 | 
						|
                modifications   = modifications,
 | 
						|
                lastUpdate      = currentTime,
 | 
						|
                spawning        = false,
 | 
						|
	            spawningPlayer  = nil
 | 
						|
            }
 | 
						|
 | 
						|
            MySQL.query('SELECT * FROM player_vehicles WHERE plate = @plate', { ['@plate'] = plate }, function(rs)
 | 
						|
                if rs[1] then
 | 
						|
                    Log("FOUND OWNER FROM VEHICLE")
 | 
						|
 | 
						|
                    MySQL.query("INSERT INTO vehicle_parking (plate, posX, posY, posZ, rotX, rotY, rotZ, modifications, lastUpdate) VALUES (@plate, @posX, @posY, @posZ, @rotX, @rotY, @rotZ, @modifications, @lastUpdate)",{
 | 
						|
                        ["@plate"]          = plate,
 | 
						|
                        ["@posX"]           = vehicles[plate].position.x,
 | 
						|
                        ["@posY"]           = vehicles[plate].position.y,
 | 
						|
                        ["@posZ"]           = vehicles[plate].position.z,
 | 
						|
                        ["@rotX"]           = vehicles[plate].rotation.x,
 | 
						|
                        ["@rotY"]           = vehicles[plate].rotation.y,
 | 
						|
                        ["@rotZ"]           = vehicles[plate].rotation.z,
 | 
						|
                        ["@modifications"]  = json.encode(vehicles[plate].modifications),
 | 
						|
                        ["@lastUpdate"]     = vehicles[plate].lastUpdate
 | 
						|
                    })
 | 
						|
                else
 | 
						|
                    Log("3: NO VEHICLE FOUND")
 | 
						|
                end
 | 
						|
            end)
 | 
						|
        end
 | 
						|
    end
 | 
						|
end)
 | 
						|
 | 
						|
-- delete a vehicle from the table (and world) with its plate
 | 
						|
RegisterServerEvent("mh_Parking:deleteVehicle")
 | 
						|
AddEventHandler("mh_Parking:deleteVehicle", function(plate, deleteEntity)
 | 
						|
    if (plate == nil) then
 | 
						|
        Log("^1mh_Parking: \"plate\" was nil while trying to delete vehicle!")
 | 
						|
        return
 | 
						|
    end
 | 
						|
 | 
						|
    Log("Trying to delete " .. tostring(plate))
 | 
						|
 | 
						|
    if (vehicles[plate] ~= nil) then
 | 
						|
        if (deleteEntity and DoesEntityExist(vehicles[plate].handle)) then
 | 
						|
            DeleteEntity(vehicles[plate].handle)
 | 
						|
        end
 | 
						|
 | 
						|
        vehicles[plate] = nil
 | 
						|
        
 | 
						|
        MySQL.query("DELETE FROM vehicle_parking WHERE plate = @plate",
 | 
						|
        {
 | 
						|
            ["@plate"] = plate
 | 
						|
        })
 | 
						|
    else
 | 
						|
        local loadedVehicles = GetAllVehicles()
 | 
						|
        local loadedVehicle = TryGetLoadedVehicle(plate, loadedVehicles)
 | 
						|
 | 
						|
        if (loadedVehicle ~= nil) then
 | 
						|
            if (deleteEntity and DoesEntityExist(loadedVehicle)) then
 | 
						|
                DeleteEntity(loadedVehicle)
 | 
						|
            end
 | 
						|
            
 | 
						|
            MySQL.query("DELETE FROM vehicle_parking WHERE plate = @plate",
 | 
						|
            {
 | 
						|
                ["@plate"] = plate
 | 
						|
            })
 | 
						|
        end
 | 
						|
    end
 | 
						|
end)
 | 
						|
 | 
						|
-- checks if vehicles have to be spawned and spawns them if necessary
 | 
						|
function TrySpawnVehicles()
 | 
						|
    local loadedVehicles = GetAllVehicles()
 | 
						|
 | 
						|
    local playerVehiclePlates = {}
 | 
						|
    for id, position in pairs(activePlayerPositions) do
 | 
						|
        local ped = GetPlayerPed(id)
 | 
						|
        local veh = GetVehiclePedIsIn(ped, false)
 | 
						|
 | 
						|
        if (DoesEntityExist(veh)) then
 | 
						|
            table.insert(playerVehiclePlates, GetVehicleNumberPlateText(veh))
 | 
						|
        end
 | 
						|
    end
 | 
						|
 | 
						|
    -- check, if vehicles need to be spawned
 | 
						|
    for plate, vehicleData in pairs(vehicles) do
 | 
						|
        local plateCheck = CheckPlate(plate)
 | 
						|
        if (plateCheck ~= false) then
 | 
						|
 | 
						|
            if (not vehicleData.faultyModel) then
 | 
						|
                if (not vehicleData.spawning) then
 | 
						|
                    local closestPlayer, dist = GetClosestPlayerId(vehicleData.position)
 | 
						|
    
 | 
						|
                    if (closestPlayer ~= nil and dist < Config.spawnDistance and not ContainsPlate(plate, playerVehiclePlates)) then
 | 
						|
                        if (vehicleData.handle ~= nil and DoesEntityExist(vehicleData.handle)) then
 | 
						|
                            -- vehicle found on server side
 | 
						|
                        
 | 
						|
                            UpdateVehicle(plate)
 | 
						|
                        else
 | 
						|
                            -- vehicle not found on server side
 | 
						|
                            -- check, if it is loaded differently
 | 
						|
    
 | 
						|
                            local loadedVehicle = TryGetLoadedVehicle(plate, loadedVehicles)
 | 
						|
                            if (loadedVehicle ~= nil) then
 | 
						|
                                -- vehicle found
 | 
						|
    
 | 
						|
                                vehicleData.handle = loadedVehicle
 | 
						|
                        
 | 
						|
                                UpdateVehicle(plate)
 | 
						|
                            else
 | 
						|
                                -- vehicle not found
 | 
						|
                                -- try and spawn it
 | 
						|
                        
 | 
						|
                                local playerId, distance = GetClosestPlayerId(vehicleData.position)
 | 
						|
                                if (playerId and distance < Config.spawnDistance) then
 | 
						|
                                    vehicleData.spawning = true
 | 
						|
    
 | 
						|
                                    Citizen.CreateThread(function()
 | 
						|
                                        local vec4 = vector4(vehicleData.position.x, vehicleData.position.y, vehicleData.position.z, vehicleData.rotation.z)
 | 
						|
                                        local vehicle = Citizen.InvokeNative(GetHashKey("CREATE_AUTOMOBILE"), vehicleData.modifications[1], vec4.xyzw)
 | 
						|
    
 | 
						|
                                        while (not DoesEntityExist(vehicle)) do
 | 
						|
                                            Citizen.Wait(0)
 | 
						|
                                        end
 | 
						|
    
 | 
						|
                                        SetEntityCoords(vehicle, vehicleData.position.x, vehicleData.position.y, vehicleData.position.z)
 | 
						|
                                        SetEntityRotation(vehicle, vehicleData.rotation.x, vehicleData.rotation.y, vehicleData.rotation.z)
 | 
						|
    
 | 
						|
                                        vehicleData.handle = vehicle
 | 
						|
                                    
 | 
						|
                                        local networkOwner = -1
 | 
						|
                                        while (networkOwner == -1) do
 | 
						|
                                            Citizen.Wait(0)
 | 
						|
                                            networkOwner = NetworkGetEntityOwner(vehicleData.handle)
 | 
						|
                                        end
 | 
						|
    
 | 
						|
                                        vehicleData.spawningPlayer = GetPlayerIdentifiersSorted(networkOwner)["license"]
 | 
						|
                                    
 | 
						|
                                        Log("Creating vehicle " .. plate .. " at " .. tostring(vehicleData.position) .. " at entity owner " .. tostring(networkOwner))
 | 
						|
    
 | 
						|
                                        TriggerClientEvent("mh_Parking:setVehicleMods", networkOwner, NetworkGetNetworkIdFromEntity(vehicleData.handle), plate, vehicleData.modifications)
 | 
						|
                                    end)
 | 
						|
                                end
 | 
						|
                            end
 | 
						|
                        end
 | 
						|
                    end
 | 
						|
                elseif (vehicleData.spawningPlayer) then
 | 
						|
                    -- if vehicle is currently spawning check if responsible player is still connected
 | 
						|
                    if (not IsPlayerWithLicenseActive(vehicleData.spawningPlayer)) then
 | 
						|
                        TriggerEvent("mh_Parking:setVehicleModsFailed", plate)
 | 
						|
                    end
 | 
						|
                end
 | 
						|
            end
 | 
						|
        end
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
RegisterServerEvent("mh_Parking:setVehicleModsSuccess")
 | 
						|
AddEventHandler("mh_Parking:setVehicleModsSuccess", function(plate)
 | 
						|
    Log("Setting mods successful...")
 | 
						|
 | 
						|
    if (vehicles[plate]) then
 | 
						|
        vehicles[plate].spawning = false
 | 
						|
        vehicles[plate].spawningPlayer = nil
 | 
						|
    end
 | 
						|
end)
 | 
						|
 | 
						|
RegisterServerEvent("mh_Parking:setVehicleModsFailed")
 | 
						|
AddEventHandler("mh_Parking:setVehicleModsFailed", function(plate)
 | 
						|
    Log("Setting mods for " .. plate .. " failed... retrying...")
 | 
						|
 | 
						|
    if (vehicles[plate] and vehicles[plate].handle and DoesEntityExist(vehicles[plate].handle)) then
 | 
						|
        local networkOwner = -1
 | 
						|
        while (networkOwner == -1) do
 | 
						|
            Citizen.Wait(0)
 | 
						|
            networkOwner = NetworkGetEntityOwner(vehicles[plate].handle)
 | 
						|
        end
 | 
						|
 | 
						|
        local netOwnerLicense = GetPlayerIdentifiersSorted(networkOwner)["license"]
 | 
						|
        if (netOwnerLicense ~= nil) then
 | 
						|
            vehicles[plate].spawningPlayer = GetPlayerIdentifiersSorted(networkOwner)["license"]
 | 
						|
 | 
						|
            TriggerClientEvent("mh_Parking:setVehicleMods", networkOwner, NetworkGetNetworkIdFromEntity(vehicles[plate].handle), plate, vehicles[plate].modifications)
 | 
						|
        else
 | 
						|
            Log("Something went wrong while trying to get player license for spawning vehicle " .. tostring(plate) .. ". Despawning vehicle")
 | 
						|
 | 
						|
            DeleteEntity(vehicles[plate].handle)
 | 
						|
 | 
						|
            vehicles[plate].handle = nil
 | 
						|
            vehicles[plate].spawningPlayer = nil
 | 
						|
            vehicles[plate].spawning = false
 | 
						|
        end
 | 
						|
    end
 | 
						|
end)
 | 
						|
 | 
						|
RegisterServerEvent("mh_Parking:modelDoesNotExist")
 | 
						|
AddEventHandler("mh_Parking:modelDoesNotExist", function(plate)
 | 
						|
    if (vehicles[plate] == nil) then
 | 
						|
        return
 | 
						|
    end
 | 
						|
 | 
						|
    if (DoesEntityExist(vehicles[plate].handle)) then
 | 
						|
        DeleteEntity(vehicles[plate].handle)
 | 
						|
    end
 | 
						|
    vehicles[plate].handle = nil
 | 
						|
    vehicles[plate].spawningPlayer = nil
 | 
						|
    vehicles[plate].spawning = false
 | 
						|
 | 
						|
    Log("The model for vehicle " .. tostring(plate) .. " does not exist. Removing from spawn pool...")
 | 
						|
 | 
						|
    vehicles[plate].faultyModel = true
 | 
						|
end)
 | 
						|
 | 
						|
RegisterServerEvent("mh_Parking:updatePlate")
 | 
						|
AddEventHandler("mh_Parking:updatePlate", function(oldPlate, newPlate)
 | 
						|
    if (oldPlate == nil or newPlate == nil) then
 | 
						|
        Log("^1mh_Parking: \"oldPlate\" or \"newPlate\" was nil while trying to update a plate!")
 | 
						|
        return
 | 
						|
    end
 | 
						|
 | 
						|
    if (vehicles[oldPlate]) then
 | 
						|
        if (vehicles[newPlate]) then
 | 
						|
            Log("Updating plate failed. New plate was already there!")
 | 
						|
        else
 | 
						|
            vehicles[newPlate] = vehicles[oldPlate]
 | 
						|
            vehicles[oldPlate] = nil
 | 
						|
            
 | 
						|
            Log("Updating plate successful!")
 | 
						|
 | 
						|
            MySQL.query("UPDATE vehicle_parking SET plate = @newPlate WHERE plate = @oldPlate",
 | 
						|
            {
 | 
						|
                ["@newPlate"] = newPlate,
 | 
						|
                ["@oldPlate"] = oldPlate
 | 
						|
            })
 | 
						|
        end
 | 
						|
    else
 | 
						|
        Log("Updating plate failed or unnecessary. Old plate was not found!")
 | 
						|
    end
 | 
						|
end)
 | 
						|
 | 
						|
function UpdateVehicle(plate)
 | 
						|
    local newPos = GetEntityCoords(vehicles[plate].handle)
 | 
						|
    local newRot = GetEntityRotation(vehicles[plate].handle)
 | 
						|
    newPos = vector3(math.floor(newPos.x * 100.0) * 0.01, math.floor(newPos.y * 100.0) * 0.01, math.floor(newPos.z * 100.0) * 0.01)
 | 
						|
    newRot = vector3(math.floor(newRot.x * 100.0) * 0.01, math.floor(newRot.y * 100.0) * 0.01, math.floor(newRot.z * 100.0) * 0.01)
 | 
						|
            
 | 
						|
    local newLockStatus     = GetVehicleDoorLockStatus(vehicles[plate].handle)
 | 
						|
    local newEngineHealth   = math.floor(GetVehicleEngineHealth(vehicles[plate].handle) * 10.0) * 0.1
 | 
						|
    local newTankHealth     = math.floor(GetVehiclePetrolTankHealth(vehicles[plate].handle) * 10.0) * 0.1
 | 
						|
    if (Vector3DistFast(vehicles[plate].position, newPos) > 1.0 
 | 
						|
        or GetRotationDifference(vehicles[plate].rotation, newRot) > 15.0
 | 
						|
        or newLockStatus ~= vehicles[plate].modifications[2]
 | 
						|
        or math.abs(newEngineHealth - vehicles[plate].modifications[5]) > 5.0
 | 
						|
        or math.abs(newTankHealth - vehicles[plate].modifications[6]) > 5.0
 | 
						|
    ) then
 | 
						|
        vehicles[plate].modifications[2] = newLockStatus
 | 
						|
        vehicles[plate].modifications[5] = newEngineHealth
 | 
						|
        vehicles[plate].modifications[6] = newTankHealth
 | 
						|
                
 | 
						|
        Log("Updating vehicle " .. plate)
 | 
						|
        
 | 
						|
        vehicles[plate].position = newPos
 | 
						|
        vehicles[plate].rotation = newRot
 | 
						|
 | 
						|
        MySQL.query("UPDATE vehicle_parking SET posX = @posX, posY = @posY, posZ = @posZ, rotX = @rotX, rotY = @rotY, rotZ = @rotZ, modifications = @modifications WHERE plate = @plate",
 | 
						|
        {
 | 
						|
            ["@posX"]           = vehicles[plate].position.x,
 | 
						|
            ["@posY"]           = vehicles[plate].position.y,
 | 
						|
            ["@posZ"]           = vehicles[plate].position.z,
 | 
						|
            ["@rotX"]           = vehicles[plate].rotation.x,
 | 
						|
            ["@rotY"]           = vehicles[plate].rotation.y,
 | 
						|
            ["@rotZ"]           = vehicles[plate].rotation.z,
 | 
						|
            ["@modifications"]  = json.encode(vehicles[plate].modifications),
 | 
						|
            ["@plate"]          = plate
 | 
						|
        })
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
function DeleteAllVehicles()
 | 
						|
    TriggerClientEvent("mh_Parking:notification", -1, Config.deleteNotification)
 | 
						|
 | 
						|
    local peds = GetAllPeds()
 | 
						|
    local playerPeds = {}
 | 
						|
    for i = 1, #peds, 1 do
 | 
						|
        if (IsPedAPlayer(peds[i])) then
 | 
						|
            table.insert(playerPeds, peds[i])
 | 
						|
        end
 | 
						|
    end
 | 
						|
 | 
						|
    if (#playerPeds == 0) then
 | 
						|
        return
 | 
						|
    end
 | 
						|
    
 | 
						|
    local time = GetGameTimer()
 | 
						|
 | 
						|
    local vehs = GetAllVehicles()
 | 
						|
    local deleted = 0
 | 
						|
    for i = 1, #vehs, 1 do
 | 
						|
        if (not IsAnyPlayerInsideVehicle(vehs[i], playerPeds)) then
 | 
						|
            local closestPlayer, distance = GetClosestPlayerPed(GetEntityCoords(vehs[i]), playerPeds)
 | 
						|
            if (closestPlayer ~= nil and distance > Config.deleteDistance) then
 | 
						|
                local plate = GetVehicleNumberPlateText(vehs[i])
 | 
						|
                if (vehicles[plate] ~= nil) then
 | 
						|
                    vehicles[plate] = nil
 | 
						|
                    
 | 
						|
                    MySQL.query("DELETE FROM vehicle_parking WHERE plate = @plate",
 | 
						|
                    {
 | 
						|
                        ["@plate"] = plate
 | 
						|
                    })
 | 
						|
                end
 | 
						|
 | 
						|
                DeleteEntity(vehs[i])
 | 
						|
 | 
						|
                deleted = deleted + 1
 | 
						|
            end
 | 
						|
        end
 | 
						|
    end
 | 
						|
    
 | 
						|
    Log("Deleted " .. tostring(deleted) .. "/" .. tostring(#vehs) .. " vehicles. Took " .. tostring((GetGameTimer() - time) / 1000.0) .. "sec")
 | 
						|
end
 | 
						|
 | 
						|
AddEventHandler("onResourceStop", function(name)
 | 
						|
    if (name ~= GetCurrentResourceName()) then
 | 
						|
        return
 | 
						|
    end
 | 
						|
 | 
						|
    -- delete vehicles that are still being spawned before actually stopping the resource
 | 
						|
    for plate, vehicleData in pairs(vehicles) do
 | 
						|
        if (vehicleData.spawning and DoesEntityExist(vehicleData.handle)) then
 | 
						|
            DeleteEntity(vehicleData.handle)
 | 
						|
        end
 | 
						|
    end
 | 
						|
end)
 | 
						|
 | 
						|
-- render entity scorched (trigger with netid of the vehicle and false when repairing)
 | 
						|
RegisterServerEvent("mh_Parking:renderScorched")
 | 
						|
AddEventHandler("mh_Parking:renderScorched", function(vehicleNetId, scorched)
 | 
						|
    local vehicleHandle = NetworkGetEntityFromNetworkId(vehicleNetId)
 | 
						|
    if (DoesEntityExist(vehicleHandle)) then
 | 
						|
        TriggerClientEvent("mh_Parking:renderScorched", -1, vehicleNetId, scorched)
 | 
						|
    end
 | 
						|
end)
 | 
						|
 | 
						|
if (GetResourceState("kimi_callbacks") == "started") then
 | 
						|
    exports["kimi_callbacks"]:Register("AP:getVehiclePosition", function(source, plate)
 | 
						|
        local vehs = GetAllVehicles()
 | 
						|
    
 | 
						|
        for i, veh in ipairs(vehs) do
 | 
						|
            local vehPlate = GetVehicleNumberPlateText(veh)
 | 
						|
            if (plate == vehPlate or plate == string.gsub(vehPlate, "^%s*(.-)%s*$", "%1")) then
 | 
						|
                return GetEntityCoords(veh)
 | 
						|
            end
 | 
						|
        end
 | 
						|
 | 
						|
        for vehPlate, vehData in pairs(vehicles) do
 | 
						|
            if (plate == vehPlate or plate == string.gsub(vehPlate, "^%s*(.-)%s*$", "%1")) then
 | 
						|
                return vehData.position
 | 
						|
            end
 | 
						|
        end
 | 
						|
    
 | 
						|
        return nil
 | 
						|
    end)
 | 
						|
 | 
						|
    exports["kimi_callbacks"]:Register("AP:getVehiclePositions", function(source, plates)
 | 
						|
        local platePositions = {}
 | 
						|
    
 | 
						|
        Log("Looking for plates:")
 | 
						|
        for i, plate in ipairs(plates) do
 | 
						|
            Log("\"" .. plate .. "\"")
 | 
						|
        end
 | 
						|
 | 
						|
        local vehs = GetAllVehicles()
 | 
						|
        for i, veh in ipairs(vehs) do
 | 
						|
            local vehPlate = GetVehicleNumberPlateText(veh)
 | 
						|
            local trimmedVehPlate = string.gsub(vehPlate, "^%s*(.-)%s*$", "%1")
 | 
						|
 | 
						|
            for j, plate in ipairs(plates) do
 | 
						|
                if (plate == vehPlate or plate == trimmedVehPlate) then
 | 
						|
                    platePositions[plate] = GetEntityCoords(veh)
 | 
						|
 | 
						|
                    break
 | 
						|
                end
 | 
						|
            end
 | 
						|
        end
 | 
						|
    
 | 
						|
        for i, plate in ipairs(plates) do
 | 
						|
            if (platePositions[plate] == nil) then
 | 
						|
                for vehPlate, vehData in pairs(vehicles) do
 | 
						|
                    local trimmedVehPlate = string.gsub(vehPlate, "^%s*(.-)%s*$", "%1")
 | 
						|
 | 
						|
                    if (plate == vehPlate or plate == trimmedVehPlate) then
 | 
						|
                        platePositions[plate] = vehData.position
 | 
						|
 | 
						|
                        break
 | 
						|
                    end
 | 
						|
                end
 | 
						|
            end
 | 
						|
        end
 | 
						|
 | 
						|
        return platePositions
 | 
						|
    end)
 | 
						|
end
 | 
						|
 | 
						|
 | 
						|
RegisterNetEvent('mh_Parking:removeVehicle')
 | 
						|
AddEventHandler('mh_Parking:removeVehicle', function(plate)
 | 
						|
    print("mh_parking: "..plate)
 | 
						|
    vehicles[plate] = nil    
 | 
						|
end)
 | 
						|
 | 
						|
function CallDB_Vehicles()
 | 
						|
    DB_vehicles = {}
 | 
						|
    MySQL.query('SELECT * FROM player_vehicles', {}, function(rs)
 | 
						|
        for k, v in pairs(rs) do
 | 
						|
            table.insert(DB_vehicles, v)
 | 
						|
        end
 | 
						|
    end) --DB_vehicles
 | 
						|
end
 | 
						|
 | 
						|
function CheckPlate(plate) -- DB_Players
 | 
						|
    for k, v in pairs(DB_vehicles) do
 | 
						|
        if Config.isDebug then
 | 
						|
            Log(json.encode(v))
 | 
						|
            Log(plate)
 | 
						|
            Log(v.plate)
 | 
						|
        end
 | 
						|
 | 
						|
        if v.plate == plate then
 | 
						|
            return true
 | 
						|
        end
 | 
						|
    end
 | 
						|
    return false
 | 
						|
end |