This plugin implements the backend compatibility needed to host the Simple Voice Chat mod on a PumpkinMC server. It allows players connecting with modern Minecraft clients (Fabric, Forge, NeoForge) to use proximity voice chat and dynamically created voice groups.
- Proximity Chat: Accurately simulates dimensional audio using 3D vector coordinates sent directly to your game client.
- Group Channels: Full support for the GUI group interfaces (creating groups, joining password-locked groups, leaving groups, managing volume).
- Dynamic Audio Categories: Create custom audio categories via configuration to differentiate audio streams (e.g. Radio, Global Broadcast) with custom names and icons.
- Packet Rate Limiting: Built-in protection against network flooding/DoS using a high-performance token-bucket rate limiter.
- Permissions Support: Fully respects the native PumpkinMC permission node trees.
- Optimized Transport: Connects entirely over UDP with lightweight
AES-128-GCMencryption for optimal performance.
- Language: Rust
- Framework:
pumpkin-api(PumpkinMC Plugin SDK) - Async Runtime:
tokio(Powers the real-time UDP connection network) - Cryptography:
aes-gcmsuite for packet serialization matching JVM mod signatures - Configuration:
serde/toml
Before setting up the plugin, make sure you have the following installed on your machine:
- The Rust Toolchain (
cargo,rustc). - A built and running instance of the PumpkinMC Server.
- A Minecraft Client with the Simple Voice Chat Mod installed.
We provide pre-built WASM components under the Releases tab.
- Download the latest
pumpkin_voice.wasmfrom the Releases page. - Place the downloaded
.wasmfile directly into your PumpkinMC server'splugins/directory.
If you prefer to compile the plugin yourself or are contributing to development:
-
Clone the Repository
git clone https://github.com/hmdnnrmn/PumpkinVoice.git cd PumpkinVoice -
Install the WASM Target Ensure you have the WebAssembly target installed:
rustup target add wasm32-wasip2
-
Build the Plugin Compile the plugin to a WASM component:
cargo build --release --target wasm32-wasip2
-
Deploy the Executable Once compiled, move the output WASM file into your server's plugin pool:
cp target/wasm32-wasip2/release/pumpkin_voice.wasm /path/to/pumpkin/plugins/
The first time you boot the server, the plugin will construct a default configuration file at plugins/pumpkin_voice/config.toml.
By default, the plugin will span out a UDP listener concurrently running on port 24454.
Connect via your Minecraft client. Look at the bottom left of your screen, you should see no "Unplugged" symbol. Press V to open up the Simple Voice Chat UI to guarantee that the UI says "Voice Chat Connected".
PumpkinMC directly delegates commands to the plugin via the Brigadier argument mapping interface. Use the following commands in-game:
| Command | Description | Permission Node |
|---|---|---|
/voicechat join <group_name> <password> |
Looks up a global group and assigns you to it. Supports passwords. | pumpkin_voice:groups |
/voicechat leave |
Disconnects you from your active group bounds. | pumpkin_voice:groups |
/voicechat invite <target> |
Sends a chat message to a player with a one-click join link. | pumpkin_voice:groups |
This codebase acts as an extremely rapid buffer bridging Minecraft Plugin Messages (TCP) and the secure stream bounds (UDP/Datagram).
src/
├── commands/ # Brigadier command interfaces (/voicechat branch)
├── config/ # TOML layout and initial injection maps
├── handlers/ # Event interceptors (Player Join/Leave, GUI Custom Payloads)
├── net/ # Networking logic
│ ├── udp/ # UDP socket, cryptography, and packet handling
│ ├── custom_payloads.rs # TCP Custom payload definitions
│ └── voice_packets.rs # Audio specific byte arrays mimicking `FriendlyByteBuf`
├── state/ # Shared asynchronous connection cache logic (Groups, Players)
├── util/ # Byte buffer extensions
└── lib.rs # Plugin Entrypoint. Registers macro hooks and routes exports
- Player Connection:
- Trigger:
PlayerJoinEventinsidelib.rs. - Action: A new AES secret is generated in
state.rs, embedded via aSecretPacket, and pushed directly over custom payloads via TCP.
- Trigger:
- UDP Handshake Authentication:
- Trigger: Client triggers a
AuthenticatePackettoudp_server.rs:24454. - Action: Server validates the UDP source against the expected
Secret. Modifiessocket_addrproperties.
- Trigger: Client triggers a
- Continuous Audio Delivery:
- Trigger: Player pushes to talk. Client issues
MicPacketencoded datagrams. - Action:
udp_server.rsassesses constraints (distance, group ID). If condition blocks pass, routes viaPlayerSoundPacketorGroupSoundPacketdirectly. Audio bleeding between different worlds is prevented via strictArc::ptr_eqmatching against the active game universe.
- Trigger: Player pushes to talk. Client issues
The plugin registers native permission nodes via pumpkin_util::permission::Permission. Adjust these directly inside your primary Pumpkin engine deployment!
pumpkin_voice:command.voicechat: Required to view the commands layout inside chat.pumpkin_voice:speak: Prevents sending encrypted UDPMicPacketsoutbound.pumpkin_voice:listen: Prevents receiving encryptedPlayerSoundPacketsinside loops.pumpkin_voice:groups: Enables UI access to channels.
As this is an ongoing backend port of the Voice Chat mod to the rapid PumpkinMC framework, the following advanced features are intentionally skipped for the current minimum viable configuration:
- Spectator Possession & Camera Broadcasting: Audio coordinates routed from entities a spectator actively possesses are currently unmapped.
- Server Audio Recording API: Hooks and custom API interceptors for third-party Pumpkin scripts to record audio natively are unavailable.
- Plugin API / Developer Events: Intercepting granular
VoicechatServerApievents directly like Forge/Fabric is non-existent. - Microphone Loopback/Testing UDP Loops: Emitting audio back to the local client exclusively for mic testing natively is untracked.
Here is a breakdown of the standard config.toml structure dynamically dropped upon deployment:
| Variable | Description | Default |
|---|---|---|
port |
The UDP Binding port. -1 aligns directly to TCP game port. |
24454 |
bind_address |
String address the UDP socket clamps to. | "" (0.0.0.0) |
max_voice_distance |
Range cap for dimensional fading audios. | 48.0 |
whisper_distance |
Range cap specifically for whispering clients. | 24.0 |
codec |
Opus codec compression parameter strings. | VOIP |
keep_alive |
Millisecond trigger interval looping connection verifications. | 1000 |
enable_groups |
Allow or reject GUI voicechat:create_group payloads. |
true |
force_voice_chat |
If true, non-modded clients are immediately dropped using a kick constraint. |
false |
max_packets_per_second |
Maximum UDP packets allowed per player per second before throttling. | 500 |
allow_pings |
Whether to respond to UDP ping packets from clients. | true |
broadcast_range |
Maximum range for audio broadcast. -1 uses max voice distance. |
-1.0 |
You can define custom categories in the config.toml:
[[categories]]
id = "radio"
name = "Radio Team"
description = "Global broadcast"Error: Connecting prints "Voice Chat not found!" or times out aggressively. Solution:
- Determine if the UDP port
24454is exposed in your cloud firewall (e.g., UFW/AWS/OCI panels). UDP acts alongside TCP constraints but requires dedicated protocol openings. - Review the logs to ensure the
tokioruntime initialized successfully in the background. - Check for
Rate limiting player ...warnings in the server console; if seen, increasemax_packets_per_secondinconfig.toml.
Error: User selects a correct password but receives "Invalid Password."
Solution: Ensure the client and server code are mirrored correctly. Abandoned GUI parameters occasionally drop payload arrays if the UI bugs out locally. Validate through the standard /voicechat join commands as a bypass mechanic.
Error: Failed to create config folder ... (os error 44) or Operation not permitted.
Solution: This typically indicates a permission or preopen mismatch in the WASI environment. Ensure the plugin has fs.read and fs.write permissions in its metadata (default in recent versions). The plugin now uses absolute-style relative paths to ensure compatibility with Pumpkin's virtual filesystem.