1
0
Fork 0
forked from Simnation/Main
Main/resources/[Developer]/[Anna]/ngd-Bridge/framework/esx/server.lua
2025-06-07 08:51:21 +02:00

431 lines
No EOL
16 KiB
Lua

module 'shared/debug'
module 'shared/resource'
module 'shared/table'
module 'shared/utils'
module 'shared/player'
ESX = nil
Version = resource.version(Bridge.FrameworkName)
IsExport, ESX = pcall(function()
return exports[Bridge.FrameworkName]:getSharedObject()
end)
if not IsExport then
TriggerEvent(Bridge.FrameworkEvent, function(obj) ESX = obj end)
end
Bridge.Debug('Framework', 'ESX', Version)
local clientRequests = {}
TriggerClientCallback = function(source, name, callback, ...)
local id = #clientRequests + 1
clientRequests[id] = callback
TriggerClientEvent(Bridge.Resource .. ':TriggerClientCallback', source, name, id, ...)
end
RegisterNetEvent(Bridge.Resource .. ':ClientCallback', function(requestId, ...)
if clientRequests[requestId] then
clientRequests[requestId](...)
clientRequests[requestId] = nil
end
end)
AddEventHandler(Bridge.FrameworkPrefix .. ':playerLoaded', function(playerId, xPlayer)
local player = Database.prepare('SELECT `gang`, `gang_grade`, `metadata` FROM `users` WHERE identifier = ?', { xPlayer.getIdentifier() })
local gang = player.gang
local grade = tostring(player.gang_grade)
local gangObject = {}
local gradeObject = {}
if Framework.DoesGangExist(gang, grade) then
gangObject, gradeObject = ESX.Gangs[gang], ESX.Gangs[gang].grades[grade]
else
if Bridge.DebugMode then print(('[^3WARNING^7] Ignoring invalid gang for ^5%s^7 [gang: ^5%s^7, grade: ^5%s^7]'):format(xPlayer.getIdentifier(), gang, grade)) end
gang, grade = 'none', '0'
gangObject, gradeObject = ESX.Gangs[gang], ESX.Gangs[gang].grades[grade]
end
local gangData = {}
gangData.name = gangObject.name
gangData.label = gangObject.label
gangData.grade = tonumber(grade)
gangData.grade_name = gradeObject.name
gangData.grade_label = gradeObject.label
local stateBag = Player(playerId).state
stateBag:set("gang", gangData, true)
stateBag:set("duty", false, true)
local metadata = pcall(xPlayer.getMeta)
if not metadata then
stateBag:set("metadata", json.decode(player.metadata), true)
end
pcall(Framework.OnPlayerLoaded, xPlayer.source)
end)
AddEventHandler('playerDropped', function()
local src = source
local xPlayer = ESX.GetPlayerFromId(src)
if xPlayer then
local metadata = pcall(xPlayer.getMeta)
if not metadata then
Database.prepare('UPDATE `users` SET `metadata` = ? WHERE `identifier` = ?', { json.encode(xPlayer.get('metadata')), xPlayer.getIdentifier() })
end
end
TriggerClientEvent(Bridge.FrameworkPrefix .. ':playerLogout', src)
pcall(Framework.OnPlayerUnload, src)
end)
AddEventHandler(Bridge.FrameworkPrefix .. ':playerLogout', function(playerId)
local xPlayer = ESX.GetPlayerFromId(playerId)
if xPlayer then
local metadata = pcall(xPlayer.getMeta)
if not metadata then
Database.prepare('UPDATE `users` SET `metadata` = ? WHERE `identifier` = ?', { json.encode(xPlayer.get('metadata')), xPlayer.getIdentifier() })
end
end
pcall(Framework.OnPlayerUnload, playerId)
end)
AddEventHandler(Bridge.FrameworkPrefix .. ':setJob', function()
pcall(Framework.OnJobUpdate, source)
end)
AddStateBagChangeHandler('duty', nil, function(bagName, _, value)
local playerId = GetPlayerFromStateBagName(bagName)
pcall(Framework.OnJobDutyUpdate, playerId)
end)
AddStateBagChangeHandler('gang', nil, function(bagName, _, gang)
local playerId = GetPlayerFromStateBagName(bagName)
local Player = Framework.GetPlayer(playerId)
if not Player then return end
if not gang.name or not gang.grade then return end
Database.prepare('UPDATE `users` SET gang = ?, gang_grade = ? WHERE identifier = ?', { gang.name, gang.grade, Player.Identifier})
pcall(Framework.OnGangUpdate, playerId)
end)
Framework.CreateCallback = function(name, cb)
ESX.RegisterServerCallback(name, cb)
end
Framework.TriggerCallback = function(source, name, cb, ...)
local success = pcall(ESX.TriggerClientCallback, source, name, cb, ...)
if not success then
TriggerClientCallback(source, name, cb, ...)
end
end
Framework.CreateUseableItem = function(name, cb)
ESX.RegisterUsableItem(name, cb)
end
Framework.GetPlayer = function(source)
local src = source
local xPlayer = ESX.GetPlayerFromId(src)
if not xPlayer then return nil end
local self = table.deepclone(Framework.Player)
---@cast self Player
local PlayerJob = xPlayer.getJob()
local PlayerGang = Player(src).state.gang
self.source = xPlayer.source
self.Identifier = xPlayer.getIdentifier()
self.Name = GetPlayerName(src)
self.Firstname = xPlayer.get('firstName')
self.Lastname = xPlayer.get('lastName')
self.DateOfBirth = xPlayer.get('dateofbirth') or '01/01/2000'
self.Gender = xPlayer.get("sex") or "m"
self.Job.Name = PlayerJob.name
self.Job.Label = PlayerJob.label
self.Job.Duty = xPlayer.get('duty')
self.Job.Boss = PlayerJob.grade_name == 'boss' and true or false
self.Job.Grade.Name = PlayerJob.grade_label
self.Job.Grade.Level = PlayerJob.grade
if type(PlayerGang) == "table" then
self.Gang.Name = PlayerGang.name
self.Gang.Label = PlayerGang.label
self.Gang.Boss = PlayerGang.grade_name == 'boss' and true or false
self.Gang.Grade.Name = PlayerGang.grade_label
self.Gang.Grade.Level = PlayerGang.grade
end
local getmeta, metadata = pcall(xPlayer.getMeta)
self.Metadata = (getmeta and metadata or (Player(self.source).state.metadata or {}))
self.SetJob = function(job, grade)
if not ESX.DoesJobExist(job, grade) then return false end
xPlayer.setJob(job, grade)
return true
end
self.SetGang = function(gang, grade)
grade = tostring(grade)
if not Framework.DoesGangExist(gang, grade) then return false end
local gangObject, gradeObject = ESX.Gangs[gang], ESX.Gangs[gang].grades[grade]
local gangData = {}
gangData.name = gangObject.name
gangData.label = gangObject.label
gangData.grade = tonumber(grade)
gangData.grade_name = gradeObject.name
gangData.grade_label = gradeObject.label
Player(self.source).state:set("gang", gangData, true)
return true
end
self.AddMoney = function (type, amount)
if type == 'cash' then type = 'money' end
local current = self.GetMoney(type)
xPlayer.addAccountMoney(type, amount)
return self.GetMoney(type) == current + amount
end
self.RemoveMoney = function(type, amount)
if type == 'cash' then type = 'money' end
local current = self.GetMoney(type)
if current < amount then return false end
xPlayer.removeAccountMoney(type, amount)
return self.GetMoney(type) == current - amount
end
self.GetMoney = function(type)
if type == 'cash' then type = 'money' end
return xPlayer.getAccount(type)?.money
end
self.GetStatus = function(key)
local p = promise.new()
TriggerEvent('esx_status:getStatus', src, key, function(status)
p:resolve(Framework.Round(status.percent, 0))
end)
return Citizen.Await(p)
end
self.SetStatus = function(key, value)
TriggerClientEvent("esx_status:set", src, key, (value * 10000))
end
self.GetMetaData = function(key)
if not key then
local success, result = pcall(xPlayer.getMeta)
if success then return result end
if not success then return Player(self.source).state.metadata or {} end
else
local success, result = pcall(xPlayer.getMeta, key)
if success then return result end
if not success then return Player(self.source).state.metadata[key] or nil end
end
end
self.SetMetaData = function(key, value)
local success, result = pcall(xPlayer.setMeta, key, value)
if not success then
local metadata = Player(self.source).state.metadata or {}
metadata[key] = value
Player(self.source).state:set("metadata", metadata, true)
end
end
self.HasLicense = function(name)
return (Database.scalar('SELECT 1 FROM `user_licenses` WHERE `type` = ? AND `owner` = ?', { name, self.Identifier }) ~= nil)
end
self.GetLicenses = function()
local p = promise.new()
Database.query('SELECT `type` FROM `user_licenses` WHERE `owner` = ?', { self.Identifier }, function(result)
local licenses = {}
for i = 1, #result do
licenses[result[i].type] = true
end
p:resolve(licenses)
end)
return Citizen.Await(p)
end
self.AddLicense = function(name)
TriggerEvent('esx_license:addLicense', src, name)
end
self.RemoveLicense = function(name)
Database.prepare('DELETE FROM `user_licenses` WHERE `type` = ? AND `owner` = ?', { name, self.Identifier })
end
return self
end
Framework.GetPlayerByIdentifier = function(identifier)
return Framework.GetPlayer(ESX.GetPlayerFromIdentifier(identifier)?.source)
end
Framework.DoesJobExist = function(job, grade)
return ESX.DoesJobExist(job, grade)
end
Framework.DoesGangExist = function(gang, grade)
grade = tostring(grade)
if gang and grade then
if ESX.Gangs[gang] and ESX.Gangs[gang].grades[grade] then
return true
else
return false
end
end
return false
end
Framework.RegisterSociety = function(name, type)
if type ~= 'job' and type ~= 'gang' then error('Society Type Must Be Job Or Gang', 0) return end
local society_data_name = ('society_%s'):format(name)
Database.scalar('SELECT `name` FROM `addon_account` WHERE `name` = ?', { society_data_name }, function(addon_account)
if not addon_account then
Database.insert('INSERT IGNORE INTO `addon_account` (`name`, `label`, `shared`) VALUES (?, ?, ?)', { society_data_name, Framework.FirstToUpper(name), 1})
end
end)
Database.scalar('SELECT `account_name` FROM `addon_account_data` WHERE `account_name` = ?', { society_data_name }, function(addon_account_data)
if not addon_account_data then
Database.insert('INSERT IGNORE INTO `addon_account_data` (`account_name`, `money`) VALUES (?, ?)', { society_data_name, 0 })
end
end)
TriggerEvent('esx_addonaccount:refreshAccounts')
TriggerEvent('esx_society:registerSociety', name, Framework.FirstToUpper(name), society_data_name, society_data_name, society_data_name, { type = 'public' })
end
Framework.SocietyGetMoney = function(name, type)
if type ~= 'job' and type ~= 'gang' then error('Society Type Must Be Job Or Gang', 0) return 0 end
local p = promise.new()
local society_name = ('society_%s'):format(name)
TriggerEvent('esx_addonaccount:getSharedAccount', society_name, function(account)
p:resolve(account.money)
end)
return Citizen.Await(p)
end
Framework.SocietyAddMoney = function(name, type, amount)
if type ~= 'job' and type ~= 'gang' then error('Society Type Must Be Job Or Gang', 0) return false end
local p = promise.new()
local society_name = ('society_%s'):format(name)
TriggerEvent('esx_addonaccount:getSharedAccount', society_name, function(account)
if account and amount > 0 then
account.addMoney(amount)
p:resolve(true)
else
p:resolve(false)
end
end)
return Citizen.Await(p)
end
Framework.SocietyRemoveMoney = function(name, type, amount)
if type ~= 'job' and type ~= 'gang' then error('Society Type Must Be Job Or Gang', 0) return false end
local p = promise.new()
local society_name = ('society_%s'):format(name)
TriggerEvent('esx_addonaccount:getSharedAccount', society_name, function(account)
if account and amount > 0 and account.money >= amount then
account.removeMoney(amount)
p:resolve(true)
else
p:resolve(false)
end
end)
return Citizen.Await(p)
end
Framework.Notify = function(source, message, type, length)
TriggerClientEvent(Bridge.FrameworkPrefix .. ':showNotification', source, message, type, length)
end
Framework.IsPlayerDead = function(source)
local p = promise.new()
Framework.TriggerCallback(source, Bridge.Resource .. ':bridge:IsPlayerDead', function(isDead)
p:resolve(isDead)
end)
return Citizen.Await(p)
end
Framework.HasPermission = function(source, permission)
local xPlayer = ESX.GetPlayerFromId(source)
if type(permission) == "string" then
return xPlayer.getGroup() == permission
elseif type(permission) == "table" then
for _, perm in pairs(permission) do
if xPlayer.getGroup() == perm then
return true
end
end
end
return false
end
Citizen.CreateThreadNow(function()
ESX.Gangs = {}
local success, result = pcall(Database.scalar, 'SELECT 1 FROM gangs')
if not success then
Database.query([[CREATE TABLE IF NOT EXISTS `gangs` (
`name` varchar(50) NOT NULL,
`label` varchar(50) DEFAULT NULL,
PRIMARY KEY (`name`)
)]])
end
local success, result = pcall(Database.scalar, 'SELECT 1 FROM gang_grades')
if not success then
Database.query([[CREATE TABLE IF NOT EXISTS `gang_grades` (
`id` int(11) NOT NULL,
`gang_name` varchar(50) DEFAULT NULL,
`grade` int(11) NOT NULL,
`name` varchar(50) NOT NULL,
`label` varchar(50) NOT NULL,
PRIMARY KEY (`id`)
)]])
end
local success, result = pcall(Database.scalar, 'SELECT gang FROM users')
if not success then
Database.query("ALTER TABLE `users` ADD COLUMN `gang` varchar(20) DEFAULT 'none' AFTER job_grade")
end
local success, result = pcall(Database.scalar, 'SELECT gang_grade FROM users')
if not success then
Database.query('ALTER TABLE `users` ADD COLUMN `gang_grade` int(11) DEFAULT 0 AFTER gang')
end
local success, gangs = pcall(Database.query, 'SELECT * FROM gangs')
if success then
for _, v in ipairs(gangs) do
ESX.Gangs[v.name] = v
ESX.Gangs[v.name].grades = {}
end
end
local success, gang_grades = pcall(Database.query, 'SELECT * FROM gang_grades')
if success then
for _, v in ipairs(gang_grades) do
if ESX.Gangs[v.gang_name] then
ESX.Gangs[v.gang_name].grades[tostring(v.grade)] = v
else
if Bridge.DebugMode then print(('[^3WARNING^7] Ignoring gang grades for ^5"%s"^0 due to missing gang'):format(v.gang_name)) end
end
end
end
for _, v in pairs(ESX.Gangs) do
if next(v.grades) == nil then
ESX.Gangs[v.name] = nil
if Bridge.DebugMode then print(('[^3WARNING^7] Ignoring gang ^5"%s"^0 due to no gang grades found'):format(v.name)) end
end
end
ESX.Gangs['none'] = {
label = 'No Gang Affiliaton',
grades = { ['0'] = { grade = 0, label = 'None' } }
}
local success, result = pcall(Database.scalar, 'SELECT metadata FROM users')
if not success then
Database.query("ALTER TABLE `users` ADD COLUMN `metadata` LONGTEXT NULL DEFAULT NULL AFTER loadout")
end
end)