forked from Simnation/Main
431 lines
No EOL
16 KiB
Lua
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) |