Two Admin Scripts That Saved Me Hours of Server Management in QBCore
Source: Dev.to
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 — 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
Permission system
The script checks permissions in two layers — txAdmin ACE first, then QBCore’s native admin/god flags. This works on both txAdmin‑managed servers and vanilla QBCore setups.
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 only sends requests. Unauthorized attempts to call the server event are blocked.
ps‑multijob integration
If a player has the same job as a side job in ps‑multijob and you assign it as their main job, a conflict occurs. The script handles this automatically — before setting a new main job, it removes any matching side‑job entry.
-- 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 as well — a single 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.
- All currently online players with their current job.
The admin selects a player, chooses a job and grade, and submits. The change applies immediately, and notifications are sent to both the admin and the target player.
lokat_cleanup — Inactive player pruning tool
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 timestamps are older than the threshold.
Results are grouped by license (one row per account) and display:
- Character names linked to the account
- Last active date
- Number of owned vehicles
- 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 so, the deletion is blocked.
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
For large player databases, the UI supports character‑name search, pagination, and sorting (oldest‑first or newest‑first).
Config overview
Both scripts use a simple config file.
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 direct database access or navigating menus that weren’t designed for speed. These two scripts are purpose‑built for the specific operations I performed repeatedly, eliminating a lot of friction from day‑to‑day server management.
Next up: Vol.5 — Building a Custom Vending Machine System for QBCore.