proxdocs

Dokumentation

Prox einrichten und erweitern.

Alles, was du für Prox brauchst: von der ersten Zeile in der server.cfg bis zu Team-Sperren, Funk-Rechten und eigenen Scripts.

Nichts gefunden. Versuch ein anderes Wort.

Überblick

Prox ist ein Voice-Chat für FiveM, der ohne TeamSpeak auskommt. Spieler öffnen einmal einen Browser-Tab auf proxvoice.net, koppeln ihn mit einem Code und reden danach mit allen in der Nähe, über Funk oder Telefon.

  • 3D-Ton mit Entfernung, Richtung, gedämpftem Klang in geschlossenen Fahrzeugen und Hall in Innenräumen.
  • Funk mit zwei Kanälen, echter Funk-Klangqualität, Dauerfunk, Mitgliederlisten und Job-Rechten.
  • Telefon inklusive Lautsprecher, den Umstehende hören.
  • Kompatibel mit den Exports und Events von SaltyChat und pma-voice. Bestehende Handys, Funkgeräte und HUDs laufen meist ohne Änderung weiter.
  • Gehostet: Die Voice-Server betreiben wir. Du trägst nur deinen Schlüssel ein.

Gesprochen wird über drei Teile: die FiveM-Ressource prox auf deinem Server, unsere Voice-Server und den Browser-Tab der Spieler. Positionen und Rechte kommen immer von deinem Server, nie vom Spieler. Deshalb kann niemand seine Position fälschen oder sich in fremde Funkkanäle hören.

Installation

  1. Server anlegen. Melde dich im Panel mit Discord an und lege einen Server an. Bis 50 Spieler ist das kostenlos. Unter „Einrichtung“ steht dein Schlüssel.
  2. Ressource einfügen. Lade die Ressource herunter und lege den Ordner prox in deinen resources-Ordner. Der Name muss prox bleiben.
  3. server.cfg ergänzen. Andere Voice-Ressourcen (SaltyChat, pma-voice) vorher entfernen.
    ensure prox
    set prox_key "dein-schlüssel-aus-dem-panel"
    
  4. Server starten. In der Konsole erscheint [prox] verbunden als "Dein Server". Fertig.
Die Adresse des Voice-Servers holt sich Prox selbst. Fällt ein Voice-Server aus, wechselt Prox automatisch auf einen anderen, ohne dass du etwas tun musst.

Startreihenfolge

Starte prox nach deinem Framework (es_extended oder qb-core) und vor Ressourcen, die SaltyChat- oder pma-voice-Exports nutzen, zum Beispiel Handy oder Funkgerät.

ensure oxmysql
ensure es_extended
ensure prox
ensure mein_handy
ensure mein_funk

Für Spieler

Beim ersten Joinen öffnet sich ingame ein Fenster mit einem Link und einem 6-stelligen Code. Spieler öffnen den Link im Browser, erlauben das Mikrofon und sind verbunden. Ab dann reicht es, den Tab offen zu lassen. Beim nächsten Mal verbindet er sich von selbst.

TasteFunktion
NSprechen (gedrückt halten)
FeststellFunk, primärer Kanal (gedrückt halten)
JDauerfunk an/aus. Alles, was du sagst, geht über den Funk.
YSprachreichweite wechseln
F9Mikrofon stumm
F7Voice-Fenster öffnen (Link und Code)

Alle Tasten lassen sich in GTA unter Einstellungen → Tastenbelegung → FiveM ändern. Die Standardtasten legst du in der Config fest.

Im Browser-Tab

  • Sprachaktivierung statt Push-to-Talk, Lautstärke pro Spieler, Spieler stumm schalten (bleibt gespeichert)
  • Soundboard, Stimmenverzerrer, Dauerfunk-Knopf (Taste R im Tab)
  • Verbindungsanzeige mit Ping und Verlust. Bei schlechter Leitung senkt Prox die Qualität automatisch, statt abzubrechen.
Chrome-Tipp: Chrome bremst Tabs im Hintergrund. Unter Einstellungen → Leistung bei „Websites immer aktiv lassen“ proxvoice.net eintragen.

Config

Alle Einstellungen stehen in config.lua. Diese Datei ist offen und bleibt bei Updates deine.

OptionStandardBedeutung
Framework'auto''esx', 'qb' oder 'custom'. Wird für Job-Rechte und das Verbinden-Fenster genutzt.
Ranges{3, 8, 15, 32}Sprachreichweiten in Metern
DefaultRange2Startreichweite (Index in Ranges)
MaxClientRange32.0Größte Reichweite, die ein Client selbst setzen darf
Keyssiehe DateiStandardtasten: talk, radio1, radio2, radioLatch, range, mute, deaf, connect
AllowVoiceActivationtrueSprachaktivierung im Browser erlauben
AllowSoundboardtrueSoundboard im Browser erlauben
RangeCircleanKreis am Boden beim Wechseln der Reichweite: marker, color, alpha, duration, animate, onForced
OverlaytrueKleine Statusleiste ingame
Prompt.enabledtrueVerbinden-Fenster automatisch zeigen
Prompt.event'auto'Erst nach diesem Client-Event zeigen. 'auto' nimmt esx:playerLoaded bzw. QBCore:Client:OnPlayerLoaded, '' sofort.
Prompt.delay4000Verzögerung danach in ms
RadioAnimationFunkgerät am Ohrenabled, dict, name, duration (-1 = solange gefunkt wird), inVehicle, skip (Funktion, die true liefert, um die Animation zu überspringen)
BlockShootingWhileRadiofalseBeim Funken nicht schießen
Soundstruetrue = Prox-Sounds, 'gta' = GTA-Funksounds, false = aus
SoundVolume1.0Lautstärke der Prox-Sounds
RadioSiehe Funk und Jobs
DeathanBewusstlose können nicht sprechen. stateKeys sind Statebag-Werte, die als tot gelten.
LimitWarningan, alle 10 minKonsolenwarnung ab 90 % der Plätze
ClientCallstrueTelefonate über Client-Exports (pma-voice) erlauben
NotifyEvent''Eigenes Notify-Event, z. B. 'esx:showNotification'. Leer = GTA-Benachrichtigung.
TextAlle Texte, die Spieler sehen

Convars

ConvarBedeutung
prox_keyDein Lizenzschlüssel (Pflicht)
prox_debug1 = ausführliche Logs in der Konsole
prox_check_msWie oft Positionen und Tod geprüft werden (Standard 1000, verteilt über alle Spieler)

Funk und Jobs

Frequenzen sind frei wählbare Texte oder Zahlen. Wer in welche Frequenz darf, prüft immer dein Server.

Config.Radio = {
    public = true,
    ranges = {
        { from = 1, to = 10, jobs = { 'police', 'sheriff', 'fib' } },
        { from = 11, to = 15, jobs = { 'ambulance' } }
    },
    check = function(source, frequency, job)
        return nil
    end
}
  • ranges sperren Zahlenbereiche für Jobs. Kommazahlen gehen auch, 1.5 liegt im Bereich 1 bis 10.
  • public regelt alle Frequenzen ohne Regel. Mit false ist alles gesperrt, was du nicht freigibst.
  • check ist deine eigene Prüfung. true erlaubt, false verbietet, nil lässt die normalen Regeln entscheiden.

Wechselt ein Spieler den Job (esx:setJob bzw. QBCore:Server:OnJobUpdate), prüft Prox seine Funkkanäle neu und wirft ihn aus Frequenzen, für die er keine Rechte mehr hat. Bei eigenem Framework löst du das selbst aus:

TriggerEvent('prox:recheckRadio', source)

Eigenes Framework

Config.Framework = 'custom'

Config.GetJob = function(source)
    return exports['mein_core']:GetJob(source)
end

Regeln aus Scripts

Einzelne Frequenzen kannst du zur Laufzeit festlegen. Das hat Vorrang vor der Config.

exports['prox']:SetRadioPermission('swat', function(source, frequency)
    return IsPlayerAceAllowed(source, 'swat.radio')
end)

exports['prox']:SetRadioPermission('event', { 12, 48, 77 })
exports['prox']:SetRadioPermission('geschlossen', false)
exports['prox']:SetRadioPermission('swat', nil)

Ingame-UI anpassen

Die Statusleiste und das Verbinden-Fenster liegen offen in nui/index.html. Farben, Schriften und Position kannst du dort frei ändern. Die Sounds liegen in nui/sounds und lassen sich durch eigene .wav-Dateien mit gleichem Namen ersetzen.

Ändere nur Aussehen und Texte. Die Logik im Script-Teil der Datei steuert die Verbindung zum Browser-Tab.

Server-Exports

Alle Exports gibt es unter exports['prox']. src ist immer die Server-ID des Spielers. Sprechmodi: 0 still, 1 in der Nähe, 2 Funk primär, 3 Funk sekundär.

Status

ExportRückgabe
IsVoiceConnected(src)true, wenn der Browser-Tab verbunden ist
GetConnection(src){ connected, level, quality, ping, loss }
IsTalking(src) / GetTalkMode(src)Spricht gerade / Sprechmodus
GetActiveTalkers()Liste { src, mode, radio } aller, die gerade sprechen
IsSelfMuted(src) / IsDeafened(src)Selbst stumm / Ton aus
GetVoiceStats(){ players, waiting, max, connected }

Funk

ExportBeschreibung
SetRadio(src, freq, primary)Kanal setzen, '' zum Verlassen. primary = false für den zweiten Kanal. Prüft keine Rechte.
GetRadio(src){ primär, sekundär }
CanUseRadio(src, freq)Darf der Spieler in die Frequenz?
GetRadioMembers(freq)Liste { src, name, primary, talking, connected }
GetRadioMemberCount(freq)Anzahl ohne Liste
GetRadioFrequencies(){ [freq] = anzahl } aller belegten Frequenzen
SetRadioPermission(freq, regel)Siehe Regeln aus Scripts
SetRadioLatch(src, on) / IsRadioLatched(src)Dauerfunk setzen / abfragen

Sprache und Telefon

ExportBeschreibung
ForceRange(src, meter)Reichweite festlegen, der Spieler kann sie nicht ändern. nil gibt sie frei.
SetMegaphone(src, on)Megafon (60 m, mit Effekt)
SetCall(src, name)In ein Telefonat. Alle mit gleichem name hören sich. nil beendet.
MutePlayerFor(target, src, on)target hört src nicht mehr (z. B. Blockieren)
ClearMutesFor(target)Alle Sperren von target aufheben
SetRoutingBucket(src, bucket)Nur nötig, wenn du Buckets ohne SetPlayerRoutingBucket verwaltest. Sonst erkennt Prox sie selbst.
RegisterNetEvent('mein_handy:anrufen', function(target)
    local src = source
    if not Handy.KannAnrufen(src, target) then return end
    local name = ('call:%d:%d'):format(math.min(src, target), math.max(src, target))
    exports['prox']:SetCall(src, name)
    exports['prox']:SetCall(target, name)
end)

Team-Sperren

Sperren gelten pro Spieler (Rockstar-Lizenz) und bleiben über Reconnects und Server-Neustarts erhalten. Im Browser-Tab sieht der Spieler „vom Team gesperrt“ samt Ablaufzeit.

ExportBeschreibung
AdminMute(src, sekunden, grund, von)Mikrofon sperren. 0 oder nil = dauerhaft.
AdminUnmute(src)Freigeben
AdminDeafen(src, sekunden, grund, von)Ton sperren, der Spieler hört niemanden
AdminUndeafen(src)Freigeben
GetAdminState(src){ muted, mutedUntil, deafened, deafUntil, reason, by }. -1 = dauerhaft.
GetAdminList()Alle aktiven Sperren, auch von Spielern, die offline sind
AdminClear(src | license)Alle Sperren eines Spielers löschen, auch offline per Lizenz
RegisterCommand('vmute', function(source, args)
    if not IstTeam(source) then return end
    local target = tonumber(args[1])
    local minuten = tonumber(args[2]) or 10
    exports['prox']:AdminMute(target, minuten * 60, table.concat(args, ' ', 3), GetPlayerName(source))
end, false)
Rechte immer serverseitig prüfen. Prox-Exports gibt es nur auf dem Server, ein Client kann sie nicht aufrufen.

Nur Funk

Für Gangkriege, Events oder Einsätze: Spieler sprechen und/oder hören nur noch über Funk. Nähe und Telefon sind dann aus.

exports['prox']:SetRadioOnly(source, true, false)

exports['prox']:SetBucketRadioOnly(42, true, true)
exports['prox']:SetBucketRadioOnly(42, false, false)

local mode = exports['prox']:GetRadioOnly(source)

Bucket-Regeln gelten automatisch für jeden, der den Bucket betritt, und enden beim Verlassen. Spieler-Regeln und Bucket-Regeln addieren sich.

Client-Exports

ExportRückgabe
IsConnected()Browser-Tab verbunden
GetConnection(){ connected, level, ping, loss }
IsTalking() / GetTalkMode()Spricht gerade / Modus
GetRange()Aktuelle Reichweite in Metern
GetRadio()primär, sekundär
GetRadioMembers(freq)Liste { src, name } deines Kanals, ohne Server-Abfrage
IsRadioLatched() / SetRadioLatch(on)Dauerfunk
IsAdminMuted() / IsAdminDeafened()Vom Team gesperrt
GetRadioOnly()talk, hear
AddEventHandler('prox:radioMembers', function(frequency, members)
    for src, name in pairs(members) do
        print(frequency, src, name)
    end
end)

Events

Server (AddEventHandler)

EventArgumente
prox:talksrc, mode
prox:talkersChangedkeine, danach GetActiveTalkers()
prox:clientStatesrc, connected
prox:radioChangedsrc, freq, primary
prox:radioMembersChangedfreq, src, joined
prox:latchChangedsrc, on
prox:selfMutesrc, muted, deafened
prox:adminChangedsrc, 'mute' | 'deafen', on
prox:aliveChangedsrc, alive
prox:qualitysrc, level, ping, loss. Level 0 gut bis 3 kritisch
prox:fullsrc, der Spieler hat wegen des Limits keinen Voice
prox:violationsrc, meter, gemeldete Position weicht ab
prox:lockdownon, Schutzmodus gegen Angriffe

Client (AddEventHandler)

EventArgumente
prox:talkStatemode
prox:rangeChangedmeter, index
prox:clientStateconnected
prox:radioTrafficsrc, freq, on, jemand funkt in deinem Kanal
prox:radioMembersfreq, { [src] = name }
prox:latchChangedon
prox:selfMutemuted, deafened
prox:adminStatemuted, deafened
prox:radioOnlyChangedtalk, hear
prox:connectionQualitylevel, ping, loss

Zusätzlich feuert Prox die bekannten SaltyChat-Events (SaltyChat_TalkStateChanged, SaltyChat_VoiceRangeChanged, SaltyChat_RadioTrafficStateChanged usw.) und pma-voice:radioActive.

Status-API

Für Discord-Bots, Webseiten oder Statusseiten. Lege im Panel unter deinem Server einen API-Schlüssel an. Optional kannst du ihn auf feste IPs und ein Ablaufdatum beschränken.

curl -H "Authorization: Bearer prx_dein_schluessel" https://panel.proxvoice.net/v1/status
{
  "name": "Mein Server",
  "status": "active",
  "players": 412,
  "max_players": 500,
  "peak": 468,
  "connected": true,
  "voice": { "online": true, "city": "Frankfurt am Main", "country": "DE" },
  "expires": null
}

Höchstens 120 Anfragen pro Minute und IP. status ist active, grace, expired oder suspended.

Umstieg von SaltyChat

  1. saltychat aus der server.cfg entfernen und den Ordner löschen. Die TeamSpeak-Convars (VoiceEnabled, ServerUniqueIdentifier usw.) brauchst du nicht mehr.
  2. Prox installieren wie unter Installation.
  3. Fertig. Prox stellt sich als saltychat bereit. exports['saltychat']:SetPlayerRadioChannel(...) und die SaltyChat-Events funktionieren weiter.
SaltyChatStatus
Funk, Telefon, Reichweite, Megafon, TodVoll unterstützt
SetPlayerRadioSpeaker, SetRadioVolumeWerden angenommen, ändern den Klang aber noch nicht
SetRadioTowersWird ignoriert. Funk reicht bei Prox über die ganze Karte, mit zunehmender Entfernung etwas rauer.
TeamSpeak-PluginNicht mehr nötig

Umstieg von pma-voice / Mumble

  1. pma-voice aus der server.cfg entfernen.
  2. Alle voice_*-Zeilen von pma-voice aus der server.cfg entfernen. Ohne pma-voice bleibt der eingebaute Mumble-Voice aus, Spieler hören sich also nicht doppelt.
  3. Prox installieren. Prox stellt sich als pma-voice bereit, setPlayerRadio, setPlayerCall, overrideProximityRange und der Statebag proximity funktionieren weiter.
Funkkanäle von pma-voice sind Zahlen. Prox übernimmt sie als Frequenz, setRadioChannel(5) landet in Frequenz 5. Deine Job-Bereiche in Config.Radio.ranges greifen dabei.

Pakete und Limits

  • Plätze: Jedes Paket hat eine Anzahl gleichzeitiger Voice-Spieler. Ab 90 % erscheint in deiner Serverkonsole eine rote Warnung (abschaltbar mit Config.LimitWarning).
  • Limit erreicht: Wer schon spricht, behält Voice. Neue Spieler sehen „Voice ist gerade nicht verfügbar“ und rücken automatisch nach, sobald ein Platz frei wird. Den Text änderst du in Config.Text.full.
  • Abgelaufen: Voice läuft noch 3 Tage weiter, die Konsole erinnert alle 30 Minuten. Danach ist Voice aus, bis du verlängerst.
  • Team: Im Panel kannst du anderen per Discord-ID Zugriff geben, mit einzelnen Rechten für Schlüssel, API und Team.

Befehle

BefehlWoFunktion
/proxSpielerNeuen Code anfordern, z. B. für ein zweites Gerät
/proxnetSpielerVerbindungsqualität anzeigen
/proxstatusSpieler (F8)Technischer Status für die Fehlersuche
prox_lockdown auto|on|offServerkonsoleSchutzmodus: nur noch bekannte Spieler-IPs dürfen verbinden

Fehlersuche

„Der Lizenzschlüssel (prox_key) ist ungültig.“

Schlüssel im Panel kopieren und ohne Leerzeichen in die server.cfg setzen. Wurde er im Panel neu erzeugt, gilt der alte nicht mehr.

„Dieser Server ist im Prox-Panel gesperrt“ oder „abgelaufen“

Im Panel den Status prüfen oder das Paket verlängern. Prox versucht es alle 5 Minuten neu und verbindet sich danach von selbst.

Spieler hören nichts

  • Ist der Browser-Tab offen und steht oben „Verbunden“?
  • Im Tab unter „Verbindung“ steht, ob UDP oder TCP genutzt wird. Blockiert eine Firewall UDP, wechselt Prox automatisch auf TCP.
  • Chrome im Hintergrund: siehe Chrome-Tipp.
  • Ist der Spieler tot, gesperrt oder im Modus „Nur Funk“? /proxstatus zeigt es.

Handy oder Funk reagieren nicht

Die Ressource muss nach prox starten. Wurde prox neu gestartet, auch Handy und Funk einmal neu starten, damit sie die Exports neu laden.

Das Verbinden-Fenster kommt im Ladebildschirm

Config.Prompt.event auf das Event setzen, das dein Charakter-Menü nach dem Spawn auslöst, und delay erhöhen.