The problem with managing a live RP server
Running a QBCore RP server means dealing with two recurring headaches:
- Players get stuck in the wrong job, or you need to assign roles fast during a session — and doing it through the database or existing admin menus is slow.
- Inactive players accumulate in the database over months. Ghosts with vehicles, characters, and data that will never be used again.
I built two scripts to solve both: lokat_adminjob for real-time job management, and lokat_cleanup for database pruning.
lokat_adminjob — Job assignment from a UI panel
The idea is simple: open a panel with a command, pick a player from the online list, pick a job and grade, and apply it instantly. No database queries, no server restarts, no fumbling through existing admin menus.
Permission system
The script checks permissions in two layers — txAdmin ACE first, then QBCore's native admin/god flags. This means it works whether you're running a txAdmin-managed server or a vanilla QBCore setup.
local function hasAdmin(src)
if IsPlayerAceAllowed(src, Config.AceName) then
return true
end
if QBCore.Functions.HasPermission(src, 'admin')
or QBCore.Functions.HasPermission(src, 'god') then
return true
end
return false
end
Permission checks always run server-side. The client never makes the decision — it just sends requests. If someone tries to call the server event directly without permission, they get blocked.
ps-multijob integration
This is the part that saves the most headaches. If a player has the same job as a side job in ps-multijob and you assign it as their main job, you get a conflict. The script handles this automatically — before setting a new main job, it removes any matching side job entry from ps-multijob.
-- Remove conflicting side job before assigning main job
PMJ_RemoveJobByName(target, jobName)
target.Functions.SetJob(jobName, grade)
When removing a job entirely (setting to unemployed), it clears all side jobs too — one clean operation.
What the panel shows
When an admin opens the panel, the server sends a live snapshot: all available jobs with their grade levels, and all currently online players with their current job. The admin selects a player, selects a job and grade, and submits — the change applies immediately with notifications sent to both the admin and the target player.
lokat_cleanup — Inactive player pruning tool
Over time, inactive players pile up in the database. After years of server operation, you end up with hundreds of accounts that haven't logged in for months — each with characters, vehicles, and associated data.
lokat_cleanup is an admin UI that lets you find and delete these accounts safely.
How it works
Open the UI with a command, set the inactivity threshold (default: 60 days), and the script queries the database for accounts where all characters' last_updated timestamp is older than the threshold.
Results are grouped by license (one row per account, not per character) and show:
- Character names linked to the account
- Last active date
- Number of vehicles owned
- Total character count
-- Group by license, get the most recent activity across all characters
SELECT license FROM players
GROUP BY license
HAVING MAX(last_updated) <= (NOW() - INTERVAL ? DAY)
Safety checks
Before deleting any account, the server checks whether any character on that license is currently online. If they are, the delete is blocked — no accidents.
for _, row in ipairs(rows) do
local p = QBCore.Functions.GetPlayerByCitizenId(row.citizenid)
if p then
cb({ ok = false, error = 'player_online' })
return
end
end
You can also choose whether to delete associated vehicles — toggled per deletion.
Search and pagination
With large player databases, listing everything at once isn't practical. The UI supports character name search and pagination. Results can be sorted oldest-first or newest-first.
Config overview
Both scripts use a simple config file. Key settings:
lokat_adminjob:
Config.AceName = 'your_ace_permission_name'
Config.OpenCommand = 'your_command_name'
Config.MultiJob = { Enable = true }
lokat_cleanup:
Config.MinDaysInactiveDefault = 60 -- adjust to your needs
Config.PageSize = 50
Config.UseAcePermission = true
Config.AceName = 'your_ace_permission_name'
Why these exist
Most admin tasks in QBCore require either database access or navigating menus that weren't designed for speed. These two scripts are purpose-built for the specific operations I was doing repeatedly — and they eliminated a lot of friction from day-to-day server management.
Next up: Vol.5 — Building a Custom Vending Machine System for QBCore.
Built with Claude Opus as my coding partner. I handle system design and edge case thinking — the AI handles implementation.
Questions about the implementation? Drop a comment.
Top comments (0)