forked from Simnation/Main
279 lines
7.6 KiB
Lua
279 lines
7.6 KiB
Lua
|
|
-- localise frequently used Lua globals
|
|
local os_time, os_difftime, os_date, math_floor = os.time, os.difftime, os.date, math.floor
|
|
|
|
-- localise frequently used natives
|
|
local DoesEntityExist, GetPlayerRoutingBucket, GetEntityCoords, DeleteEntity, GetVehicleEngineHealth, GetEntityRoutingBucket =
|
|
DoesEntityExist, GetPlayerRoutingBucket, GetEntityCoords, DeleteEntity, GetVehicleEngineHealth, GetEntityRoutingBucket
|
|
|
|
-- task system
|
|
local tasks = {}
|
|
|
|
local function GetTime()
|
|
local time = os_time()
|
|
|
|
return {
|
|
day = tonumber(os_date("%w", time)),
|
|
hour = tonumber(os_date("%H", time)),
|
|
minute = tonumber(os_date("%M", time))
|
|
}
|
|
end
|
|
|
|
local taskRunning = false
|
|
local function StartTaskThread()
|
|
if (taskRunning) then return end
|
|
|
|
taskRunning = true
|
|
|
|
local lastTime = GetTime()
|
|
|
|
while (taskRunning) do
|
|
Wait(1000)
|
|
|
|
local time = GetTime()
|
|
|
|
if (time.minute ~= lastTime.minute or time.hour ~= lastTime.hour or time.day ~= lastTime.day) then
|
|
for i = 1, #tasks do
|
|
if ((not tasks[i].day or tasks[i].day == time.day) and tasks[i].hour == time.hour and tasks[i].minute == time.minute) then
|
|
tasks[i].Run()
|
|
end
|
|
end
|
|
|
|
lastTime = time
|
|
end
|
|
end
|
|
end
|
|
|
|
local function AddTask(task, d, h, m)
|
|
assert(task and type(task) == "function", "Parameter \"task\" must be a function!")
|
|
assert(not d or type(d) == "number", "Parameter \"day\" must be a number!")
|
|
assert(h and type(h) == "number", "Parameter \"hour\" must be a number!")
|
|
assert(m and type(m) == "number", "Parameter \"minute\" must be a number!")
|
|
|
|
tasks[#tasks + 1] = {
|
|
day = d and math_floor(d),
|
|
hour = math_floor(h),
|
|
minute = math_floor(m),
|
|
Run = task
|
|
}
|
|
|
|
if (not taskRunning) then
|
|
CreateThread(StartTaskThread)
|
|
end
|
|
end
|
|
|
|
|
|
|
|
-- get all players sorted by bucket
|
|
local function GetPositionsOfAllPlayersByBucket()
|
|
local playerPositions = {}
|
|
|
|
local players = GetPlayers()
|
|
for i = 1, #players do
|
|
local ped = GetPlayerPed(players[i])
|
|
if (DoesEntityExist(ped)) then
|
|
local bucket = GetPlayerRoutingBucket(players[i])
|
|
if (not playerPositions[bucket]) then
|
|
playerPositions[bucket] = {}
|
|
end
|
|
|
|
playerPositions[bucket][#playerPositions[bucket] + 1] = GetEntityCoords(ped)
|
|
end
|
|
end
|
|
|
|
return playerPositions
|
|
end
|
|
|
|
-- get closest position and distance from list
|
|
local function GetClosestDistanceFromList(position, positionList)
|
|
local closestDistance = 100000
|
|
|
|
for i = 1, positionList and #positionList or 0 do
|
|
local tempDist = #(position - positionList[i])
|
|
if (tempDist < closestDistance) then
|
|
closestDistance = tempDist
|
|
end
|
|
end
|
|
|
|
return closestDistance
|
|
end
|
|
|
|
-- runs the whole cleanup process once
|
|
function CleanupProcess()
|
|
local timeDiff = 0
|
|
if (Cleanup.timeThreshold) then
|
|
local currentTime = os_time()
|
|
local threshold = math_floor(3600 * Cleanup.timeThreshold)
|
|
timeDiff = os_difftime(currentTime, threshold)
|
|
end
|
|
|
|
local playerPositions = GetPositionsOfAllPlayersByBucket()
|
|
|
|
local toDelete = {}
|
|
|
|
for id, vehicleData in pairs(savedVehicles) do
|
|
local position = DoesEntityExist(vehicleData.handle) and GetEntityCoords(vehicleData.handle) or vehicleData.position
|
|
|
|
for i = 1, #Cleanup.ignoredZones do
|
|
if (#(position - Cleanup.ignoredZones[i].position) < Cleanup.ignoredZones[i].radius) then
|
|
goto cleanupDone -- continue
|
|
end
|
|
end
|
|
|
|
for i = 1, #Cleanup.ignoredPlates do
|
|
if (vehicleData.tuning[1]:find(Cleanup.ignoredPlates[i]:upper())) then
|
|
goto cleanupDone -- continue
|
|
end
|
|
end
|
|
|
|
for i = 1, #Cleanup.ignoredModels do
|
|
if (vehicleData.model == Cleanup.ignoredModels[i]) then
|
|
goto cleanupDone -- continue
|
|
end
|
|
end
|
|
|
|
if (Cleanup.timeThreshold and vehicleData.lastUpdate < timeDiff) then
|
|
toDelete[#toDelete + 1] = id
|
|
TriggerEvent("AP:cleanup:deletingVehicle", vehicleData.handle, vehicleData.tuning[1], "time")
|
|
goto cleanupDone -- continue
|
|
end
|
|
|
|
if (Cleanup.engineThreshold and vehicleData.status[3] <= Cleanup.engineThreshold) then
|
|
toDelete[#toDelete + 1] = id
|
|
TriggerEvent("AP:cleanup:deletingVehicle", vehicleData.handle, vehicleData.tuning[1], "engineHealth")
|
|
goto cleanupDone -- continue
|
|
end
|
|
|
|
if (Cleanup.distanceThreshold) then
|
|
local distance = GetClosestDistanceFromList(position, playerPositions[vehicleData.bucket])
|
|
if (distance > Cleanup.distanceThreshold) then
|
|
toDelete[#toDelete + 1] = id
|
|
TriggerEvent("AP:cleanup:deletingVehicle", vehicleData.handle, vehicleData.tuning[1], "distance")
|
|
goto cleanupDone -- continue
|
|
end
|
|
end
|
|
|
|
for i = 1, #Cleanup.zones do
|
|
if (#(position - Cleanup.zones[i].position) < Cleanup.zones[i].radius) then
|
|
toDelete[#toDelete + 1] = id
|
|
TriggerEvent("AP:cleanup:deletingVehicle", vehicleData.handle, vehicleData.tuning[1], "zone_" .. i)
|
|
goto cleanupDone -- continue
|
|
end
|
|
end
|
|
|
|
::cleanupDone::
|
|
end
|
|
|
|
for i, id in ipairs(toDelete) do
|
|
if (savedVehicles[id].handle and DoesEntityExist(savedVehicles[id].handle)) then
|
|
DeleteEntity(savedVehicles[id].handle)
|
|
|
|
LogDebug("Cleanup removed \"%s\" (\"%s\").", id, savedVehicles[id].tuning[1])
|
|
end
|
|
|
|
if (Cleanup.storeVehicles) then
|
|
StoreVehicle(savedVehicles[id].tuning[1], savedVehicles[id].handle)
|
|
end
|
|
|
|
savedVehicles[id] = nil
|
|
spawnQueue[id] = nil
|
|
end
|
|
|
|
DeleteVehiclesFromDB(toDelete)
|
|
|
|
local othersCount = 0
|
|
if (Cleanup.allVehicles) then
|
|
local vehicles = GetAllVehicles()
|
|
for i = 1, #vehicles do
|
|
if (not DoesEntityExist(vehicles[i])) then
|
|
goto cleanupOthersDone -- continue
|
|
end
|
|
|
|
local position = GetEntityCoords(vehicles[i])
|
|
|
|
for i = 1, #Cleanup.ignoredZones do
|
|
if (#(position - Cleanup.ignoredZones[i].position) < Cleanup.ignoredZones[i].radius) then
|
|
goto cleanupOthersDone -- continue
|
|
end
|
|
end
|
|
|
|
if (#Cleanup.ignoredPlates > 0) then
|
|
local plate = GetVehicleNumberPlateText(vehicles[i])
|
|
for i = 1, #Cleanup.ignoredPlates do
|
|
if (plate:find(Cleanup.ignoredPlates[i]:upper())) then
|
|
goto cleanupOthersDone -- continue
|
|
end
|
|
end
|
|
end
|
|
|
|
if (#Cleanup.ignoredModels > 0) then
|
|
local model = GetEntityModel(vehicles[i])
|
|
for i = 1, #Cleanup.ignoredModels do
|
|
if (model == Cleanup.ignoredModels[i]) then
|
|
goto cleanupOthersDone -- continue
|
|
end
|
|
end
|
|
end
|
|
|
|
if (Cleanup.engineThreshold and GetVehicleEngineHealth(vehicles[i]) <= Cleanup.engineThreshold) then
|
|
DeleteEntity(vehicles[i])
|
|
othersCount += 1
|
|
goto cleanupOthersDone -- continue
|
|
end
|
|
|
|
if (Cleanup.distanceThreshold) then
|
|
local distance = GetClosestDistanceFromList(position, playerPositions[GetEntityRoutingBucket(vehicles[i])])
|
|
if (distance > Cleanup.distanceThreshold) then
|
|
DeleteEntity(vehicles[i])
|
|
othersCount += 1
|
|
goto cleanupOthersDone -- continue
|
|
end
|
|
end
|
|
|
|
for i = 1, #Cleanup.zones do
|
|
if (#(position - Cleanup.zones[i].position) < Cleanup.zones[i].radius) then
|
|
DeleteEntity(vehicles[i])
|
|
othersCount += 1
|
|
goto cleanupOthersDone -- continue
|
|
end
|
|
end
|
|
|
|
::cleanupOthersDone::
|
|
end
|
|
end
|
|
|
|
TriggerClientEvent("AP:showNotification", -1, Cleanup.deleteNotification)
|
|
|
|
Log("Cleanup complete. Removed %s saved vehicles. Removed %s other vehicles.", #toDelete, othersCount)
|
|
end
|
|
|
|
-- add timed clean up tasks
|
|
for i = 1, #Cleanup.times do
|
|
local day = Cleanup.times[i].day
|
|
local hour = Cleanup.times[i].hour
|
|
local minute = Cleanup.times[i].minute
|
|
AddTask(CleanupProcess, day, hour, minute)
|
|
|
|
for j = 1, #Cleanup.notificationTimes do
|
|
local d = day
|
|
local h = hour
|
|
local m = minute - Cleanup.notificationTimes[j]
|
|
if (m < 0) then
|
|
m += 60
|
|
h -= 1
|
|
if (h < 0) then
|
|
h += 24
|
|
if (d) then
|
|
d -= 1
|
|
if (d < 0) then
|
|
d += 7
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
AddTask(function()
|
|
TriggerClientEvent("AP:showNotification", -1, Cleanup.timeLeftNotification:format(Cleanup.notificationTimes[j]))
|
|
end, d, h, m)
|
|
end
|
|
end
|