forked from Simnation/Main
ed
This commit is contained in:
parent
88ffeb3375
commit
87623c8379
27 changed files with 2865 additions and 1705 deletions
279
resources/[carscripts]/AdvancedParking/server/cleanup.lua
Normal file
279
resources/[carscripts]/AdvancedParking/server/cleanup.lua
Normal file
|
@ -0,0 +1,279 @@
|
|||
|
||||
-- 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
|
1179
resources/[carscripts]/AdvancedParking/server/server.lua
Normal file
1179
resources/[carscripts]/AdvancedParking/server/server.lua
Normal file
File diff suppressed because it is too large
Load diff
Binary file not shown.
|
@ -0,0 +1,178 @@
|
|||
|
||||
if (GetResourceState("oxmysql") == "missing") then return end
|
||||
|
||||
local tableName, colName = nil, nil
|
||||
local function GetOwnedVehiclesTableName()
|
||||
if (tableName ~= nil) then
|
||||
return tableName
|
||||
end
|
||||
|
||||
tableName = (GetResourceState("es_extended") ~= "missing") and "owned_vehicles" or "player_vehicles"
|
||||
return tableName
|
||||
end
|
||||
local function GetStoredColumnName()
|
||||
if (colName ~= nil) then
|
||||
return colName
|
||||
end
|
||||
|
||||
colName = (GetResourceState("es_extended") ~= "missing") and "stored" or "state"
|
||||
return colName
|
||||
end
|
||||
|
||||
local oxmysql = exports["oxmysql"]
|
||||
|
||||
local function DoesColumnExist(colName)
|
||||
return oxmysql:scalar_async([[
|
||||
SELECT COUNT(*) FROM `INFORMATION_SCHEMA`.`COLUMNS`
|
||||
WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = ? AND `COLUMN_NAME` = ?;
|
||||
]], { "vehicle_parking", colName }) > 0
|
||||
end
|
||||
|
||||
Storage.Create = function()
|
||||
oxmysql:update_async([[
|
||||
CREATE TABLE IF NOT EXISTS `vehicle_parking` (
|
||||
`id` varchar(16) NOT NULL,
|
||||
`model` int(11) NOT NULL,
|
||||
`type` varchar(16) NOT NULL,
|
||||
`status` text NOT NULL,
|
||||
`tuning` text NOT NULL,
|
||||
`extraValues` text NOT NULL DEFAULT '[]',
|
||||
`stateBags` longtext NOT NULL DEFAULT '[]',
|
||||
`bucket` int(11) NOT NULL DEFAULT '0',
|
||||
`posX` float NOT NULL,
|
||||
`posY` float NOT NULL,
|
||||
`posZ` float NOT NULL,
|
||||
`rotX` float NOT NULL,
|
||||
`rotY` float NOT NULL,
|
||||
`rotZ` float NOT NULL,
|
||||
`lastUpdate` int(11) NOT NULL DEFAULT '0',
|
||||
`initialPlayer` varchar(50),
|
||||
`lastPlayer` varchar(50),
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
]])
|
||||
|
||||
-- v3 backwards compatibility
|
||||
if (not DoesColumnExist("bucket")) then
|
||||
oxmysql:update_async([[
|
||||
ALTER TABLE `vehicle_parking`
|
||||
ADD COLUMN `bucket` INT(11) NOT NULL DEFAULT 0 AFTER `stateBags`;
|
||||
]])
|
||||
end
|
||||
if (not DoesColumnExist("initialPlayer")) then
|
||||
oxmysql:update_async([[
|
||||
ALTER TABLE `vehicle_parking`
|
||||
ADD COLUMN `initialPlayer` varchar(50) AFTER `lastUpdate`;
|
||||
]])
|
||||
end
|
||||
if (not DoesColumnExist("lastPlayer")) then
|
||||
oxmysql:update_async([[
|
||||
ALTER TABLE `vehicle_parking`
|
||||
ADD COLUMN `lastPlayer` varchar(50) AFTER `initialPlayer`;
|
||||
]])
|
||||
end
|
||||
if (not DoesColumnExist("extraValues")) then
|
||||
oxmysql:update_async([[
|
||||
ALTER TABLE `vehicle_parking`
|
||||
ADD COLUMN `extraValues` TEXT NOT NULL DEFAULT '[]' AFTER `tuning`;
|
||||
]])
|
||||
end
|
||||
oxmysql:update_async([[
|
||||
ALTER TABLE `vehicle_parking`
|
||||
MODIFY COLUMN `stateBags` longtext NOT NULL DEFAULT '[]';
|
||||
]])
|
||||
end
|
||||
|
||||
Storage.GetAllVehicles = function()
|
||||
return oxmysql:query_async([[
|
||||
SELECT `id`, `model`, `type`, `status`, `tuning`, `extraValues`, `stateBags`, `bucket`, `posX`, `posY`, `posZ`, `rotX`, `rotY`, `rotZ`, `lastUpdate`, `initialPlayer`, `lastPlayer`
|
||||
FROM `vehicle_parking`;
|
||||
]])
|
||||
end
|
||||
|
||||
Storage.DeleteById = function(id)
|
||||
oxmysql:update([[
|
||||
DELETE FROM `vehicle_parking`
|
||||
WHERE `id` = ?;
|
||||
]], { id })
|
||||
end
|
||||
|
||||
Storage.DeleteByIds = function(formattedIds)
|
||||
oxmysql:update(([[
|
||||
DELETE FROM `vehicle_parking`
|
||||
WHERE `id` IN (%s);
|
||||
]]):format(formattedIds))
|
||||
end
|
||||
|
||||
Storage.StoreVehicleInGarage = function(params)
|
||||
oxmysql:update(([[
|
||||
UPDATE `%s` SET `%s` = 1
|
||||
WHERE `plate` = ? OR `plate` = ?;
|
||||
]]):format(GetOwnedVehiclesTableName(), GetStoredColumnName()), params)
|
||||
end
|
||||
|
||||
Storage.InsertVehicle = function(params)
|
||||
oxmysql:insert([[
|
||||
INSERT INTO `vehicle_parking` (`id`, `model`, `type`, `status`, `tuning`, `extraValues`, `stateBags`, `bucket`, `posX`, `posY`, `posZ`, `rotX`, `rotY`, `rotZ`, `lastUpdate`, `initialPlayer`, `lastPlayer`)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
|
||||
]], params)
|
||||
end
|
||||
|
||||
Storage.UpdateVehicle = function(params)
|
||||
oxmysql:update([[
|
||||
UPDATE `vehicle_parking`
|
||||
SET `status` = ?, `tuning` = ?, `extraValues` = ?,
|
||||
`stateBags` = ?,
|
||||
`bucket` = ?,
|
||||
`posX` = ?, `posY` = ?, `posZ` = ?,
|
||||
`rotX` = ?, `rotY` = ?, `rotZ` = ?,
|
||||
`lastUpdate` = ?,
|
||||
`lastPlayer` = ?
|
||||
WHERE `id` = ?;
|
||||
]], params)
|
||||
end
|
||||
|
||||
Storage.UpdateBucket = function(bucket, id)
|
||||
oxmysql:update([[
|
||||
UPDATE `vehicle_parking`
|
||||
SET `bucket` = ?
|
||||
WHERE `id` = ?;
|
||||
]], { bucket, id })
|
||||
end
|
||||
|
||||
Storage.UpdateStatus = function(status, id)
|
||||
oxmysql:update([[
|
||||
UPDATE `vehicle_parking`
|
||||
SET `status` = ?
|
||||
WHERE `id` = ?;
|
||||
]], { status, id })
|
||||
end
|
||||
|
||||
Storage.UpdatePosition = function(position, rotation, id)
|
||||
oxmysql:update([[
|
||||
UPDATE `vehicle_parking`
|
||||
SET `posX` = ?, `posY` = ?, `posZ` = ?,
|
||||
`rotX` = ?, `rotY` = ?, `rotZ` = ?,
|
||||
WHERE `id` = ?;
|
||||
]], { position.x, position.y, position.z, rotation.x, rotation.y, rotation.z, id })
|
||||
end
|
||||
|
||||
Storage.UpdateStateBags = function(params)
|
||||
oxmysql:update([[
|
||||
UPDATE `vehicle_parking`
|
||||
SET `stateBags` = ?
|
||||
WHERE `id` = ?;
|
||||
]], params)
|
||||
end
|
||||
|
||||
Storage.IsVehicleOwned = function(params)
|
||||
return oxmysql:scalar_async(([[
|
||||
SELECT `plate`
|
||||
FROM `%s`
|
||||
WHERE `plate` = ? OR `plate` = ?;
|
||||
]]):format(GetOwnedVehiclesTableName()), params)
|
||||
end
|
||||
|
||||
Storage.DeleteAllVehicles = function()
|
||||
oxmysql:update("DELETE FROM `vehicle_parking`;")
|
||||
end
|
Binary file not shown.
|
@ -0,0 +1,30 @@
|
|||
|
||||
local Ox = GetResourceState("ox_core") == "started" and exports["ox_core"] or nil
|
||||
|
||||
function IsOwnedVehicle(plate, vehicle)
|
||||
if (Ox) then
|
||||
return Ox:GetVehicle(vehicle)
|
||||
end
|
||||
|
||||
local results = Storage.IsVehicleOwned({ plate, Trim(plate) })
|
||||
|
||||
if (not results) then
|
||||
return false
|
||||
end
|
||||
|
||||
return #results > 0
|
||||
end
|
||||
|
||||
function StoreVehicle(plate, vehicle)
|
||||
if (Ox) then
|
||||
if (vehicle) then
|
||||
local oxVeh = Ox:GetVehicle(vehicle)
|
||||
if (oxVeh) then
|
||||
oxVeh.setStored()
|
||||
end
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
Storage.StoreVehicleInGarage({ plate, Trim(plate) })
|
||||
end
|
74
resources/[carscripts]/AdvancedParking/server/sv_utils.lua
Normal file
74
resources/[carscripts]/AdvancedParking/server/sv_utils.lua
Normal file
|
@ -0,0 +1,74 @@
|
|||
|
||||
-- returns if any player is inside a given vehicle
|
||||
function IsAnyPlayerInsideVehicle(vehicle, playerPeds)
|
||||
for i = 1, #playerPeds do
|
||||
local veh = GetVehiclePedIsIn(playerPeds[i], false)
|
||||
|
||||
if (DoesEntityExist(veh) and veh == vehicle) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
-- return the id and distance of the closest player
|
||||
function GetClosestPlayer(position, maxRadius, players, playerPedsWithHandles, bucket)
|
||||
local closestDistance = maxRadius or 1000.0
|
||||
local closestPlayer = nil
|
||||
|
||||
for i = 1, #players do
|
||||
if (GetPlayerRoutingBucket(players[i]) == bucket) then
|
||||
local distance = #(position - GetEntityCoords(playerPedsWithHandles[ players[i] ]))
|
||||
if (distance < closestDistance) then
|
||||
closestDistance = distance
|
||||
closestPlayer = players[i]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return closestPlayer, closestDistance
|
||||
end
|
||||
|
||||
-- return all player peds associated to their player handles
|
||||
function GetAllPlayerPedsWithHandles(players)
|
||||
local peds = {}
|
||||
|
||||
for i = 1, #players do
|
||||
local ped = GetPlayerPed(players[i])
|
||||
peds[players[i]] = DoesEntityExist(ped) and ped or nil
|
||||
end
|
||||
|
||||
return peds
|
||||
end
|
||||
|
||||
-- returns all currently loaded player peds
|
||||
function GetAllPlayerPeds()
|
||||
local playerPeds = {}
|
||||
|
||||
local players = GetPlayers()
|
||||
for i = 1, #players do
|
||||
local ped = GetPlayerPed(players[i])
|
||||
if (DoesEntityExist(ped)) then
|
||||
playerPeds[#playerPeds + 1] = ped
|
||||
end
|
||||
end
|
||||
|
||||
return playerPeds
|
||||
end
|
||||
|
||||
-- returns a list of all vehicles that are loaded and are registered within AP already
|
||||
function GetLoadedVehiclesWithId(vehicles)
|
||||
local list = {}
|
||||
|
||||
for i = 1, #vehicles do
|
||||
if (DoesEntityExist(vehicles[i])) then
|
||||
local id = Entity(vehicles[i])?.state?.ap_id
|
||||
if (id) then
|
||||
list[id] = vehicles[i]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return list
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue