Configuration - SocketSVC Docs
SocketSVC Docs

Configuration

Server config fields, defaults, visible-player filtering and hot reload

Config file location

Server sideConfig file
Paper pluginplugins/SocketSVC/config.yml
Fabric/Quilt/NeoForge/Forge server modconfig/socketsvc-server.yml

The default config is written on first start. Both files have the same fields and can be copied between each other. Defaults come from config.yml and socketsvc-server.yml (they must match, which ServerModConfigTest checks); the only difference is that metrics currently exists only in the Paper plugin.

Fields

FieldDefaultBehaviour
port24455Port of the WebSocket listener, always a plain (non-TLS) local port; reload rebinds it in the background without restarting Minecraft
bind-address0.0.0.0Network interface the listener binds; 0.0.0.0 keeps direct/LAN access, use 127.0.0.1 when the reverse proxy runs on the same machine
public-url""WebSocket base URL sent to clients; no trailing /, query or /voice path (the client appends /voice?token=...&uuid=...)
public-hostlocalhostUsed only when public-url is blank, to build ws://<public-host>:<port>
hearing-range48.0Hearing distance in blocks within the same world; players in different worlds never hear each other
fade-start-distance0.0Distance where linear volume fade begins, silent at hearing-range; 0 fades over the whole range
spectator-interactionfalseWhether spectators can speak to non-spectators
visible-players-onlyfalseWhen true, listeners only receive voice from players they track and are allowed to see, including microphone audio relayed through spatial speakers; see Visible players only
soundboard-enabledtrueWhen false, the server drops all soundboard audio
server-list-adverttrueMarks this server's status ping so a player running the client mod sees a voice-chat badge next to it in the multiplayer server list, before joining; see Server list badge
addons.usesemptyAddons this server uses, offered to clients that have the mod; see Telling clients what you use. Server-side addon jars live in addons/ instead, see Server addons
addons.requiredemptyAddons clients install for themselves on connect, from their own index; see Installing it for them
addons.root-commands.*offGives each server addon a command of its own, like /cinema; see Root commands
require-client.*offRefuse players who are not running the client mod; see Requiring the client mod
voice-ranges.*offWhisper and shout — a quieter tier and a louder one on a key each; see Whisper and shout
range-overrides.*offPer-world and per-region hearing ranges, for when one number cannot describe every place on the server; see Per-world and per-region ranges
groups.*offVoice groups: named channels players join from the in-game menu. Disabled by default, and while disabled the capability is not even negotiated, so clients know to say so
metrics.enabledtruePaper plugin only: anonymous, aggregate usage metrics (server count, versions, platform), never player identities or voice data; set to false to opt out, takes effect on the next server start

Every field except metrics.enabled supports /ssvc-server reload; see Hot reload.

Field notes and invalid values

  • spectator-interaction: when false, spectators can still hear non-spectators and talk to other spectators; same-world and distance limits apply in either mode.
  • hearing-range: non-finite or non-positive values disable voice relay.
  • fade-start-distance: must be at least 0 and less than hearing-range. If an existing config lacks this field or the value is invalid, the legacy 70% start (hearing-range × 0.7) is kept, so upgrading does not change an existing fade curve. This is a SocketSVC-specific option, not a Simple Voice Chat config key.
  • port must be an integer from 1 to 65535; bind-address must not be blank.
  • public-url must be a ws:// or wss:// URL without user info, query or fragment; public-host must not contain /, @, ?, # or whitespace.
  • server-list-advert: advisory only. Nothing about joining, handshaking or talking depends on it, and a server that does not advertise simply shows no badge — the client never claims the opposite of what it found.
  • voice-ranges is validated on every reload whether or not a tier is switched on, the same as range-overrides below.
  • range-overrides is validated on every reload whether or not it is switched on, so a typo is refused by the reload that introduced it rather than the day somebody flips the switch.
  • When soundboard-enabled is false, the server still negotiates the soundboard protocol so clients cannot bypass the switch through the legacy microphone fallback; dedicated soundboard frames are dropped by the server instead. See Voice protocol.

Telling clients what you use

A server can name the addons it runs. Players with the client mod see them on their Addons tab under "This server uses", with an install button for anything they are missing.

plugins/SocketSVC/config.yml
addons:
  uses:
    - cinema
    - walkie-talkie

/ssvc-server reload applies a change without reconnecting anybody, and /ssvc-server status lists what is being advertised.

Ids only — and the wire format has nowhere to put anything else

You name an addon; the client resolves that name against the index it configured itself and downloads from there. A server handing a client a jar location would be remote code execution with a progress bar, so the message is a space-separated list of ids and an id cannot contain / or :.

An id you ask for that a player's index does not offer shows on their screen as Not in your index, rather than as a button that cannot work. Where to get it is not yours to say.

Installing it for them

uses is an offer: a row on the tab with an install button. required is the same offer with the button pressed for the player.

plugins/SocketSVC/config.yml
addons:
  required:
    - cinema

A client that connects without one of these downloads it from its own index, switches it on, and says so in chat; one that has an older build than the index offers is updated the same way — no tab to find. One already installed but switched off is switched on again, and that is said too. Anything listed here is advertised as used as well, so a client too old to understand the second line still sees the offer.

What it does not change: the source is still the index the player configured, an id their index does not carry is reported in chat rather than fetched from anywhere else, and a player can turn the automatic install off on their Addons tab — in which case chat tells them what you require and leaves the install to them. A mod still cannot load until they restart.

Nothing here refuses anybody

A player who ends up with none of it plays and talks normally — the only thing they miss is whatever those addons do. There is no switch that kicks a player for lacking an addon: refusing players is what require-client is for, and it is about the voice mod itself.

An addon can be switched on as soon as it downloads. A mod cannot load until that player restarts their game, so the session that offered it goes without — and their screen says so rather than implying otherwise.

An id that is not a usable addon id is refused by the reload that introduced it, with the running settings left untouched, rather than being advertised to clients that could never resolve it.

Server addons

Some features ship as server addons: plain jars you drop in plugins/SocketSVC/addons/ (or config/socketsvc/addons/ for the server mods). One jar works on Paper, Fabric, NeoForge and Forge — a server addon never touches a Bukkit or Minecraft type, so there is nothing to build four times.

plugins/SocketSVC/
  config.yml
  addons/
    socketsvc-addon-cinema-server-0.2.0.jar
    cinema.yml

Each addon reads its own <id>.yml beside its jar, rather than a block in config.yml: an addon you delete should take its settings with it, and config.yml should not describe things that are no longer installed.

They load at startup and again on /ssvc-server reload, which re-reads the folder — so adding or removing one needs no restart. They are deliberately not hot-swapped mid-session the way client addons are: a server addon holds state other people are connected to.

/ssvc-server addon <id> [arguments...]

reaches an addon's own commands, behind socketsvc.admin.addon (defaults to op). /ssvc-server status lists what loaded, and names anything that did not along with why.

Root commands

Turned on, each addon that takes commands also gets a command of its own, so /cinema play lobby does what /ssvc-server addon cinema play lobby does:

addons:
  root-commands:
    enabled: true
    names:
      cinema: film      # call it /film instead
      walkie-talkie: '' # or give one none

Off by default. A command name like /cinema is one every other plugin and mod on the server could also want, so claiming it is your decision rather than an addon's.

  • Each addon's command is named after its id unless names says otherwise.
  • A name something else already has is refused, not taken over. The server log says which addon missed out and who has the name; rename it under names. The long form always works either way.
  • It is the same command behind a shorter name: the same arguments, the same tab completion, the same socketsvc.admin.addon permission. Players without that permission do not see it at all.
  • Changes apply on /ssvc-server reload, with no restart, and players' tab lists update straight away. On the server mods a root command that is turned off stays in the game's command list but is hidden from everyone and cannot be run — the game has no way to remove one while it runs.

A broken jar costs that addon and nothing else

An addon that fails to load is reported and skipped; the server still starts, and the other addons still load. Nothing you drop in that folder can stop players getting in.

The cinema is the worked example: its server jar defines screens and drives their playheads, while SocketSVC itself carries only the timecode sync.

Microphone tap

Lets server plugins receive players' voice as it arrives — a bridge to another voice mod, a Discord relay, recording, transcription or moderation replay. The API is documented under Microphone tap. The Cross System Bridge needs it to carry SocketSVC players' voices to Simple Voice Chat.

plugins/SocketSVC/config.yml
microphone-tap:
  enabled: false

Off by default, and this default is about your players

Every other switch in this file decides what SocketSVC does with audio. This one decides whether audio leaves SocketSVC at all, for code this project did not write. Turn it on because you installed something that needs it and you know what that something does with what it hears.

While it is off, a plugin asking to subscribe is refused with a reason rather than accepted and given silence, so an addon author finds out immediately that the switch is the problem.

Who can be heard

socketsvc.bridge decides whose audio may leave, player by player. It defaults to true — the switch above is what keeps the feature off, so a node defaulting to false would leave you turning this on and still hearing nothing. Take it away from anybody whose voice should never leave SocketSVC. It is checked per frame against an answer refreshed every second, so revoking it stops their audio within a second rather than at their next reconnect.

A tap hears exactly what the room hears: frames reach it only after the mute check and after socketsvc.speak, so a muted or silenced player is silent to a tap too. Soundboard and instrument audio are not tapped.

Seeing what is listening

Every plugin that subscribes is named in your server log the first time it does. That log line is the only way to see what is listening without reading plugin source, so read it after turning this on.

/ssvc-server reload applies a change. Turning it back off closes every live subscription rather than leaving one running against a decision you have just made; changing the port does not end a subscription, so a rebind cannot silently break a plugin that was working.

Requiring the client mod

A server can refuse players who are not running SocketSVC, with a message pointing them at the download.

plugins/SocketSVC/config.yml
require-client:
  enabled: false
  grace-seconds: 10
  message: "This server requires the SocketSVC voice chat mod.\nDownload it at https://modrinth.com/mod/socketsvc"

message is the disconnect reason. It accepts MiniMessage and & colour codes, and \n starts a new line. Every other message the server sends is in the messages file.

Off by default, and this default matters more than the others

Every other switch in this file degrades a feature when it is wrong. This one closes the door on people who were already playing on your server — upgrade the jar, restart, and your regulars cannot get in. Nothing is ever refused unless you turn it on yourself, and a server with it off does not delay a single join.

How a client is detected

By the plugin channel the handshake travels on. A client that registers it has the mod — the same question the server already asks before it sends a handshake at all.

It is deliberately not "do they have a voice connection". That also depends on your voice port being reachable from where the player is, so using it would kick people because your tunnel was down, which is the worst thing this feature could do.

Nobody is refused for not having answered yet

There are three states, not two: has the mod, does not have it, and has not said yet. Channel registration lands shortly after somebody joins rather than at the instant they do, so for a moment the honest answer is that nobody knows — and grace-seconds is how long that moment is allowed to last. A player is only refused once it has passed with nothing registered.

The default of 10 seconds is mostly slack: registration normally arrives within a second. The range is 1–120.

Exemption

socketsvc.require.exempt (default op) is never refused, so turning the requirement on cannot lock out the person who turned it on — and a staff member on a laptop without the mod can still get in and turn it off again.

Every refusal is logged with the player's name and the reason. "I cannot join your server" is a report you have to be able to explain, and a kick with no trace of why is how this ends up blamed on the voice port.

Geyser and Floodgate players can never pass this check

Bedrock players cannot install the mod (Bedrock support). Turning this on with Geyser installed is telling every Bedrock player to leave. That may be exactly what you want; it should not be a surprise.

For addons

SocketSvcApi and SocketSvcModApi expose the same registry from version 3:

VoiceClientState state = api.voiceClientState(player); // PRESENT, ABSENT or UNKNOWN
boolean hasMod = api.hasVoiceClient(player);           // PRESENT only
boolean enforced = api.requiresVoiceClient();

An addon that acts on ABSENT should decide what it does about UNKNOWN rather than treating it as a no — hasVoiceClient collapses both to false, which is convenient for showing an icon and wrong for deciding whether to refuse somebody.

/ssvc-server status reports whether the requirement is on and how many connected players are known to have the mod.

Whisper and shout

A quieter tier and a louder one, each on a key the player holds. Both are off by default — they change how far every player on the server can be heard, which is a decision about how a server plays rather than something to hand out unasked.

plugins/SocketSVC/config.yml
voice-ranges:
  whisper:
    enabled: true
    hearing-range: 8.0
  shout:
    enabled: true
    hearing-range: 96.0

Each tier is switchable on its own — a server that wants whisper but not shout is an ordinary thing to want — and /ssvc-server reload applies a change immediately, without reconnecting anybody.

A tier scales the range, it does not replace it

Each tier is written as a distance because that is what an operator can picture, and applied as a ratio to whatever range is in force where the speaker is standing.

With hearing-range: 48 and a shout of 96, a shout carries twice as far as normal. Inside a range-overrides arena whose range is 16, it therefore carries 32 — not 96. Replacing instead of scaling would mean every quiet place on the server had a shout that ignored it, which would make per-world ranges meaningless to anybody holding a key.

A range of 0 stays silent whatever tier is used: silence scaled by anything is still silence.

A tier changes distance and nothing else

A shout does not cross worlds, pass the visible-players-only rule, or reach somebody who has deafened themselves. A whisper is not a private channel — it is a smaller radius, and anybody standing inside it hears you. Voice groups are what a real private channel is for.

Soundboard clips and plugin speakers are never whispered or shouted: a tier is how loudly somebody is talking, and a clip is not speech.

You can see who is whispering and who is shouting

The voice icon beside a player's nameplate is drawn smaller for a whisper and larger for a shout, so the tier is readable at a glance without a second icon beside it to compare against. Your own icon on the HUD scales by the same amounts, so what you see on yourself is what everybody else sees on you.

The tier rides the player roster alongside the deafen state, so it reaches every client the same way. A tier the server has switched off is never published: a client one reload ahead of the operator would otherwise draw somebody as whispering while the relay routes them at ordinary range.

Keys, and what a client does when a tier is off

Both keybinds ship unbound. Both tiers are off by default server-side, so a server that switches one on will tell its players which key to bind; claiming two more default keys for a feature most servers never enable is a cost paid by everybody for the benefit of a few. Players bind them under Controls → SocketSVC. Holding both keys at once whispers — it is the quieter of the two, and the one whose point is not being overheard.

The server tells each client which tiers exist here, so a key for a tier that is off does nothing and says so, once, in chat. Without that the player's own HUD would say "Whisper" while everybody heard them at ordinary volume — a silent disagreement between two machines that both think they are right.

Older clients are unaffected

A client that predates whisper and shout never sends a tier and is heard normally. A client that sends a tier the server has since switched off is heard normally too, rather than being silenced or disconnected — a client whose idea of the config is one reload out of date should not lose its voice over it. See Voice protocol.

/ssvc-server status reports each tier, its configured distance and the ratio it works out to.

Per-world and per-region ranges

hearing-range is one number for the whole server, which cannot describe a network with a lobby, a survival world and a minigame arena on it. range-overrides names the exceptions; anything it does not name keeps the global range.

plugins/SocketSVC/config.yml
range-overrides:
  enabled: true

  worlds:
    lobby:
      hearing-range: 0          # no voice in the lobby at all
    arena:
      hearing-range: 16.0
      fade-start-distance: 8.0

  regions:
    - name: library
      world: world
      min: [100, 60, 100]
      max: [140, 80, 140]
      hearing-range: 8.0

On the server mods, worlds are named by dimension ID (minecraft:overworld); on Paper they are Bukkit world names. Both are the names that platform already reports everywhere else.

The switch is a switch, not a delete

enabled: false restores the global range everywhere and leaves everything below it intact, so an operator who turns overrides on for an event can turn them off again without retyping any of it. Both states apply through /ssvc-server reload without disconnecting anybody.

The block is also parsed and validated while it is off. A malformed entry is refused by the reload that introduced it — with the running settings left untouched, as with any rejected reload — rather than lying in wait until the switch is next flipped.

A range of 0 means no voice, in both directions

Nobody in that place is heard outside it, and nobody outside is heard in it.

That follows from the rule for a speaker and a listener who resolve different ranges: the smaller of the two applies to both. Taking only the speaker's range would let somebody standing in a silenced booth listen in on the room outside; taking only the listener's would let them be heard from it. Either is a hole in the thing the operator set out to do.

Voice groups are not a place

A voice group already ignores distance, worlds and visibility, and it ignores range overrides for the same reason: it is a channel, not a location. Two people in the same group hear each other in a silenced world. If you need a place nobody can talk from at all, take socketsvc.speak away there, or switch groups off.

Regions

A region is an axis-aligned box in one world. min and max are two opposite corners written as [x, y, z], both inclusive, and it does not matter which corner is which.

A region is checked before the world it sits in, so a region can be quieter or louder than its surroundings. Where two regions overlap, the first one listed wins — file order is a tie-break an operator can see and reorder, which smallest-box-wins would not be.

Omitting hearing-range inherits it: a region from its world, a world from the global setting. So a region can narrow the fade alone. fade-start-distance inherits too, but only while it still fits — it is an absolute distance, so a global fade of 33 blocks means nothing inside a 16-block arena and falls back to 70% of that range instead, the same curve the global default uses.

Regions are defined here, not read from WorldGuard

WorldGuard is Bukkit-only, and the Fabric/NeoForge/Forge server mods are promised the same features as the Paper plugin — a region system that worked on one of the four would break that. A box in the config behaves identically on all of them and needs no third-party API to follow. Reading real WorldGuard regions is a candidate for a separate addon, for servers that already draw their regions there.

Checking it

/ssvc-server status lists every configured override and says whether they are being applied. /ssvc-server test <player> adds a line naming the world or region that player is standing in and the range in force there — "nobody can hear me" and "I am standing in a region with its own range" look identical from the outside, and that is the command that tells them apart.

Plugin speakers are unaffected

A speaker created through the spatial audio API carries the range its own SpatialSettings declares. An override changes where players are heard, and does not silently retune a plugin's speakers underneath it.

Default config file

plugins/SocketSVC/config.yml
port: 24455
bind-address: "0.0.0.0"
public-url: ""
public-host: localhost
hearing-range: 48.0
fade-start-distance: 0.0
spectator-interaction: false
visible-players-only: false
soundboard-enabled: true
server-list-advert: true

groups:
  enabled: false
  max-groups: 32
  max-members: 16
  allow-player-created: true
  allow-passwords: true
  allow-persistent: false
  default-type: normal

microphone-tap:
  enabled: false

metrics:
  enabled: true

The server mod's config/socketsvc-server.yml has the same content without the metrics block.

Server list badge

With server-list-advert on (the default), a player running the SocketSVC client mod sees a microphone badge beside this server's row in their multiplayer server list, in the margin to the left of it — so they know voice chat works here without joining first.

It rides on the status ping the list already sends. The server appends an empty component to its MOTD carrying nothing but a style insertion, which is the one style field with no rendering of its own: it is the text a shift-click would put in the chat box, and the server list offers no such action. A vanilla client therefore renders exactly the MOTD it would have rendered, at the same width and with the same line wrapping. No extra connection, no extra port, no new protocol.

Turn it off by setting server-list-advert: false and running /ssvc-server reload; it applies to the next ping. Players can also hide the badge on their side under Advanced → Interface → Server list voice badge.

It can be lost, and that is fine

An MOTD plugin that rebuilds the description from a plain string — common with packet-library MOTD plugins — drops the sibling, so the badge does not appear. Nothing else changes. SocketSVC appends at the lowest-running event priority so a plugin that merely sets the MOTD keeps it.

On a Velocity or BungeeCord network the badge has to come from the relay plugin instead: players ping the proxy, and each backend's own voice listener is internal and never answers a server-list ping. A backend's server-list-advert does nothing there. See Proxy configuration.

Public URL

When public-url is blank, ws://<public-host>:<port> is built automatically, which suits LAN or direct connections without TLS. For a public server, set public-url to the wss:// hostname of your reverse proxy or Cloudflare Tunnel (for example wss://mydomain.com); the proxy terminates TLS and forwards to the local port. See Public deployment and WSS for details.

With a Velocity/BungeeCord relay, bind-address/port only need to be reachable by the relay, and public-host/public-url must point at the relay's public address; see Proxy configuration.

Visible players only

When visible-players-only is true, a player's voice only reaches listeners that are tracking the speaker's entity and allowed to see it. Microphone audio relayed through spatial speakers is filtered the same way. The state is refreshed every tick.

Server sideHow visibility is decided
PaperEntity tracking updated by the server every tick, plus Bukkit canSee state (hidePlayer/hideEntity)
Server modThere is no vanilla hidden-player API, so it checks same dimension and within the player entity tracking distance (min(view-distance, player tracking range))
  • Neither is affected by camera direction, walls or client render culling.
  • Hiding plugins that only intercept packets without updating Bukkit visibility/tracking state cannot be detected by this setting.
  • Standalone audio sources (server-played PCM/WAV and so on) are unaffected.
  • A missing or false value keeps the previous behaviour.

Changing settings by command

/ssvc-server settings lists the everyday settings and their values. Click a name to start typing /ssvc-server settings set <name> <value>, which changes one: on/off for a switch, a number of blocks for a distance. Names and config keys both work.

NameConfig key
rangehearing-range
fadefade-start-distance
spectatorsspectator-interaction
visible-onlyvisible-players-only
soundboardsoundboard-enabled
groupsgroups.enabled
whisper, whisper-rangevoice-ranges.whisper.enabled, .hearing-range
shout, shout-rangevoice-ranges.shout.enabled, .hearing-range
require-clientrequire-client.enabled
root-commandsaddons.root-commands.enabled
  • Saving is a reload. The value is written into the config file and /ssvc-server reload runs, so a change is applied exactly as a hand edit would be. The edited file is validated first: a value the reload would refuse is refused without the file being touched.
  • The file keeps its comments. Only the line holding the value is rewritten; everything else in the file, comments included, stays as it was. A key missing from an older file is added under its section.
  • A fade at or past the hearing range is refused, rather than being quietly ignored as it would be in the file.
  • What is not here. The port, bind address and public URLs are left out - a slip there disconnects everybody - and so are per-world ranges and regions, messages, and every other text setting. Edit those in the file.
  • It needs socketsvc.admin, like every /ssvc-server command.

Hot reload

After editing the config, run /ssvc-server reload (the / can be omitted in the console). It requires the socketsvc.admin permission; see Permissions. This is SocketSVC's own config hot reload; Bukkit /reload is not needed.

  • Routing settings: range, fade, spectator rules, visible-players-only, soundboard-enabled and the groups block apply immediately and clear stale routed audio that has not been sent yet; voice connections stay up. Turning groups.enabled off also disbands every live group, and the groups capability itself is only picked up by a client when it next reconnects.
  • Listener address: a port/bind address change stops the old listener and starts a new one in the background, briefly interrupting voice without affecting the Minecraft connection. Existing speaker API objects, IDs and playback sources are kept, and playback time of audio sources keeps advancing.
  • External URL: a public-url/public-host change closes existing voice connections so clients automatically fetch a new token and connect to the new URL. Adjust external proxies and firewalls separately.
  • Errors: invalid YAML or network settings are rejected. If the new listener is not ready within five seconds, the failed listener is cleaned up and the old address is rebound, keeping the previous settings. If the old address cannot be restored either, the error is reported explicitly and the voice plugin is disabled; details are in the server log.
  • Concurrency and status: only one reload is accepted at a time; /ssvc-server status shows the actual listener address and reload state. The running settings are only updated on success, a failed reload never overwrites the file on disk, and you can reload again after fixing it.

Speakers owned by other plugins

Speakers managed by other plugins through the Spatial audio API are still updated by their owner through the API; they are not part of this config file.

Updates

SocketSVC checks whether a newer build exists and tells administrators; it never updates the server by itself. Installing is always /ssvc-server update confirm, gated on socketsvc.admin.update (which falls back to operators when no permission plugin is installed).

updates:
  enabled: true        # check and report; never installs on its own
  channel: release     # release, dev, or a branch channel the update service offers
  endpoint: ''         # blank uses the deploy SocketSVC ships with
  notify-admins: true  # tell holders of socketsvc.admin.update when they join
CommandWhat it does
/ssvc-server updateChecks the channel and prints what would be installed, how big it is and when it applies
/ssvc-server update confirmDownloads, verifies the SHA-256 and stages it
/ssvc-server update listEvery build on the channel, newest first, marking the installed one

The Paper plugin puts the verified jar in Bukkit's update folder under the running plugin's file name, so the server replaces it on the next start. The Fabric/NeoForge/Forge server mod stages it beside its config and swaps it in as the server shuts down, logging to updates/apply.log. Update settings are read at start; /ssvc-server reload does not re-read them.