1
0
Fork 0
forked from Simnation/Main
Main/resources/[carscripts]/lc_utils/frameworks/esx/server.lua
2025-06-07 08:51:21 +02:00

617 lines
22 KiB
Lua

---@diagnostic disable: duplicate-set-field
if Config.framework ~= "ESX" then return end
Utils.Framework = {}
-- Framework init
ESX = nil
if Config.ESX_settings.is_updated then
ESX = exports["es_extended"]:getSharedObject()
else
TriggerEvent(Config.ESX_settings.shared_object, function(obj) ESX = obj end)
end
-- Framework functions
function Utils.Framework.getPlayerIdLog(source)
local user_id = Utils.Framework.getPlayerId(source)
local player_name = GetPlayerName(source)
return user_id.." ("..player_name..")"
end
-- Framework functions
function Utils.Framework.getPlayers()
return ESX.GetPlayers()
end
function Utils.Framework.getPlayerId(source)
local xPlayer = ESX.GetPlayerFromId(source)
if xPlayer then
return xPlayer.identifier
end
return nil
end
function Utils.Framework.getPlayerSource(user_id)
local xPlayer = ESX.GetPlayerFromIdentifier(user_id)
if xPlayer then
return xPlayer.source
end
return nil
end
function Utils.Framework.getPlayerName(user_id)
local xPlayer = ESX.GetPlayerFromIdentifier(user_id)
if xPlayer then
return xPlayer.name
else
local sql = "SELECT firstname, lastname FROM `users` WHERE identifier = @user_id";
local query = MySQL.Sync.fetchAll(sql,{['@user_id'] = user_id});
if query and query[1] and query[1].firstname then
return query[1].firstname.." "..query[1].lastname
end
end
return false
end
function Utils.Framework.getOnlinePlayers()
local online_players = {}
if Config.ESX_settings.is_updated then
-- ESX 1.9+
local xPlayers = ESX.GetExtendedPlayers()
for _, xPlayer in pairs(xPlayers) do
table.insert(online_players, {
source = xPlayer.source,
identifier = xPlayer.identifier,
name = xPlayer.name
})
end
else
-- ESX older than 1.9.0
local xPlayers = ESX.GetPlayers()
for i=1, #xPlayers, 1 do
local xPlayer = ESX.GetPlayerFromId(xPlayers[i])
table.insert(online_players, {
source = xPlayer.source,
identifier = xPlayer.identifier,
name = xPlayer.name
})
end
end
return online_players
end
function Utils.Framework.giveAccountMoney(source,amount,account)
local xPlayer = ESX.GetPlayerFromId(source)
if account == 'money' or account == 'cash' then
xPlayer.addMoney(amount)
else
xPlayer.addAccountMoney(account, amount)
end
end
function Utils.Framework.tryRemoveAccountMoney(source,amount,account)
local money = 0
local xPlayer = ESX.GetPlayerFromId(source)
if account == 'money' or account == 'cash' then
money = xPlayer.getMoney()
else
money = xPlayer.getAccount(account).money
end
if money >= amount then
if account == 'money' or account == 'cash' then
xPlayer.removeMoney(amount)
else
xPlayer.removeAccountMoney(account, amount)
end
return true
else
return false
end
end
function Utils.Framework.getPlayerAccountMoney(source,account)
local money = 0
local xPlayer = ESX.GetPlayerFromId(source)
if account == 'money' or account == 'cash' then
money = xPlayer.getMoney()
else
money = xPlayer.getAccount(account).money
end
return money
end
function Utils.Framework.hasJobs(source,jobs)
local xPlayer = ESX.GetPlayerFromId(source)
local PlayerJob = xPlayer.getJob()
if Config.debug_job then
print("Job name: "..PlayerJob.name)
end
for k,v in pairs(jobs) do
if PlayerJob.name == v then
return true
end
end
return false
end
function Utils.Framework.getPlayerJob(source)
local xPlayer = ESX.GetPlayerFromId(source)
local PlayerJob = xPlayer.getJob()
if Config.debug_job then
print("Job name: "..PlayerJob.name)
end
return PlayerJob.name, true
end
function Utils.Framework.getPlayerInventory(source)
local xPlayer = ESX.GetPlayerFromId(source)
local inventory = {}
for k, v in pairs(xPlayer.getInventory()) do
if v.count and v.count > 0 then
table.insert(inventory, { amount = v.count, name = string.lower(v.name), label = v.label })
end
end
return inventory
end
local function canStoreItemInInventory(source,item,amount)
local xPlayer = ESX.GetPlayerFromId(source)
local weight_ok = false
if Config.ESX_settings.esx_version == 'limit' then
local sourceItem = xPlayer.getInventoryItem(item)
if sourceItem == nil or sourceItem.limit == -1 or (sourceItem.count + amount) <= sourceItem.limit then
weight_ok = true
else
weight_ok = false
end
elseif Config.ESX_settings.esx_version == 'weight' then
if xPlayer.canCarryItem(item, amount) then
weight_ok = true
else
weight_ok = false
end
else
weight_ok = true
end
return weight_ok
end
function Utils.Framework.givePlayerItem(source,item,amount,metadata)
local xPlayer = ESX.GetPlayerFromId(source)
if Config.custom_scripts_compatibility.inventory == "ox_inventory" then
if exports['ox_inventory']:CanCarryItem(source, item, amount) then
return exports['ox_inventory']:AddItem(source, item, amount, metadata)
end
elseif Config.custom_scripts_compatibility.inventory == "qs-inventory" then
return exports['qs-inventory']:AddItem(source, item, amount, nil, metadata)
elseif Config.custom_scripts_compatibility.inventory == "ps-inventory" then
error("ps-inventory not available for ESX")
elseif Config.custom_scripts_compatibility.inventory == "tgiann-inventory" then
exports["tgiann-inventory"]:AddItem(source, item, amount, nil, metadata)
elseif Config.custom_scripts_compatibility.inventory == "default" then
if canStoreItemInInventory(source,item,amount) then
xPlayer.addInventoryItem(item, amount)
return true
else
return false
end
else
return Utils.CustomScripts.givePlayerItem(source,item,amount,metadata)
end
return false
end
function Utils.Framework.insertWeaponInInventory(source,item,amount,metadata)
local ammo = 0
if metadata and metadata.ammo then
ammo = metadata.ammo
end
local xPlayer = ESX.GetPlayerFromId(source)
if Config.custom_scripts_compatibility.inventory == "ox_inventory" then
if exports['ox_inventory']:CanCarryItem(source, item, amount) then
return exports['ox_inventory']:AddItem(source, item, amount, metadata)
end
elseif Config.custom_scripts_compatibility.inventory == "qs-inventory" then
return exports['qs-inventory']:AddItem(source, item, amount, metadata)
elseif Config.custom_scripts_compatibility.inventory == "ps-inventory" then
error("ps-inventory not available for ESX")
elseif Config.custom_scripts_compatibility.inventory == "tgiann-inventory" then
exports["tgiann-inventory"]:AddItem(source, item, amount, nil, metadata)
elseif Config.custom_scripts_compatibility.inventory == "default" then
xPlayer.addWeapon(item, ammo)
return true
else
return Utils.CustomScripts.givePlayerWeapon(source,item,amount,metadata)
end
return false
end
function Utils.Framework.givePlayerWeapon(source,item,amount,metadata)
if Config.custom_scripts_compatibility.mdt == "ps-mdt" then
error("ps-mdt not available for ESX")
elseif Config.custom_scripts_compatibility.mdt == "redutzu-mdt" then
error("redutzu-mdt not available for ESX")
elseif Config.custom_scripts_compatibility.mdt == "lb-tablet" then
error("lb-tablet not available for ESX")
elseif Config.custom_scripts_compatibility.mdt == "default" then
return Utils.Framework.insertWeaponInInventory(source,item,amount,metadata)
else
return Utils.CustomScripts.createWeaponInMdt(source,item,amount,metadata)
end
return false
end
function Utils.Framework.playerHasItem(source,item,amount)
local xPlayer = ESX.GetPlayerFromId(source)
if xPlayer.getInventoryItem(item) and xPlayer.getInventoryItem(item).count >= amount then
return true
else
return false
end
end
function Utils.Framework.getPlayerItem(source,item,amount)
local xPlayer = ESX.GetPlayerFromId(source)
if Config.custom_scripts_compatibility.inventory == "ox_inventory" then
return exports['ox_inventory']:RemoveItem(source, item, amount)
elseif Config.custom_scripts_compatibility.inventory == "qs-inventory" then
if Utils.Framework.playerHasItem(source,item,amount) then
exports['qs-inventory']:RemoveItem(source, item, amount)
return true
else
return false
end
elseif Config.custom_scripts_compatibility.inventory == "ps-inventory" then
error("ps-inventory not available for ESX")
elseif Config.custom_scripts_compatibility.inventory == "tgiann-inventory" then
exports["tgiann-inventory"]:RemoveItem(source, item, amount)
elseif Config.custom_scripts_compatibility.inventory == "default" then
if Utils.Framework.playerHasItem(source,item,amount) then
xPlayer.removeInventoryItem(item,amount)
return true
else
return false
end
else
return Utils.CustomScripts.getPlayerItem(source,item,amount)
end
end
function Utils.Framework.getPlayerWeapon(source,item,amount)
local xPlayer = ESX.GetPlayerFromId(source)
if Config.custom_scripts_compatibility.inventory == "ox_inventory" then
return exports['ox_inventory']:RemoveItem(source, item, amount)
elseif Config.custom_scripts_compatibility.inventory == "qs-inventory" then
if Utils.Framework.playerHasItem(source,item,amount) then
exports['qs-inventory']:RemoveItem(source, item, amount)
return true
else
return false
end
elseif Config.custom_scripts_compatibility.inventory == "ps-inventory" then
error("ps-inventory not available for ESX")
elseif Config.custom_scripts_compatibility.inventory == "tgiann-inventory" then
exports["tgiann-inventory"]:RemoveItem(source, item, amount)
elseif Config.custom_scripts_compatibility.inventory == "default" then
if Utils.Framework.playerHasItem(source,item,amount) then
xPlayer.removeInventoryItem(item,amount)
return true
else
return false
end
else
return Utils.CustomScripts.getPlayerWeapon(source,item,amount)
end
end
function Utils.Framework.hasWeaponLicense(source)
local hasLicense = nil
TriggerEvent('esx_license:checkLicense', source, "weapon", function(hasWeaponLicense)
if hasWeaponLicense then
hasLicense = true
else
hasLicense = false
end
end)
while hasLicense == nil do
Wait(10)
end
return hasLicense
end
function Utils.Framework.registerUsableItem(item_id, event_name, is_server_event, ...)
local args = {...}
ESX.RegisterUsableItem(item_id, function(playerId)
local xPlayer = ESX.GetPlayerFromId(playerId)
if is_server_event then
TriggerEvent(event_name, xPlayer.source, item_id, xPlayer.identifier, table.unpack(args))
else
TriggerClientEvent(event_name, xPlayer.source, item_id, xPlayer.identifier, table.unpack(args))
end
end)
end
-----------------------------------------------------------------------------------------------------------------------------------------
-- Vehicles
-----------------------------------------------------------------------------------------------------------------------------------------
local vehList = {}
function Utils.Framework.setvehList(l)
vehList = l
end
function Utils.Framework.getVehicleModelFromVehicleColumn(vehicle)
local vehicleProps = json.decode(vehicle)
return vehList[vehicleProps.model] or "CARNOTFOUND"
end
function Utils.Framework.givePlayerVehicle(source, vehicle, vehicle_type, plate_format, vehicle_props, state, finance_details)
local xPlayer = ESX.GetPlayerFromId(source)
local plate = vehicle_props and vehicle_props.plate or Utils.Framework.generatePlate(plate_format)
local mods = vehicle_props and vehicle_props or { model = joaat(vehicle), plate = plate, tankHealth = 1000.0, bodyHealth = 1000.0, engineHealth = 1000.0 }
local state = state or 1
local finance_details = finance_details or {}
local vehicle_type = vehicle_type or 'car'
local garage = Config.owned_vehicles['default'].garage
if Config.owned_vehicles[vehicle_type] then
garage = Config.owned_vehicles[vehicle_type].garage
end
Utils.Database.execute('INSERT INTO owned_vehicles (owner, plate, vehicle, type, stored, parking, balance, paymentamount, paymentsleft, financetime) VALUES (@owner, @plate, @vehicle, @type, @stored, @parking, @balance, @paymentamount, @paymentsleft, @financetime)',
{
['@owner'] = xPlayer.identifier,
['@plate'] = plate,
['@vehicle'] = json.encode(mods),
['@stored'] = state, -- 1 = inside garage | 0 = outside garage
['@type'] = vehicle_type,
['@parking'] = garage,
['@balance'] = finance_details.balance or 0,
['@paymentamount'] = finance_details.paymentamount or 0,
['@paymentsleft'] = finance_details.paymentsleft or 0,
['@financetime'] = finance_details.financetime or 0
})
return true
end
function Utils.Framework.getVehiclesData(plate, user_id, query_data)
query_data = query_data or {}
local sql = "SELECT owner as user_id, vehicle, plate, balance, paymentamount, paymentsleft, financetime FROM `owned_vehicles` WHERE 1=1";
local params = {}
if plate then
sql = sql .. " AND plate = @plate"
params['@plate'] = plate
end
if user_id then
sql = sql .. " AND owner = @user_id"
params['@user_id'] = user_id
end
if query_data.only_financed_vehicles then
sql = sql .. " AND balance > 0"
end
local query = Utils.Database.fetchAll(sql, params)
for k, v in pairs(query) do
query[k].vehicle = Utils.Framework.getVehicleModelFromVehicleColumn(v.vehicle)
end
return query
end
function Utils.Framework.updateVehicleData(plate, user_id, vehicle_data)
if not vehicle_data or vehicle_data == {} then return end
assert(plate, "plate cannot be null")
assert(next(vehicle_data) ~= nil, "vehicle_data table must have at least one element")
local sql = "UPDATE `owned_vehicles` SET ";
local params = {
['@plate'] = plate
}
if vehicle_data.balance then
sql = sql .. "balance = @balance, "
params['@balance'] = vehicle_data.balance
end
if vehicle_data.paymentamount then
sql = sql .. "paymentamount = @paymentamount, "
params['@paymentamount'] = vehicle_data.paymentamount
end
if vehicle_data.paymentsleft then
sql = sql .. "paymentsleft = @paymentsleft, "
params['@paymentsleft'] = vehicle_data.paymentsleft
end
if vehicle_data.financetime then
sql = sql .. "financetime = @financetime, "
params['@financetime'] = vehicle_data.financetime
end
sql = sql:sub(1, -3)
sql = sql .. " WHERE plate = @plate"
if user_id then
sql = sql .. " AND owner = @user_id"
params['@user_id'] = user_id
end
Utils.Database.execute(sql, params);
end
function Utils.Framework.deleteOwnedVehicle(plate, user_id)
assert(plate, "plate cannot be null")
local sql = "DELETE FROM `owned_vehicles` WHERE plate = @plate"
local params = {
['@plate'] = plate
}
if user_id then
sql = sql .. " AND owner = @user_id"
params['@user_id'] = user_id
end
Utils.Database.execute(sql, params)
end
function Utils.Framework.deductFinanceTimeFromPlayerVehicles(user_id, financetime)
local sql = "UPDATE owned_vehicles SET financetime = financetime - @financetime WHERE owner = @user_id AND balance > 0";
Utils.Database.execute(sql, {['@user_id'] = user_id, ['@financetime'] = financetime});
end
function Utils.Framework.getVehicleDataByPlates(plates)
local plate_str = table.concat(plates, "','")
local sql = ("SELECT owner as user_id, vehicle, plate, balance, paymentamount, paymentsleft, financetime FROM `owned_vehicles` WHERE plate IN('%s')"):format(plate_str);
local query = Utils.Database.fetchAll(sql, {});
for k, v in pairs(query) do
query[k].vehicle = Utils.Framework.getVehicleModelFromVehicleColumn(v.vehicle)
end
return query
end
function Utils.Framework.getVehicleOwner(plate)
local query = Utils.Database.fetchAll("SELECT owner as user_id FROM owned_vehicles WHERE plate = @plate", {['@plate'] = plate})
if query[1] then
return query[1].user_id
else
return false
end
end
Utils.Framework.isOwnedVehicle = Utils.Framework.getVehicleOwner -- Adv. vehicles
function Utils.Framework.dontAskMeWhatIsThis(user_id)
local sql = [[
SELECT O.owner, O.vehicle, O.plate, R.price, R.id, R.status
FROM `owned_vehicles` O
LEFT JOIN `dealership_requests` R ON R.plate = O.plate
WHERE O.owner = @user_id OR R.user_id = @user_id AND R.request_type = 0
UNION
SELECT O.owner, R.vehicle, R.plate, R.price, R.id, R.status
FROM `owned_vehicles` O
RIGHT JOIN `dealership_requests` R ON R.plate = O.plate
WHERE O.owner = @user_id OR R.user_id = @user_id AND R.request_type = 0
]];
local vehicles = Utils.Database.fetchAll(sql,{['@user_id'] = user_id});
local owned_vehicles = {}
for k,v in pairs(vehicles) do
if not v.id then -- Not in requests table
local vehicleProps = json.decode(v.vehicle)
local model = vehicleProps.model
table.insert(owned_vehicles, {model = model, plate = v.plate, price = v.price, id = v.id, status = v.status})
else
table.insert(owned_vehicles, {vehicle = v.vehicle, plate = v.plate, price = v.price, id = v.id, status = v.status})
end
end
local data = {}
for k,v in pairs(owned_vehicles) do
if not v.vehicle then
local vehName = vehList[v.model]
if vehName == nil then vehName = "CARNOTFOUND" end
table.insert(data, {plate=v.plate, price = v.price, id = v.id, status = v.status, vehicle = vehName})
else
table.insert(data, {plate=v.plate, price = v.price, id = v.id, status = v.status, vehicle = v.vehicle})
end
end
return data
end
function Utils.Framework.generatePlate(plate_format)
local plateFormat = plate_format or Config.owned_vehicles.plate_format
local generatedPlate = ''
math.randomseed(os.time())
for i = 1, math.min(#plateFormat, 8) do
local currentChar = string.sub(plateFormat, i, i)
if currentChar == 'n' then
local a = math.random(0, 9)
generatedPlate = generatedPlate .. a
elseif currentChar == 'l' then
local a = string.char(math.random(65, 90))
generatedPlate = generatedPlate .. a
elseif currentChar == 'x' then
local isLetter = math.random(0, 1)
if isLetter == 1 then
local a = string.char(math.random(65, 90))
generatedPlate = generatedPlate .. a
else
local a = math.random(0, 9)
generatedPlate = generatedPlate .. a
end
else
generatedPlate = generatedPlate .. string.upper(currentChar)
end
end
local isDuplicate = MySQL.Sync.fetchScalar('SELECT COUNT(1) FROM owned_vehicles WHERE plate = @plate', {
['@plate'] = generatedPlate
})
if isDuplicate == 1 then
generatedPlate = Utils.Framework.generatePlate(plateFormat)
end
return generatedPlate
end
Citizen.CreateThread(function()
Wait(2000)
Utils.Database.validateOwnedVehicleTableColumns("owned_vehicles")
end)
-----------------------------------------------------------------------------------------------------------------------------------------
-- Trucker
-----------------------------------------------------------------------------------------------------------------------------------------
function Utils.Framework.getTopTruckers()
local sql = [[SELECT U.lastname as name, U.firstname, T.user_id, T.exp, T.traveled_distance
FROM trucker_users T
INNER JOIN users U ON T.user_id = U.identifier
WHERE traveled_distance > 0 ORDER BY traveled_distance DESC LIMIT 10]];
return Utils.Database.fetchAll(sql,{});
end
function Utils.Framework.getpartyMembers(party_id)
local sql = [[SELECT U.lastname as name, U.firstname, P.*
FROM `trucker_party_members` P
INNER JOIN users U ON P.user_id = U.identifier
WHERE party_id = @party_id]];
return Utils.Database.fetchAll(sql,{['@party_id'] = party_id});
end
-----------------------------------------------------------------------------------------------------------------------------------------
-- Fisher
-----------------------------------------------------------------------------------------------------------------------------------------
function Utils.Framework.getTopFishers()
local sql = [[SELECT U.lastname as name, U.firstname, F.user_id, F.exp, SUM(C.amount) as fishes_caught
FROM fishing_simulator_users F
INNER JOIN users U ON F.user_id = U.identifier
LEFT JOIN fishing_simulator_fishes_caught C ON F.user_id = C.user_id
WHERE F.exp > 0
GROUP BY U.lastname, U.firstname, F.user_id, F.exp
ORDER BY F.exp DESC
LIMIT 10]];
return Utils.Database.fetchAll(sql,{});
end
-----------------------------------------------------------------------------------------------------------------------------------------
-- Collations
-----------------------------------------------------------------------------------------------------------------------------------------
function Utils.Framework.validateTableCollations(script_table, script_column, alter_queries)
local collation_sql = [[SELECT COLLATION_NAME, CHARACTER_SET_NAME
FROM information_schema.columns
WHERE table_schema = (SELECT DATABASE() AS default_schema)
AND table_name = 'users'
AND column_name = 'identifier']]
local query_collation = Utils.Database.fetchAll(collation_sql,{})[1];
local collation_sql_script = [[SELECT COLLATION_NAME, CHARACTER_SET_NAME
FROM information_schema.columns
WHERE table_schema = (SELECT DATABASE() AS default_schema)
AND table_name = ']]..script_table..[['
AND column_name = ']]..script_column..[[']]
local query_collation_script = Utils.Database.fetchAll(collation_sql_script,{})[1];
if query_collation and query_collation['COLLATION_NAME'] and query_collation['CHARACTER_SET_NAME'] and query_collation_script and query_collation_script['COLLATION_NAME'] and query_collation['COLLATION_NAME'] ~= query_collation_script['COLLATION_NAME'] then
for _, alter_query in ipairs(alter_queries) do
Utils.Database.execute(alter_query:format(query_collation['CHARACTER_SET_NAME'],query_collation['COLLATION_NAME']), {})
end
end
end