Voice Plugin
Proximity voice that never touches the game protocol.
SA-MP 0.3.7 and 0.3.DL have no voice channel, so audio cannot travel over RakNet. Knight solves this with a sidecar: the server decides who should hear whom, and the audio is carried by a separate transport (WebRTC or anything else). Gameplay latency is unaffected because audio never enters the tick.
text
game client ── Knight server ── voice sidecar ── audio transport ── game client
│ │
player::update proximity groups
1. Run it
bash
# 1. sidecar (separate process)
./knight-voice -addr :7788 -range 30
# 2. server with the voice plugin compiled in
KNIGHT_VOICE_URL=http://127.0.0.1:7788 ./knight-server -cfg "" -gamemode Gamemodes/voice.sa
| Variable | Default | Meaning |
|---|---|---|
KNIGHT_VOICE_URL | http://127.0.0.1:7788 | sidecar address |
KNIGHT_VOICE_RANGE | 30 | hearing radius in world units |
2. Natives
| Native | Returns | Purpose |
|---|---|---|
VoiceJoin(playerid) | bool | Register with the sidecar |
VoiceLeave(playerid) | bool | Remove from the sidecar |
VoiceMute(playerid, bool) | bool | Silence their outgoing audio |
VoiceDeafen(playerid, bool) | bool | Silence their incoming audio |
VoicePeers(playerid) | string | Comma-separated ids they can hear |
VoiceInRange(playerid, other) | bool | Local check, no sidecar call |
VoiceSetRange(float) | bool | Change the radius |
3. Automatic behaviour
| Event | Action |
|---|---|
player::spawn | join the voice room |
player::update | forward position |
player::disconnect | leave the room |
Note
The hooks always return true. If the sidecar is offline, gameplay continues and
VoiceJoin returns false.4. Example
knight
player::spawn() {
if (!VoiceJoin(playerid)) {
SendClientMessage(playerid, "Voice tidak tersedia.");
}
};
player::command("/who") {
SendClientMessage(playerid, "Dengar: [{VoicePeers(playerid)}]");
};
player::command("/mute") {
VoiceMute(playerid, true);
};
5. Membership rules
| Rule | Effect |
|---|---|
| Same world | Players in another interior/world hear nothing |
| Within range | Default 30 units, 3D distance |
| Not muted | A muted speaker is inaudible to everyone |
| Deafened | That listener hears nothing, but is still audible |
-teams | If enabled on the sidecar, only same-team players connect |
6. Testing with a bot
bash
./knight-voice -addr 127.0.0.1:7788 -range 30 &
./knight-voicebot -url http://127.0.0.1:7788 -bots 5 -steps 8
The bot joins several players, walks them around, mutes, deafens and leaves, then fails if any listener hears a muted, far, out-of-world or departed player.
7. What is not included
Audio capture inside the SA-MP client, which the protocol cannot carry; players use a browser or app alongside the game. The sidecar is transport-agnostic: pion/webrtc is already a dependency if you want to add an SFU.