Live
Warrants and criminal justice
A connected justice system for a police roleplay community: arrest warrants, criminal records, felonies, bail and appeals, with server-side checks on every action.
- Role
- Design and implementation
- Stack
- Lua (GLua), MySQL, Discord webhooks
- Context
- Police and criminal roleplay on Diverge Networks
- Status
- Live
The problem
Police roleplay depends on its paperwork. The server needed warrants officers could file and act on, records that hold up, and consequences that carry across the game, all without trusting anything a player’s game client sends.
Warrants
- Officers file, search and manage warrants through an in-game police computer, with paginated lists of active warrants.
- Every action checks rank-based permissions on the server, including access for government roles, and database requests are rate-limited per player.
- Submitted charges are rebuilt on the server against the real charge list, and capped at ten counts per warrant.
- The supporting document link has to start with the expected domain, trailing slash included, so lookalike domains are rejected.
- One active warrant per person. Executing a warrant requires the suspect to be cuffed, restrained and inside the jail area, and the server re-checks that the warrant belongs to them before closing it.
- Issuing, rescinding and executing a warrant each fire an event. A pager message to the wanted person, a Discord post for the police team and an in-game wanted flag are separate listeners, so none of them can break the others.
- The Discord webhook is set at runtime through a rank-gated admin command and never stored in code.
- Plate checks, plus stolen plates that can be fitted to stolen vehicles and expire after 30 minutes.
Screenshot coming soon
The warrant submission form, filled in with test data.
assets/projects/justice-system/warrant-form.png (tight crop to the panel)
Screenshot coming soon
The list of active warrants, showing pagination.
assets/projects/justice-system/warrant-list.png (tight crop to the panel)
Screenshot coming soon
The in-game pager message a wanted character receives.
assets/projects/justice-system/pager.png (tight crop)
Screenshot coming soon
The Discord post for a new warrant, with server and channel names blurred.
assets/projects/justice-system/discord-embed.png (crop to the message only)
Video (optional) coming soon
Filing a warrant, seeing it appear in the list, then arresting the suspect through the context menu.
assets/projects/justice-system/warrant-arrest.mp4 (20 to 30 seconds)
Code excerpt coming soon
The warrant filing handler: permissions, rate limiting, rebuilding client-supplied charges, and the duplicate check.
assets/excerpts/issue-warrant.lua
Felonies and records
- Any felony charge marks a character as a felon.
- Felon status shows on in-game ID cards.
- Shops can restrict each item to everyone, felons only or non-felons only, enforced on the server at the moment of trade.
- Staff manage the charge list in-game, with every charge validated against a fixed schema.
- Records management was rewritten to work on the new data system, including for characters who are offline.
Screenshot coming soon
A criminal record with the felony flag visible.
assets/projects/justice-system/record-felony.png (tight crop to the panel)
Screenshot coming soon
An ID card showing felon status.
assets/projects/justice-system/id-card-felon.png (tight crop)
Appeals, bail and consent
- Appeals. Government characters can clear felony status, but only on records the server has shown them. The server keeps the list of record IDs it sent each player and rejects anything else, so changing an ID in the request does nothing.
- Bail. Prisoners can refuse being bailed out, which stopped bail being used to pull people out of jail against their will.
- Consent. Permanent character death as an alternative to a prison sentence requires the player’s consent within a time limit. Refusing sends them to trial instead, and disconnecting doesn’t dodge the decision.
Code excerpt coming soon
The appeals handler, which only accepts record IDs the server previously sent to that player.
assets/excerpts/records-allowlist.lua