547 lines
19 KiB
Lua
547 lines
19 KiB
Lua
if Config.Framework ~= "qb" then
|
||
return
|
||
end
|
||
|
||
local nameCache = {}
|
||
Core = {
|
||
CoreReady = false,
|
||
JobbyJobs = {},
|
||
JobbyJobsReady = false,
|
||
}
|
||
Core.__index = Core
|
||
Core.Functions = {}
|
||
|
||
local databaseReady = false
|
||
AddEventHandler('codem-phone:database:ready', function()
|
||
databaseReady = true
|
||
end)
|
||
|
||
local function CheckQBCoreStatus()
|
||
local resourceState = GetResourceState('qb-core')
|
||
return resourceState == "started" or resourceState == "starting"
|
||
end
|
||
|
||
local QBCore = nil
|
||
if CheckQBCoreStatus() then
|
||
local success, result = pcall(function()
|
||
return exports['qb-core']:GetCoreObject()
|
||
end)
|
||
|
||
if success and result then
|
||
QBCore = result
|
||
Core.CoreReady = true
|
||
|
||
Citizen.CreateThread(function()
|
||
local timeout = 0
|
||
while not databaseReady and timeout < 60000 do
|
||
Wait(100)
|
||
timeout = timeout + 100
|
||
end
|
||
|
||
if not databaseReady then
|
||
print('^1[CODEM-PHONE] Framework ERROR: Database initialization timeout!^7')
|
||
return
|
||
end
|
||
|
||
local JobbyConfig = LoadFile('config/AppConfig/JobbyConfig.lua')
|
||
local players = MySQL.query.await('SELECT citizenid, job, charinfo FROM players')
|
||
for k, v in pairs(JobbyConfig.AllowJobs) do
|
||
Core.JobbyJobs[k] = {
|
||
label = QBCore.Shared.Jobs[k] and QBCore.Shared.Jobs[k].label or 'Unknown Job',
|
||
players = {},
|
||
name = k,
|
||
grades = QBCore.Shared.Jobs[k] and QBCore.Shared.Jobs[k].grades or {},
|
||
money = 0,
|
||
announcements = {},
|
||
logs = {},
|
||
}
|
||
local ShowSQl = MySQL.scalar.await(
|
||
"SELECT 1 FROM information_schema.tables WHERE table_name = 'codem_mphone_jobby_announcements' LIMIT 1")
|
||
local announcementSql = {}
|
||
if ShowSQl then
|
||
announcementSql = MySQL.query.await(
|
||
'SELECT id, title, content, created_at FROM codem_mphone_jobby_announcements WHERE jobname = ? ORDER BY created_at DESC LIMIT 15',
|
||
{ k }
|
||
)
|
||
end
|
||
|
||
local ShowLogSQl = MySQL.scalar.await(
|
||
"SELECT 1 FROM information_schema.tables WHERE table_name = 'codem_mphone_jobby_log' LIMIT 1")
|
||
local logsSql = {}
|
||
if ShowLogSQl then
|
||
logsSql = MySQL.query.await(
|
||
'SELECT id, action, amount, playername, phone_number, date FROM codem_mphone_jobby_log WHERE jobname = ? ORDER BY date DESC LIMIT 20',
|
||
{ k }
|
||
)
|
||
end
|
||
for __, vv in pairs(players) do
|
||
local jobs = json.decode(vv.job)
|
||
if jobs and jobs.name and jobs.name == k then
|
||
local charinfo = vv.charinfo and json.decode(vv.charinfo) or nil
|
||
local playerName = 'Unknown Player'
|
||
|
||
if charinfo and charinfo.firstname and charinfo.lastname then
|
||
playerName = charinfo.firstname .. ' ' .. charinfo.lastname
|
||
end
|
||
local PhoneNumber = MySQL.query.await(
|
||
"SELECT phone_number FROM codem_mphone_data WHERE owner = ? LIMIT 1", { vv.citizenid })
|
||
local gradeLevel = (jobs.grade and jobs.grade.level) or 0
|
||
local gradeName = (jobs.grade and jobs.grade.name) or 'Unknown Grade'
|
||
Core.JobbyJobs[k].players[#Core.JobbyJobs[k].players + 1] = {
|
||
name = playerName,
|
||
grade_level = gradeLevel,
|
||
grade_name = gradeName,
|
||
src = false,
|
||
identifier = vv.citizenid,
|
||
boss = false,
|
||
phone_number = PhoneNumber and PhoneNumber[1] and PhoneNumber[1].phone_number or nil,
|
||
}
|
||
end
|
||
end
|
||
Core.JobbyJobs[k].money = GetJobMoney(k)
|
||
Core.JobbyJobs[k].announcements = announcementSql or {}
|
||
Core.JobbyJobs[k].logs = logsSql or {}
|
||
end
|
||
Core.JobbyJobsReady = true
|
||
end)
|
||
else
|
||
DebugPrint('Error: QB-Core object could not be retrieved')
|
||
end
|
||
else
|
||
DebugPrint('Error: QB-Core resource not found or not started')
|
||
return
|
||
end
|
||
|
||
|
||
|
||
|
||
-- Example job structure from QBCore:
|
||
-- "realestate": {
|
||
-- "label": "Real Estate",
|
||
-- "offDutyPay": false,
|
||
-- "grades": {
|
||
-- "3": {
|
||
-- "payment": 125,
|
||
-- "name": "Broker"
|
||
-- },
|
||
-- "4": {
|
||
-- "isboss": true,
|
||
-- "payment": 150,
|
||
-- "name": "Manager"
|
||
-- },
|
||
-- "0": {
|
||
-- "payment": 50,
|
||
-- "name": "Recruit"
|
||
-- },
|
||
-- "1": {
|
||
-- "payment": 75,
|
||
-- "name": "House Sales"
|
||
-- },
|
||
-- "2": {
|
||
-- "payment": 100,
|
||
-- "name": "Business Sales"
|
||
-- }
|
||
-- },
|
||
-- "defaultDuty": true
|
||
-- }
|
||
|
||
|
||
function JobHasIsBossField(job)
|
||
local AllFrameworkJobs = Core.JobbyJobs or {}
|
||
if not AllFrameworkJobs[job] then return false end
|
||
|
||
local AllGrades = AllFrameworkJobs[job].grades or {}
|
||
for _, gradeData in pairs(AllGrades) do
|
||
if gradeData.isboss == true then
|
||
return true
|
||
end
|
||
end
|
||
return false
|
||
end
|
||
|
||
function IsGradeBoss(job, gradeLevel)
|
||
local AllFrameworkJobs = Core.JobbyJobs or {}
|
||
if not AllFrameworkJobs[job] then return false end
|
||
local AllGrades = AllFrameworkJobs[job].grades or {}
|
||
local gradeData = AllGrades[tonumber(gradeLevel)] or AllGrades[tostring(gradeLevel)]
|
||
if gradeData and gradeData.isboss == true then
|
||
return true
|
||
end
|
||
return false
|
||
end
|
||
|
||
function GetHighestGrade(job)
|
||
local AllFrameworkJobs = Core.JobbyJobs or {}
|
||
if AllFrameworkJobs[job] then
|
||
local AllGrades = AllFrameworkJobs[job].grades
|
||
local highestGrade = -1
|
||
for key, _ in pairs(AllGrades) do
|
||
local gradeNum = tonumber(key)
|
||
if gradeNum and gradeNum > highestGrade then
|
||
highestGrade = gradeNum
|
||
end
|
||
end
|
||
return highestGrade
|
||
else
|
||
return false
|
||
end
|
||
end
|
||
|
||
function IsBoss(job, gradeLevel)
|
||
if JobHasIsBossField(job) then
|
||
return IsGradeBoss(job, gradeLevel)
|
||
else
|
||
local highestGrade = GetHighestGrade(job)
|
||
return highestGrade and gradeLevel >= highestGrade
|
||
end
|
||
end
|
||
|
||
Core.Functions.GetPlayer = function(playerid)
|
||
if not playerid then
|
||
DebugPrint('Error: playerId is required')
|
||
return nil
|
||
end
|
||
if QBCore and QBCore.Functions and QBCore.Functions.GetPlayer then
|
||
local success, playerData = pcall(QBCore.Functions.GetPlayer, playerid)
|
||
if success and playerData then
|
||
return playerData
|
||
else
|
||
return false
|
||
end
|
||
else
|
||
return false
|
||
end
|
||
end
|
||
|
||
Core.Functions.GetIdentifier = function(playerId)
|
||
if not playerId then
|
||
DebugPrint('Error: playerId is required')
|
||
return nil
|
||
end
|
||
|
||
if QBCore and QBCore.Functions and QBCore.Functions.GetPlayer then
|
||
local success, playerData = pcall(QBCore.Functions.GetPlayer, playerId)
|
||
if success and playerData and playerData.PlayerData then
|
||
return playerData.PlayerData.citizenid or nil
|
||
else
|
||
return false
|
||
end
|
||
else
|
||
return false
|
||
end
|
||
end
|
||
|
||
Core.Functions.GetSourceFromIdentifier = function(identifier)
|
||
if not identifier then
|
||
DebugPrint('Error: identifier is required')
|
||
return nil
|
||
end
|
||
if QBCore and QBCore.Functions and QBCore.Functions.GetPlayer then
|
||
local success, player = pcall(QBCore.Functions.GetPlayerByCitizenId, identifier)
|
||
if success and player then
|
||
return player.PlayerData.source
|
||
else
|
||
return false
|
||
end
|
||
else
|
||
return false
|
||
end
|
||
end
|
||
|
||
|
||
-- Example job data structure from QBCore:
|
||
--[[
|
||
{
|
||
"payment": 150,
|
||
"grade": {
|
||
"payment": 150,
|
||
"name": "Chief",
|
||
"isboss": true,
|
||
"level": 4
|
||
},
|
||
"type": "leo",
|
||
"name": "police",
|
||
"label": "Law Enforcement",
|
||
"isboss": true,
|
||
"onduty": true
|
||
}
|
||
]]
|
||
Core.Functions.GetPlayerJob = function(playerId)
|
||
if not playerId then
|
||
DebugPrint('Error: playerId is required')
|
||
return false
|
||
end
|
||
|
||
if QBCore and QBCore.Functions and QBCore.Functions.GetPlayer then
|
||
local success, playerData = pcall(QBCore.Functions.GetPlayer, playerId)
|
||
if success and playerData and playerData.PlayerData and playerData.PlayerData.job then
|
||
return {
|
||
name = playerData.PlayerData.job.name or 'unemployed',
|
||
label = playerData.PlayerData.job.label or 'Unemployed',
|
||
onduty = playerData.PlayerData.job.onduty or false,
|
||
grade_name = playerData.PlayerData.job.grade.name or 'unemployed',
|
||
grade_level = playerData.PlayerData.job.grade.level or 0,
|
||
isboss = playerData.PlayerData.job.grade.isboss or false
|
||
}
|
||
else
|
||
return false
|
||
end
|
||
else
|
||
return false
|
||
end
|
||
end
|
||
|
||
|
||
Core.Functions.IsPlayerAdmin = function(playerId)
|
||
if not playerId then
|
||
DebugPrint('Error: playerId is required')
|
||
return false
|
||
end
|
||
|
||
local permissions = Config.Permissions or { 'god' }
|
||
|
||
if type(permissions) ~= 'table' or #permissions == 0 then
|
||
DebugPrint('Warning: Config.Permissions is invalid, using default permissions')
|
||
permissions = { 'god' }
|
||
end
|
||
|
||
for _, v in pairs(Config.AdminPermissions) do
|
||
if QBCore.Functions.HasPermission(playerId, v) or IsPlayerAceAllowed(playerId, 'command') then
|
||
return true
|
||
end
|
||
end
|
||
|
||
return false
|
||
end
|
||
|
||
|
||
AddEventHandler("QBCore:Server:OnJobUpdate", function(src, job)
|
||
TriggerClientEvent('codem-phone:client:OnJobUpdate', src)
|
||
OnJobUpdate(src, {
|
||
jobname = job.name or 'unemployed',
|
||
onduty = job.onduty or false,
|
||
})
|
||
|
||
OnJobbyJobUpdate(src)
|
||
end)
|
||
|
||
AddEventHandler("QBCore:Server:SetDuty", function(src, onDuty)
|
||
local playerJob = Core.Functions.GetPlayerJob(src)
|
||
OnJobUpdate(src, {
|
||
jobname = playerJob and playerJob.name or 'unemployed',
|
||
onduty = onDuty or false,
|
||
})
|
||
|
||
OnJobbyJobUpdate(src)
|
||
end)
|
||
|
||
Core.Functions.GetName = function(playerId, nameType)
|
||
if not playerId then
|
||
DebugPrint('Error: playerId is required')
|
||
return 'Unknown'
|
||
end
|
||
|
||
if QBCore and QBCore.Functions and QBCore.Functions.GetPlayer then
|
||
local success, playerData = pcall(QBCore.Functions.GetPlayer, playerId)
|
||
if success and playerData and playerData.PlayerData then
|
||
local firstname = playerData.PlayerData.charinfo.firstname or ""
|
||
local lastname = playerData.PlayerData.charinfo.lastname or ""
|
||
if nameType and nameType:lower() == 'first' then
|
||
return (firstname):gsub("^%l", string.upper) or 'Unknown'
|
||
elseif nameType and nameType:lower() == 'full' then
|
||
return (firstname .. " " .. lastname):gsub("^%l", string.upper) or 'Unknown'
|
||
end
|
||
return (firstname .. " " .. lastname):gsub("^%l", string.upper) or 'Unknown'
|
||
else
|
||
-- offline player ismini çekmek için Core.Functions.GetName fonksiyonunu çağırırken playerId yerine identifier'ini yaz
|
||
if nameCache[playerId] then
|
||
if nameType and nameType:lower() == 'first' then
|
||
return (nameCache[playerId].firstname):gsub("^%l", string.upper) or 'Unknown'
|
||
elseif nameType and nameType:lower() == 'full' then
|
||
return (nameCache[playerId].firstname .. " " .. nameCache[playerId].lastname):gsub("^%l",
|
||
string.upper) or 'Unknown'
|
||
end
|
||
return (nameCache[playerId].firstname .. " " .. nameCache[playerId].lastname):gsub("^%l", string.upper) or
|
||
'Unknown'
|
||
end
|
||
local result = MySQL.single.await("SELECT charinfo FROM players WHERE citizenid = ? LIMIT 1", { playerId })
|
||
if result and result.charinfo then
|
||
local charinfo = json.decode(result.charinfo)
|
||
if nameType and nameType:lower() == 'first' then
|
||
return (charinfo.firstname):gsub("^%l", string.upper) or 'Unknown'
|
||
elseif nameType and nameType:lower() == 'full' then
|
||
return (charinfo.firstname .. " " .. charinfo.lastname):gsub("^%l", string.upper) or 'Unknown'
|
||
end
|
||
nameCache[playerId] = {
|
||
firstname = charinfo.firstname,
|
||
lastname = charinfo.lastname,
|
||
}
|
||
return (charinfo.firstname .. " " .. charinfo.lastname):gsub("^%l", string.upper) or 'Unknown'
|
||
end
|
||
end
|
||
else
|
||
DebugPrint('Error: QB-Core Functions not available')
|
||
end
|
||
return 'Unknown'
|
||
end
|
||
|
||
Core.Functions.GetMoney = function(playerId, moneyType)
|
||
if not playerId then
|
||
DebugPrint('Error: playerId is required')
|
||
return 0
|
||
end
|
||
moneyType = moneyType or 'bank'
|
||
if QBCore and QBCore.Functions and QBCore.Functions.GetPlayer then
|
||
local success, playerData = pcall(QBCore.Functions.GetPlayer, playerId)
|
||
if success and playerData and playerData.PlayerData and playerData.PlayerData.money then
|
||
return {
|
||
success = true,
|
||
money = playerData.PlayerData.money[moneyType] or 0
|
||
}
|
||
else
|
||
return {
|
||
success = false,
|
||
message = 'Error: Player data could not be retrieved - ID: ' .. tostring(playerId)
|
||
}
|
||
end
|
||
else
|
||
return {
|
||
success = false,
|
||
message = 'Error: QB-Core Functions not available'
|
||
}
|
||
end
|
||
end
|
||
|
||
Core.Functions.RemoveMoney = function(playerId, amount, moneyType)
|
||
if not playerId then
|
||
DebugPrint('Error: playerId is required')
|
||
return false
|
||
end
|
||
if not amount or amount <= 0 then
|
||
DebugPrint('Error: amount must be a positive number')
|
||
return false
|
||
end
|
||
moneyType = moneyType or 'bank'
|
||
if QBCore and QBCore.Functions and QBCore.Functions.GetPlayer then
|
||
local success, playerData = pcall(QBCore.Functions.GetPlayer, playerId)
|
||
if success and playerData and playerData.PlayerData and playerData.PlayerData.money then
|
||
local currentMoney = playerData.PlayerData.money[moneyType] or 0
|
||
if currentMoney >= amount then
|
||
local removeSuccess, removeResult = pcall(function()
|
||
return playerData.Functions.RemoveMoney(moneyType, amount, "codem-phone")
|
||
end)
|
||
if removeSuccess and removeResult then
|
||
return true
|
||
else
|
||
return false
|
||
end
|
||
else
|
||
return false
|
||
end
|
||
else
|
||
return false
|
||
end
|
||
else
|
||
return false
|
||
end
|
||
end
|
||
|
||
Core.Functions.AddMoney = function(playerId, amount, moneyType)
|
||
if not playerId then
|
||
DebugPrint('Error: playerId is required')
|
||
return false
|
||
end
|
||
if not amount or amount <= 0 then
|
||
DebugPrint('Error: amount must be a positive number')
|
||
return false
|
||
end
|
||
moneyType = moneyType or 'bank'
|
||
if QBCore and QBCore.Functions and QBCore.Functions.GetPlayer then
|
||
local success, playerData = pcall(QBCore.Functions.GetPlayer, playerId)
|
||
if success and playerData and playerData.PlayerData and playerData.PlayerData.money then
|
||
local addSuccess, addResult = pcall(function()
|
||
return playerData.Functions.AddMoney(moneyType, amount, "codem-phone")
|
||
end)
|
||
if addSuccess then
|
||
return addResult
|
||
else
|
||
return false
|
||
end
|
||
else
|
||
return false
|
||
end
|
||
else
|
||
return false
|
||
end
|
||
end
|
||
|
||
|
||
|
||
Core.Functions.AddMoneyOffline = function(citizenid, amount, moneyType)
|
||
if not citizenid then
|
||
return { success = false, message = "Citizen ID is required." }
|
||
end
|
||
if not amount or amount <= 0 then
|
||
return { success = false, message = "Invalid amount." }
|
||
end
|
||
moneyType = moneyType or 'bank'
|
||
|
||
if QBCore and QBCore.Functions then
|
||
local moneyData = MySQL.scalar.await(
|
||
"SELECT money FROM players WHERE citizenid = ?",
|
||
{ citizenid }
|
||
)
|
||
|
||
if not moneyData then
|
||
return { success = false, message = "Player not found in database." }
|
||
end
|
||
|
||
local playerData = json.decode(moneyData) or {}
|
||
local currentMoney = playerData[moneyType] or 0
|
||
playerData[moneyType] = currentMoney + amount
|
||
|
||
local affectedRows = MySQL.update.await(
|
||
"UPDATE players SET money = ? WHERE citizenid = ?",
|
||
{ json.encode(playerData), citizenid }
|
||
)
|
||
|
||
if affectedRows > 0 then
|
||
return { success = true }
|
||
else
|
||
return { success = false, message = "Failed to update money for offline player." }
|
||
end
|
||
else
|
||
return { success = false, message = "Core Functions not available." }
|
||
end
|
||
end
|
||
|
||
|
||
Core.Functions.SetPlayerJob = function(playerid, jobname, grade)
|
||
local player = Core.Functions.GetPlayer(playerid)
|
||
if player then
|
||
player.Functions.SetJob(jobname, grade)
|
||
return true
|
||
else
|
||
DebugPrint('Error: Player not found - ID: ' .. tostring(playerid))
|
||
return false
|
||
end
|
||
end
|
||
|
||
|
||
Core.Functions.CreateUseableItem = function(itemName, callback)
|
||
if not itemName or type(itemName) ~= 'string' then
|
||
DebugPrint('Error: itemName must be a valid string')
|
||
return
|
||
end
|
||
if not callback or type(callback) ~= 'function' then
|
||
DebugPrint('Error: callback must be a valid function')
|
||
return
|
||
end
|
||
|
||
if QBCore and QBCore.Functions and QBCore.Functions.CreateUseableItem then
|
||
QBCore.Functions.CreateUseableItem(itemName, callback)
|
||
else
|
||
DebugPrint('Error: QB-Core Functions not available')
|
||
end
|
||
end
|