Sounds
Gate provides a dedicated sound
package for playing and controlling sounds for Minecraft players. This API allows you to create immersive audio experiences in your proxy extensions.
Version Requirements
- Minimum Minecraft Version: 1.19.3
- UI Sound Source: Requires 1.21.5+
Players on older versions will receive an error if they try to use sound features.
Package Import
import (
"go.minekube.com/gate/pkg/edition/java/sound"
)
Quick Start
Playing Sounds
The simplest way to play a sound:
// Create a sound
snd := sound.NewSound("entity.player.levelup", sound.SourcePlayer)
// Play it for the player (emitted from the player's location)
err := sound.Play(player, snd, player)
Stopping Sounds
// Stop all sounds
err := sound.StopAll(player)
// Stop sounds from a specific source
err := sound.StopSource(player, sound.SourceMusic)
// Stop a specific sound
err := sound.StopSound(player, "entity.cat.ambient")
Sound Configuration
The Sound
struct allows you to customize playback:
snd := sound.NewSound("block.note_block.pling", sound.SourceBlock).
WithVolume(2.0). // Louder (also increases range)
WithPitch(1.5). // Higher pitch
WithSeed(12345) // Specific random seed
Sound Properties
- Name: The sound identifier (e.g.,
"entity.experience_orb.pickup"
) - Source: The sound category/source (affects volume controls)
- Volume:
0.0
to∞
(values > 1.0 increase audible range) - Pitch:
0.5
to2.0
(lower = deeper, higher = higher pitch) - Seed: Optional random seed for sound variation
Sound Sources
Sound sources determine which volume slider in the client controls the sound:
Description | Constant |
---|---|
Master volume | sound.SourceMaster |
Background music | sound.SourceMusic |
Jukebox/Music discs | sound.SourceRecord |
Rain, thunder | sound.SourceWeather |
Block sounds | sound.SourceBlock |
Hostile mobs | sound.SourceHostile |
Neutral mobs | sound.SourceNeutral |
Player actions | sound.SourcePlayer |
Ambient sounds | sound.SourceAmbient |
Voice chat | sound.SourceVoice |
Interface sounds | sound.SourceUI ⚠️ 1.21.5+ |
Parsing Sound Sources
// From string
source, err := sound.ParseSource("music")
if err != nil {
// Invalid source name
}
// To string
name := source.String() // "music"
Playing Sounds from Different Emitters
Sounds can be emitted from different players on the same server:
targetPlayer := ... // player who will hear the sound
emitterPlayer := ... // player from whose location the sound plays
snd := sound.NewSound("entity.villager.yes", sound.SourceNeutral)
// Play sound at emitter's location for target player
err := sound.Play(targetPlayer, snd, emitterPlayer)
Same Server Required
Both the target player and emitter must be connected to the same backend server. Otherwise, ErrDifferentServers
will be returned.
Advanced Stop Options
The sound.Stop()
function provides flexible filtering:
// Stop specific sound from specific source
source := sound.SourceAmbient
soundName := "entity.cat.ambient"
err := sound.Stop(player, &source, &soundName)
// Stop all sounds from a source (soundName = nil)
err := sound.Stop(player, &source, nil)
// Stop a sound from all sources (source = nil)
err := sound.Stop(player, nil, &soundName)
// Stop everything (both nil)
err := sound.Stop(player, nil, nil)
Complete Example: Event-Based Sounds
Play a sound when a player connects to a server:
package main
import (
"context"
"go.minekube.com/gate/pkg/edition/java/proxy"
"go.minekube.com/gate/pkg/edition/java/sound"
"go.minekube.com/gate/pkg/gate"
)
func main() {
proxy.Plugins = append(proxy.Plugins, proxy.Plugin{
Name: "SoundExample",
Init: func(ctx context.Context, p *proxy.Proxy) error {
return registerSoundExample(p)
},
})
gate.Execute()
}
func registerSoundExample(p *proxy.Proxy) error {
// Subscribe to server connected event
p.Event().Subscribe(&proxy.ServerPostConnectEvent{}, 0, func(e *proxy.ServerPostConnectEvent) {
player := e.Player()
// Play a level-up sound when player connects to a server
levelUpSound := sound.NewSound("entity.player.levelup", sound.SourcePlayer).
WithVolume(1.0).
WithPitch(1.0)
_ = sound.Play(player, levelUpSound, player)
})
return nil
}
Complete Example: Sound Commands
Create commands to test the sound API:
package main
import (
"context"
"fmt"
"strconv"
"go.minekube.com/brigodier"
. "go.minekube.com/common/minecraft/color"
. "go.minekube.com/common/minecraft/component"
"go.minekube.com/gate/pkg/command"
"go.minekube.com/gate/pkg/edition/java/proxy"
"go.minekube.com/gate/pkg/edition/java/sound"
"go.minekube.com/gate/pkg/gate"
)
func main() {
proxy.Plugins = append(proxy.Plugins, proxy.Plugin{
Name: "SoundCommandExample",
Init: func(ctx context.Context, p *proxy.Proxy) error {
return registerSoundCommands(p)
},
})
gate.Execute()
}
func registerSoundCommands(p *proxy.Proxy) error {
// Register /playsound command
p.Command().Register(
brigodier.Literal("playsound").
Then(brigodier.Argument("sound", brigodier.String).
Then(brigodier.Argument("source", brigodier.String).
Then(brigodier.Argument("volume", brigodier.String).
Then(brigodier.Argument("pitch", brigodier.String).
Executes(command.Command(func(c *command.Context) error {
player, ok := c.Source.(proxy.Player)
if !ok {
return c.Source.SendMessage(&Text{
S: Style{Color: Red},
Content: "Only players can use this command!",
})
}
soundName := c.String("sound")
source, err := sound.ParseSource(c.String("source"))
if err != nil {
return c.Source.SendMessage(&Text{
S: Style{Color: Red},
Content: err.Error(),
})
}
volume, err := strconv.ParseFloat(c.String("volume"), 32)
if err != nil {
return c.Source.SendMessage(&Text{
S: Style{Color: Red},
Content: "Invalid volume",
})
}
pitch, err := strconv.ParseFloat(c.String("pitch"), 32)
if err != nil {
return c.Source.SendMessage(&Text{
S: Style{Color: Red},
Content: "Invalid pitch",
})
}
// Create and play the sound
snd := sound.NewSound(soundName, source).
WithVolume(float32(volume)).
WithPitch(float32(pitch))
if err := sound.Play(player, snd, player); err != nil {
return c.Source.SendMessage(&Text{
S: Style{Color: Red},
Content: fmt.Sprintf("Error: %v", err),
})
}
return c.Source.SendMessage(&Text{
S: Style{Color: Green},
Content: fmt.Sprintf("Playing %s at %.1f volume, %.1f pitch",
soundName, volume, pitch),
})
})),
),
),
),
),
)
// Register /stopsound command
p.Command().Register(
brigodier.Literal("stopsound").
Executes(command.Command(func(c *command.Context) error {
player, ok := c.Source.(proxy.Player)
if !ok {
return c.Source.SendMessage(&Text{
S: Style{Color: Red},
Content: "Only players can use this command!",
})
}
if err := sound.StopAll(player); err != nil {
return c.Source.SendMessage(&Text{
S: Style{Color: Red},
Content: fmt.Sprintf("Error: %v", err),
})
}
return c.Source.SendMessage(&Text{
S: Style{Color: Green},
Content: "Stopped all sounds",
})
})),
)
return nil
}
Common Sound Names
UI & Feedback Sounds
entity.experience_orb.pickup
- XP orb pickup soundentity.player.levelup
- Level up fanfareui.button.click
- Button clickentity.villager.yes
/entity.villager.no
- Villager sounds
Note Block Sounds
block.note_block.bell
- Bellblock.note_block.pling
- Pling (high pitch)block.note_block.harp
- Harpblock.note_block.bass
- Bassblock.note_block.guitar
- Guitar
Entity Sounds
entity.enderman.teleport
- Teleport effectentity.arrow.hit_player
- Arrow hitentity.item.pickup
- Item pickup
Find More Sounds
For a complete list of available sounds, see the Minecraft Wiki - Sound Events.
Error Handling
The sound API returns specific errors for better handling:
err := sound.Play(player, snd, emitter)
if err != nil {
switch {
case errors.Is(err, sound.ErrUnsupportedClientProtocol):
// Player is on a version < 1.19.3
case errors.Is(err, sound.ErrUISourceUnsupported):
// Player tried to use UI source on version < 1.21.5
case errors.Is(err, sound.ErrNotConnected):
// Player is not connected to a server
case errors.Is(err, sound.ErrDifferentServers):
// Emitter and target are on different servers
}
}
Known Minecraft Bugs
Minecraft Limitations
- MC-146721: Stereo sounds are always played globally in 1.14+ (not positional)
- MC-138832: Volume and pitch are ignored in Minecraft 1.14 to 1.16.5
- Invalid sound names will silently fail (no error, but no sound plays)
API Reference
Functions
sound.Play(player, sound, emitter) error
Plays a sound at an entity's location.
Parameters:
player
- The player who will hear the soundsound
- The sound configurationemitter
- The player from whose location the sound plays
Returns: Error if version incompatible or players not on same server
sound.Stop(player, source, soundName) error
Stops sounds based on criteria.
Parameters:
player
- The player for whom to stop soundssource
- Sound source filter (nil = any)soundName
- Sound name filter (nil = any)
Returns: Error if version incompatible
Helper Functions
sound.StopAll(player) error
- Stop all soundssound.StopSource(player, source) error
- Stop all sounds from a sourcesound.StopSound(player, name) error
- Stop a specific sound
See Also
- Events Documentation - Handle player events
- Commands Documentation - Create custom commands
- Cookie Package - Similar package pattern
- Boss Bar Package - Similar package pattern