Features
How every part of oxide-radio works — channels, access control, encryption, the panel, the roster overlay, and job integration.
How every part of oxide-radio works, from the server owner's point of view.
The one-radio model
oxide-radio gives your whole server a single radio. Every player uses the same inventory item (radio by default) to open it. There are no separate "police radio" or "EMS radio" items — whether someone can join a restricted channel is decided by their job, not by what item they're carrying.
That means setup is simple: hand out one item, and access sorts itself out based on who each player is. A civilian and a police officer carry the identical radio; the officer just sees and can join channels the civilian can't.
- One item for everyone —
Config.Item(default'radio') - Require it or not — with
Config.RequireItem = true(the default), a player must be holding the radio item to tune in and stay connected. Set it tofalseto let anyone use the radio without an item
Open frequencies
An open frequency is a civilian channel that anyone with a radio can tune to. Every whole number inside the dial range is an open frequency, unless it's been reserved as a restricted job channel.
- The dial range is set by
Config.MinFrequencyandConfig.MaxFrequency(default 1 to 9999). - Players tune in by typing a number, using the +/- steppers, or picking one from their favorites.
- Anyone on the same open frequency can hear each other (as long as
pma-voiceis running). - Open frequencies can be password-locked by the players using them.
Only free tuning is limited to the dial range. Restricted job channels can sit on any frequency at all, even outside 1–9999 — the range only controls which numbers civilians can freely dial.
Restricted job channels
A restricted channel is a frequency reserved for one or more jobs. Only players whose job qualifies can tune in. You define these in Config.JobChannels, and other resources (like police and EMS) can register their own at runtime.
Each restricted channel has:
| Setting | What it does |
|---|---|
label | The name shown on the radio for this frequency (e.g. "Police Dispatch") |
jobs | The list of job names allowed on this frequency — case-sensitive, list every spelling your server uses |
minRank | The lowest job grade allowed (0 = any grade). Use this to keep a command channel to senior ranks |
dutyOnly | When true, a player must be clocked in (on duty) to join |
default | When true, players of these jobs are tuned to this frequency automatically when they clock on |
Example from the default config:
| Frequency | Label | Jobs | Min rank | Duty only | Clock-on default |
|---|---|---|---|---|---|
1 | Police Dispatch | police, lspd, bcso, ... | 0 | No | Yes |
2 | Police Tac 1 | police, lspd, bcso, ... | 0 | No | No |
3 | Police Command | police, lspd, bcso, ... | 3 | No | No |
4 | EMS Dispatch | ambulance, ems, EMS | 0 | No | Yes |
5 | EMS Tac | ambulance, ems, EMS | 0 | No | No |
Job names must match your server exactly, including capitalization. If your framework calls the police job police, put 'police'; if it's LSPD, put 'LSPD'. The defaults list several common spellings so they work on more servers — edit them down to the ones you actually use.
How a player joins a restricted channel
- The player opens the radio. Channels their job qualifies for show up as one-tap entries in the panel.
- They tap the channel (or type the frequency and tune in).
- The server checks their job, rank, duty, and radio item. If everything passes, they're connected.
- If they don't qualify — wrong job, rank too low, or off duty on a duty-only channel — they get a clear message telling them why.
Duty is only required to join a duty-only channel, not to see it in the list.
Access control and enforcement
Access is server-authoritative. The server decides who's allowed on each channel, and it enforces that decision down at the pma-voice layer — so a player using a modded/cheat client cannot force themselves onto a restricted or encrypted channel. Sending fake data to the voice system just gets them kicked back off.
What's checked every time someone tries to join:
- Radio item — do they have the
radioitem (whenConfig.RequireItemis on)? - Job — is their job in the channel's
jobslist? - Rank — is their job grade at least the channel's
minRank? - Duty — if the channel is
dutyOnly, are they clocked in? - Password — if the frequency is encrypted, did they provide the right password?
Access is re-checked, not just checked once
A player who qualified when they joined might stop qualifying later — they get fired, go off duty, or drop their radio. oxide-radio handles this:
- The moment a player's job or duty changes, their current channel is re-checked. If they no longer qualify, they're taken off it and told so.
- On a repeating timer (
Config.RevalidateInterval, default 30 seconds; set to0to turn it off), everyone on a restricted channel is re-checked. This catches changes that don't fire an event, like a player quietly dropping their radio item or toggling duty.
The result: restricted channels stay restricted to the people who currently belong on them, automatically.
Channel encryption
Any player currently tuned to an open frequency can put a password on it. This turns it into an encrypted channel that others must unlock.
- Setting a lock — a player tuned to an open frequency opens the encryption manager in the panel and sets a password (6–32 characters). From then on, others need that password to join or even to see who's on the channel.
- Joining a locked channel — a player enters the password once. If it's right, they're in; if it's remembered from before, they join automatically.
- Changing or removing a lock — changing the password in place requires knowing the current one (that applies to everyone). Removing the lock is different: the person who created it, or a server admin, can remove it without any password; anyone else needs the current password. A creator who forgot the password can simply remove the lock and set a fresh one.
- Passwords are never exposed. They're stored on the server salted and hashed — never as plain text, and never sent to other players' clients.
Brute-force protection
Guessing passwords is throttled. After 5 wrong attempts, that player is locked out from trying for 5 minutes. The lockout is tracked per character and survives a reconnect, so someone can't dodge it by rejoining the server.
Admin recovery
If a password is lost, or a griefer locks a channel to be annoying, an admin can force the lock off with /radio unlock <frequency> — no password needed. See Admin Guide.
Only open frequencies can be encrypted. Restricted job channels are gated by job, not by password, so they can't be password-locked.
The radio panel
Using the radio item opens the handheld radio panel. It contains:
- A frequency dial — type a number directly, or use the +/- steppers to move up and down.
- Tune In / Disconnect — join the entered frequency, or leave your current channel.
- Your job channels — one-tap entries for the restricted channels your job qualifies for.
- The channel browser — see below.
- Favorites — star frequencies you use often for quick access.
- The encryption manager — for the open frequency you're tuned to: add, change, or remove a password.
- User settings — set your radio display name, choose your mic-click sound, and reposition the on-screen overlay.
While the panel is open, your character holds the radio up (a phone-style pose). Closing the panel (or pressing ESC) puts it away. You can't open the radio while dead or downed.
The channel browser
The browser is a TeamSpeak-style list inside the panel showing every channel that currently has someone on it, and who's on each one. It's scoped to you — you only see what you're allowed to see:
- Open channels — always visible, with their full member list.
- Restricted channels — you only see the members if your job qualifies for that channel. If it's not your channel, you can see it exists and how many people are on it, but not who.
- Encrypted channels — members are hidden until you unlock the channel with its password (or you're already on it).
This keeps players from metagaming — a civilian can't read the police roster off the radio.
The on-screen roster overlay
The overlay is a small, subtle heads-up list of who's on your current channel, shown in the corner of the screen. It's designed to stay out of the way:
- It's Discord-style — quiet and faint when nobody's talking, and it brightens and highlights whoever is speaking, live.
- Each member shows their display name, an optional badge tag (e.g. an officer's badge number), and a downed indicator if they've been reported as down.
- Toggle it with the overlay keybind — default U (
Config.OverlayKey). Players can rebind this in Settings → Key Bindings → FiveM in their own game; the config value is only the default for players who've never set it. - The overlay only exists when
Config.ShowRosteris on (it is by default). - Players can reposition the overlay from the panel's user settings — drag it wherever they like, and it stays there.
Radio display names
Each player can set a radio display name — the name shown next to them on rosters and overlays instead of their character name. It's set in the panel's user settings, stored per character, and remembered between sessions.
This is handy for departments that use call signs or unit numbers on the air. Names are 2–32 characters.
Mic clicks, favorites, and remembered passwords
These are personal, per-client preferences — they follow the player's game install, across characters:
- Mic clicks — the little click sound when keying the radio. Each player chooses Default, On, or Off in the panel's user settings. This drives
pma-voice's own mic-click setting. "Default" leavespma-voice's setting alone; "On"/"Off" force it and are re-applied each time the game starts. - Favorites — players can star frequencies they use often for one-tap tuning.
- Remembered passwords — when a player unlocks an encrypted channel, the radio can remember that password so they don't have to re-enter it next time. If a remembered password stops working (someone changed it), the radio quietly forgets it and prompts fresh.
Roster tags and downed flags
These are aimed at integration with other resources, and need no configuration on your part:
- Badge tags — another resource can put a short tag next to a member's name on the roster (via the
SetMemberTagexport).oxide-policeuses this to show each officer's badge number. If you don't run a resource that sets tags, members simply show no tag. - Downed flag — members show as "down" on the roster when a death or medical resource reports them as dead or downed. This works through
o-link's death events, so it picks up whatever death system you run (oxide-death, QBCore, QBX, ESX, etc.) with no hard dependency. A resource can also set it directly via theSetRadioDeadexport.
See Exports & API Reference for how integrators use these.
Job resource integration
When you run the studio's job resources alongside oxide-radio, they wire themselves up automatically:
oxide-policeregisters its department channels withoxide-radioand puts officers on their default channel when they clock on, showing each officer's badge number on the roster. Ifoxide-policehad its own built-in radio, it stands that down whenoxide-radiois installed and mirrors its channels here instead.oxide-emsdoes the same for EMS channels.
You configure those department channels inside those resources' own admin menus, not in oxide-radio. The Config.JobChannels here are for jobs that don't have a resource doing this for them. Runtime channels registered by a resource take priority over a config channel on the same frequency, and are released automatically if that resource stops.
Running without pma-voice
pma-voice provides the actual voice audio. If it isn't installed (or the voice_enableRadios convar is off), oxide-radio still runs:
- The radio panel opens and everything on screen works — tuning, the browser, encryption, display names.
- Players see a clear "voice unavailable" banner so they know audio is offline.
- No voice is transmitted, because there's no voice backend to carry it.
This lets you install and configure the radio before your voice system is ready, and it fails gracefully if pma-voice is ever stopped. Install pma-voice (and start it before oxide-radio) to enable audio.
Next Steps
- Configuration — every setting explained
- Admin Guide — admin commands and the settings menu
- Exports & API Reference — developer reference for integrators
- Troubleshooting — fixes for common problems