Knight docs
EN ID
GitHub

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
VariableDefaultMeaning
KNIGHT_VOICE_URLhttp://127.0.0.1:7788sidecar address
KNIGHT_VOICE_RANGE30hearing radius in world units

2. Natives

NativeReturnsPurpose
VoiceJoin(playerid)boolRegister with the sidecar
VoiceLeave(playerid)boolRemove from the sidecar
VoiceMute(playerid, bool)boolSilence their outgoing audio
VoiceDeafen(playerid, bool)boolSilence their incoming audio
VoicePeers(playerid)stringComma-separated ids they can hear
VoiceInRange(playerid, other)boolLocal check, no sidecar call
VoiceSetRange(float)boolChange the radius

3. Automatic behaviour

EventAction
player::spawnjoin the voice room
player::updateforward position
player::disconnectleave 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

RuleEffect
Same worldPlayers in another interior/world hear nothing
Within rangeDefault 30 units, 3D distance
Not mutedA muted speaker is inaudible to everyone
DeafenedThat listener hears nothing, but is still audible
-teamsIf 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.