769 lines
		
	
	
		
			No EOL
		
	
	
		
			31 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			769 lines
		
	
	
		
			No EOL
		
	
	
		
			31 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)
 | |
|     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 | 
