1
0
Fork 0
forked from Simnation/Main
This commit is contained in:
Nordi98 2025-07-01 08:02:31 +02:00
parent 72d74fb01a
commit 10000b6b8c
5 changed files with 133 additions and 48 deletions

View file

@ -29,28 +29,43 @@ local function playSound(audioName, audioDict)
end
-- Events
RegisterNetEvent('qb_vehicle_tracker:client:manageTracker', function(serialNumber)
lib.registerContext({
id = 'vt_menu',
title = locale('vt_menu_header'),
options = {
{
title = locale('vt_menu_check_location'),
event = 'qb_vehicle_tracker:client:locateTracker',
icon = 'eye',
args = serialNumber
}
}
})
RegisterNetEvent('qb_vehicle_tracker:client:showTrackerMenu', function(citizenid)
lib.callback('qb_vehicle_tracker:getPlayerTrackers', false, function(trackers)
if not trackers or #trackers == 0 then
uiNotify(locale('vt_no_trackers_found') or "No trackers found", 'error')
return
end
if uiProgressBar(2000, locale('vt_pb_connecting'), {
dict = 'amb@code_human_in_bus_passenger_idles@female@tablet@base',
clip = 'base'
}, {
model = `prop_cs_tablet`,
pos = vec3(0.03, 0.002, -0.0),
rot = vec3(10.0, 160.0, 0.0)
}) then lib.showContext('vt_menu') else uiNotify(locale('vt_pb_cancelled'), 'error') end
local options = {}
for _, tracker in ipairs(trackers) do
table.insert(options, {
title = (locale('vt_vehicle_plate') or "Vehicle Plate") .. ': ' .. tracker.vehiclePlate,
description = (locale('vt_serial_number') or "Serial Number") .. ': ' .. tracker.serialNumber,
event = 'qb_vehicle_tracker:client:locateTracker',
icon = 'car',
args = tracker.serialNumber
})
end
lib.registerContext({
id = 'vt_menu',
title = locale('vt_menu_header') or "Vehicle Tracker",
options = options
})
if uiProgressBar(2000, locale('vt_pb_connecting') or "Connecting to tracker network...", {
dict = 'amb@code_human_in_bus_passenger_idles@female@tablet@base',
clip = 'base'
}, {
model = `prop_cs_tablet`,
pos = vec3(0.03, 0.002, -0.0),
rot = vec3(10.0, 160.0, 0.0)
}) then
lib.showContext('vt_menu')
else
uiNotify(locale('vt_pb_cancelled') or "Cancelled", 'error')
end
end, citizenid)
end)
RegisterNetEvent('qb_vehicle_tracker:client:scanTracker', function(slot)

View file

@ -15,5 +15,8 @@
"vt_pb_removing": "Removing GPS Tracker...",
"vt_pb_cancelled": "Cancelled",
"vt_alert_title": "GPS Tracker Found!",
"vt_alert_description": "You have found a GPS Tracker! Do you want to remove it?"
"vt_alert_description": "You have found a GPS Tracker! Do you want to remove it?",
"vt_no_trackers_found": "You don't have any active trackers",
"vt_vehicle_plate": "Vehicle Plate",
"vt_serial_number": "Serial Number"
}

View file

@ -4,8 +4,9 @@ function db.deleteOldTrackers()
return MySQL.query.await('DELETE FROM `vehicle_trackers` WHERE startedAt < (NOW() - INTERVAL 7 DAY)')
end
function db.addTracker(serialNumber, vehiclePlate)
return MySQL.prepare.await('INSERT INTO `vehicle_trackers` (`serialNumber`, `vehiclePlate`) VALUES (?, ?)', { serialNumber, vehiclePlate })
function db.addTracker(serialNumber, vehiclePlate, owner)
return MySQL.prepare.await('INSERT INTO `vehicle_trackers` (`serialNumber`, `vehiclePlate`, `owner`) VALUES (?, ?, ?)',
{ serialNumber, vehiclePlate, owner })
end
function db.deleteTracker(vehiclePlate)
@ -20,4 +21,8 @@ function db.isTracked(vehiclePlate)
return MySQL.scalar.await('SELECT `serialNumber` FROM `vehicle_trackers` WHERE `vehiclePlate` = ? LIMIT 1', { vehiclePlate })
end
function db.getPlayerTrackers(owner)
return MySQL.query.await('SELECT `serialNumber`, `vehiclePlate` FROM `vehicle_trackers` WHERE `owner` = ?', { owner })
end
return db

View file

@ -1,16 +1,71 @@
local QBCore = exports['qb-core']:GetCoreObject()
local config = require 'config'
local utils = require 'server.utils'
local db = require 'server.db'
-- Database functions
local function deleteOldTrackers()
return MySQL.query.await('DELETE FROM `vehicle_trackers` WHERE startedAt < (NOW() - INTERVAL 7 DAY)')
end
local function addTracker(serialNumber, vehiclePlate, owner)
return MySQL.prepare.await('INSERT INTO `vehicle_trackers` (`serialNumber`, `vehiclePlate`, `owner`) VALUES (?, ?, ?)',
{ serialNumber, vehiclePlate, owner })
end
local function deleteTracker(vehiclePlate)
return MySQL.prepare.await('DELETE FROM `vehicle_trackers` WHERE `vehiclePlate` = ?', { vehiclePlate })
end
local function getTracker(serialNumber)
return MySQL.single.await('SELECT `serialNumber`, `vehiclePlate` FROM `vehicle_trackers` WHERE `serialNumber` = ? LIMIT 1', { serialNumber })
end
local function isTracked(vehiclePlate)
return MySQL.scalar.await('SELECT `serialNumber` FROM `vehicle_trackers` WHERE `vehiclePlate` = ? LIMIT 1', { vehiclePlate })
end
local function getPlayerTrackers(owner)
return MySQL.query.await('SELECT `serialNumber`, `vehiclePlate` FROM `vehicle_trackers` WHERE `owner` = ?', { owner })
end
-- Utility functions
local function getRandomSerialNumber()
return lib.string.random('...........')
end
local function trim(plate)
return (plate:gsub("^%s*(.-)%s*$", "%1"))
end
local function getVehicleNetworkIdByPlate(vehiclePlate)
local vehicles = GetAllVehicles()
for _, vehicle in ipairs(vehicles) do
if trim(GetVehicleNumberPlateText(vehicle)) == trim(vehiclePlate) then
return NetworkGetNetworkIdFromEntity(vehicle)
end
end
return nil
end
local function isPlayerNearVehicle(playerCoords, vehiclePlate)
local vehicle = lib.getClosestVehicle(playerCoords, 3.0, true)
if not vehicle or not DoesEntityExist(vehicle) or GetVehicleNumberPlateText(vehicle) ~= vehiclePlate then
return false
end
return true
end
-- QB Usable Items
QBCore.Functions.CreateUseableItem(config.trackerItem, function(source, item)
TriggerClientEvent('qb_vehicle_tracker:client:placeTracker', source, item.slot, utils.getRandomSerialNumber())
TriggerClientEvent('qb_vehicle_tracker:client:placeTracker', source, item.slot, getRandomSerialNumber())
end)
QBCore.Functions.CreateUseableItem(config.trackerTabletItem, function(source, item)
local serialNumber = item.info and item.info.serialNumber or item.metadata.serialNumber
TriggerClientEvent('qb_vehicle_tracker:client:manageTracker', source, serialNumber)
local Player = QBCore.Functions.GetPlayer(source)
TriggerClientEvent('qb_vehicle_tracker:client:showTrackerMenu', source, Player.PlayerData.citizenid)
end)
QBCore.Functions.CreateUseableItem(config.trackerScannerItem, function(source, item)
@ -19,8 +74,8 @@ end)
-- Event Handler
AddEventHandler('onResourceStart', function(resourceName)
if cache.resource == resourceName then
db.deleteOldTrackers()
if GetCurrentResourceName() == resourceName then
deleteOldTrackers()
end
end)
@ -28,10 +83,10 @@ end)
lib.callback.register('qb_vehicle_tracker:getTrackedVehicleBySerial', function(_, serialNumber)
if type(serialNumber) ~= "string" or string.len(serialNumber) < 11 then return end
local tracker = db.getTracker(serialNumber)
local tracker = getTracker(serialNumber)
if not tracker then return end
local vehicleNetworkID = utils.getVehicleNetworkIdByPlate(tracker.vehiclePlate)
local vehicleNetworkID = getVehicleNetworkIdByPlate(tracker.vehiclePlate)
if not vehicleNetworkID then return end
local vehicleEntity = NetworkGetEntityFromNetworkId(vehicleNetworkID)
@ -43,33 +98,32 @@ lib.callback.register('qb_vehicle_tracker:getTrackedVehicleBySerial', function(_
end)
lib.callback.register('qb_vehicle_tracker:isVehicleTracked', function(source, vehiclePlate)
if type(vehiclePlate) ~= "string" or not utils.isPlayerNearVehicle(GetEntityCoords(GetPlayerPed(source)), vehiclePlate) then
if type(vehiclePlate) ~= "string" or not isPlayerNearVehicle(GetEntityCoords(GetPlayerPed(source)), vehiclePlate) then
return false
end
return db.isTracked(utils.trim(vehiclePlate))
return isTracked(trim(vehiclePlate))
end)
lib.callback.register('qb_vehicle_tracker:placeTracker', function(source, vehiclePlate, slot, serialNumber)
if type(vehiclePlate) ~= "string" or type(serialNumber) ~= "string" or string.len(serialNumber) < 11 then return false end
if not utils.isPlayerNearVehicle(GetEntityCoords(GetPlayerPed(source)), vehiclePlate) then return false end
if not db.addTracker(serialNumber, utils.trim(vehiclePlate)) then return false end
if not isPlayerNearVehicle(GetEntityCoords(GetPlayerPed(source)), vehiclePlate) then return false end
local Player = QBCore.Functions.GetPlayer(source)
if Player.Functions.AddItem(config.trackerTabletItem, 1, false, { plate = utils.trim(vehiclePlate), serialNumber = serialNumber }) then
Player.Functions.RemoveItem(config.trackerItem, 1, slot)
TriggerClientEvent('inventory:client:ItemBox', source, QBCore.Shared.Items[config.trackerTabletItem], 'add')
end
if not addTracker(serialNumber, trim(vehiclePlate), Player.PlayerData.citizenid) then return false end
Player.Functions.RemoveItem(config.trackerItem, 1, slot)
TriggerClientEvent('inventory:client:ItemBox', source, QBCore.Shared.Items[config.trackerItem], 'remove')
return true
end)
lib.callback.register('qb_vehicle_tracker:removeTracker', function(source, vehiclePlate, slot)
if type(vehiclePlate) ~= "string" or not utils.isPlayerNearVehicle(GetEntityCoords(GetPlayerPed(source)), vehiclePlate) then
if type(vehiclePlate) ~= "string" or not isPlayerNearVehicle(GetEntityCoords(GetPlayerPed(source)), vehiclePlate) then
return false
end
if not db.deleteTracker(utils.trim(vehiclePlate)) then return false end
if not deleteTracker(trim(vehiclePlate)) then return false end
local Player = QBCore.Functions.GetPlayer(source)
if Player.Functions.RemoveItem(config.trackerScannerItem, 1, slot) then
@ -78,3 +132,10 @@ lib.callback.register('qb_vehicle_tracker:removeTracker', function(source, vehic
return true
end)
lib.callback.register('qb_vehicle_tracker:getPlayerTrackers', function(source, citizenid)
local Player = QBCore.Functions.GetPlayer(source)
if Player.PlayerData.citizenid ~= citizenid then return {} end
return getPlayerTrackers(citizenid)
end)

View file

@ -1,6 +1,7 @@
CREATE TABLE IF NOT EXISTS `vehicle_trackers` (
`serialNumber` varchar(11) NOT NULL,
`vehiclePlate` varchar(11) NOT NULL,
`owner` varchar(50) NULL,
`startedAt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY `serialNumber` (`serialNumber`),
KEY `vehiclePlate` (`vehiclePlate`)