diff --git a/resources/[inventory]/tgiann-inventory/configs/configStashes.lua b/resources/[inventory]/tgiann-inventory/configs/configStashes.lua index b07449014..a0a548425 100644 --- a/resources/[inventory]/tgiann-inventory/configs/configStashes.lua +++ b/resources/[inventory]/tgiann-inventory/configs/configStashes.lua @@ -35,7 +35,7 @@ config.stashes = { ---- NORDIS HAUS ---- { - coords = vec3(-1238.3628, 838.1411, 192.8895), + coords = vec3(-1237.74, 837.11, 192.89), textUiLabel = 'öffnen', name = 'nordisideboard', -- uniq name label = 'Sideboard', @@ -43,7 +43,7 @@ config.stashes = { weight = 70000, }, { - coords = vec3(-1230.7251, 839.1404, 192.8895), + coords = vec3(-1230.77, 839.04, 192.89), textUiLabel = 'öffnen', name = 'nordisfridge', -- uniq name label = 'Kühlschrank', diff --git a/resources/[standalone]/ps-multijob/server/sv_main.lua b/resources/[standalone]/ps-multijob/server/sv_main.lua index e69de29bb..a08c23b20 100644 --- a/resources/[standalone]/ps-multijob/server/sv_main.lua +++ b/resources/[standalone]/ps-multijob/server/sv_main.lua @@ -0,0 +1,309 @@ +local QBCore = exports['qb-core']:GetCoreObject() + +local function GetJobs(citizenid) + local p = promise.new() + MySQL.Async.fetchAll("SELECT jobdata FROM multijobs WHERE citizenid = @citizenid",{ + ["@citizenid"] = citizenid + }, function(jobs) + if jobs[1] and jobs ~= "[]" then + jobs = json.decode(jobs[1].jobdata) + else + local Player = QBCore.Functions.GetOfflinePlayerByCitizenId(citizenid) + local temp = {} + if not Config.IgnoredJobs[Player.PlayerData.job.name] then + temp[Player.PlayerData.job.name] = Player.PlayerData.job.grade.level + MySQL.insert('INSERT INTO multijobs (citizenid, jobdata) VALUES (:citizenid, :jobdata) ON DUPLICATE KEY UPDATE jobdata = :jobdata', { + citizenid = citizenid, + jobdata = json.encode(temp), + }) + end + jobs = temp + end + p:resolve(jobs) + end) + return Citizen.Await(p) +end +exports("GetJobs", GetJobs) + +local function AddJob(citizenid, job, grade) + local jobs = GetJobs(citizenid) + for ignored in pairs(Config.IgnoredJobs) do + if jobs[ignored] then + jobs[ignored] = nil + end + end + + jobs[job] = grade + MySQL.insert('INSERT INTO multijobs (citizenid, jobdata) VALUES (:citizenid, :jobdata) ON DUPLICATE KEY UPDATE jobdata = :jobdata', { + citizenid = citizenid, + jobdata = json.encode(jobs), + }) +end +exports("AddJob", AddJob) + +local function UpdatePlayerJob(Player, job, grade) + if Player.PlayerData.source ~= nil then + Player.Functions.SetJob(job,grade) + else -- player is offline + local sharedJobData = QBCore.Shared.Jobs[job] + if sharedJobData == nil then return end + + local sharedGradeData = sharedJobData.grades[grade] + if sharedGradeData == nil then return end + + local isBoss = false + if sharedGradeData.isboss then isBoss = true end + + MySQL.update.await("update players set job = @jobData where citizenid = @citizenid", { + jobData = json.encode({ + label = sharedJobData.label, + name = job, + isboss = isBoss, + onduty = sharedJobData.defaultDuty, + payment = sharedGradeData.payment, + grade = { + name = sharedGradeData.name, + level = grade, + }, + }), + citizenid = Player.PlayerData.citizenid + }) + end +end + +local function UpdateJobRank(citizenid, job, grade) + local Player = QBCore.Functions.GetOfflinePlayerByCitizenId(citizenid) + if Player == nil then + return + end + + local jobs = GetJobs(citizenid) + if jobs[job] == nil then + return + end + + jobs[job] = grade + + MySQL.update.await("update multijobs set jobdata = :jobdata where citizenid = :citizenid", { + citizenid = citizenid, + jobdata = json.encode(jobs), + }) + + -- if the current job matches, then update + if Player.PlayerData.job.name == job then + UpdatePlayerJob(Player, job, grade) + end +end +exports("UpdateJobRank", UpdateJobRank) + +local function RemoveJob(citizenid, job) + local Player = QBCore.Functions.GetPlayerByCitizenId(citizenid) + + if Player == nil then + Player = QBCore.Functions.GetOfflinePlayerByCitizenId(citizenid) + end + + if Player == nil then return end + + local jobs = GetJobs(citizenid) + jobs[job] = nil + + -- Since we removed a job, put player in a new job + local foundNewJob = false + if Player.PlayerData.job.name == job then + for k,v in pairs(jobs) do + UpdatePlayerJob(Player, k,v) + foundNewJob = true + break + end + end + + if not foundNewJob then + UpdatePlayerJob(Player, "unemployed", 0) + end + + MySQL.insert('INSERT INTO multijobs (citizenid, jobdata) VALUES (:citizenid, :jobdata) ON DUPLICATE KEY UPDATE jobdata = :jobdata', { + citizenid = citizenid, + jobdata = json.encode(jobs), + }) +end +exports("RemoveJob", RemoveJob) + +QBCore.Commands.Add('removejob', 'Remove Multi Job (Admin Only)', { { name = 'id', help = 'ID of player' }, { name = 'job', help = 'Job Name' } }, false, function(source, args) + local source = source + if source ~= 0 then + if args[1] then + local Player = QBCore.Functions.GetPlayer(tonumber(args[1])) + if Player then + if args[2] then + RemoveJob(Player.PlayerData.citizenid, args[2]) + else + TriggerClientEvent("QBCore:Notify", source, "Wrong usage!") + end + else + TriggerClientEvent("QBCore:Notify", source, "Wrong usage!") + end + else + TriggerClientEvent("QBCore:Notify", source, "Wrong usage!") + end + else + TriggerClientEvent("QBCore:Notify", source, "Wrong usage!") + end +end, 'admin') + +QBCore.Commands.Add('addjob', 'Add Multi Job (Admin Only)', { { name = 'id', help = 'ID of player' }, { name = 'job', help = 'Job Name' }, { name = 'grade', help = 'Job Grade' } }, false, function(source, args) + local source = source + if source ~= 0 then + if args[1] then + local Player = QBCore.Functions.GetPlayer(tonumber(args[1])) + if Player then + if args[2]and args[3] then + AddJob(Player.PlayerData.citizenid, args[2], args[3]) + else + TriggerClientEvent("QBCore:Notify", source, "Wrong usage!") + end + else + TriggerClientEvent("QBCore:Notify", source, "Wrong usage!") + end + else + TriggerClientEvent("QBCore:Notify", source, "Wrong usage!") + end + else + TriggerClientEvent("QBCore:Notify", source, "Wrong usage!") + end +end, 'admin') + + +QBCore.Functions.CreateCallback("ps-multijob:getJobs", function(source, cb) + local Player = QBCore.Functions.GetPlayer(source) + local jobs = GetJobs(Player.PlayerData.citizenid) + local multijobs = {} + local whitelistedjobs = {} + local civjobs = {} + local active = {} + local pendingJobs = {} -- Track jobs that might be loaded later + + -- Initialize active jobs count + local Players = QBCore.Functions.GetPlayers() + for i = 1, #Players, 1 do + local xPlayer = QBCore.Functions.GetPlayer(Players[i]) + if xPlayer then + active[xPlayer.PlayerData.job.name] = active[xPlayer.PlayerData.job.name] or 0 + if xPlayer.PlayerData.job.onduty then + active[xPlayer.PlayerData.job.name] = active[xPlayer.PlayerData.job.name] + 1 + end + end + end + + for job, grade in pairs(jobs) do + if QBCore.Shared.Jobs[job] == nil then + -- Store this job for later processing + pendingJobs[job] = grade + else + local online = active[job] or 0 + local getjobs = { + name = job, + grade = grade, + description = Config.Descriptions[job] or "No description available", + icon = Config.FontAwesomeIcons[job] or "fa-solid fa-briefcase", + label = QBCore.Shared.Jobs[job].label, + active = online, + } + + -- Safer access to grade properties + if QBCore.Shared.Jobs[job].grades and QBCore.Shared.Jobs[job].grades[tostring(grade)] then + getjobs.gradeLabel = QBCore.Shared.Jobs[job].grades[tostring(grade)].name or "Unknown" + getjobs.salary = QBCore.Shared.Jobs[job].grades[tostring(grade)].payment or 0 + else + getjobs.gradeLabel = "Unknown" + getjobs.salary = 0 + end + + if Config.WhitelistJobs[job] then + whitelistedjobs[#whitelistedjobs+1] = getjobs + else + civjobs[#civjobs+1] = getjobs + end + end + end + + multijobs = { + whitelist = whitelistedjobs, + civilian = civjobs, + } + cb(multijobs) +end) + +RegisterNetEvent("ps-multijob:changeJob",function(cjob, cgrade) + local source = source + local Player = QBCore.Functions.GetPlayer(source) + + if cjob == "unemployed" and cgrade == 0 then + Player.Functions.SetJob(cjob, cgrade) + return + end + + local jobs = GetJobs(Player.PlayerData.citizenid) + for job, grade in pairs(jobs) do + if cjob == job and cgrade == grade then + Player.Functions.SetJob(job, grade) + end + end +end) + +RegisterNetEvent("ps-multijob:removeJob",function(job, grade) + local source = source + local Player = QBCore.Functions.GetPlayer(source) + RemoveJob(Player.PlayerData.citizenid, job) +end) + +-- QBCORE EVENTS + +RegisterNetEvent('ps-multijob:server:removeJob', function(targetCitizenId) + MySQL.Async.execute('DELETE FROM multijobs WHERE citizenid = ?', { targetCitizenId }, function(affectedRows) + if affectedRows > 0 then + print('Removed job: ' .. targetCitizenId) + else + print('Cannot remove job: ' .. targetCitizenId) + end + end) +end) + +RegisterNetEvent('QBCore:Server:OnJobUpdate', function(source, newJob) + local source = source + local Player = QBCore.Functions.GetPlayer(source) + local jobs = GetJobs(Player.PlayerData.citizenid) + local amount = 0 + local setjob = newJob + for k,v in pairs(jobs) do + amount = amount + 1 + end + + local maxJobs = Config.MaxJobs + if QBCore.Functions.HasPermission(source, "admin") then + maxJobs = math.huge + end + + if amount < maxJobs and not Config.IgnoredJobs[setjob.name] then + local foundOldJob = jobs[setjob.name] + if not foundOldJob or foundOldJob ~= setjob.grade.level then + AddJob(Player.PlayerData.citizenid, setjob.name, setjob.grade.level) + end + end +end) + +-- Add the event listener for jobs_creator +RegisterNetEvent("jobs_creator:injectJobs", function(jobs) + -- This will run when jobs are injected by jobs_creator + print("ps-multijob: Jobs have been updated by jobs_creator") + + -- Optional: You could notify online players that jobs have been updated + -- This would allow them to refresh their job menu to see any new jobs + local Players = QBCore.Functions.GetPlayers() + for i = 1, #Players do + local Player = QBCore.Functions.GetPlayer(Players[i]) + if Player then + TriggerClientEvent('QBCore:Notify', Players[i], "Job system has been updated", "success") + end + end +end)