Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Level sounds

Implement play_level_sound_at_position or play_level_sound_at_entity to edit or cancel a level sound before it is broadcast (server) or played (client). Match the hook's HostSide to distinguish the requests; the event's sound, source, volume and pitch describe that side's request, and original volume and pitch remain available after edits. Returning Flow::Cancel suppresses that request. A server cancellation sends no packet, so there is no client request.

Incoming sound packets, including /playsound, ask the client level hooks. An entity-sound packet stays bound to its emitter. UI clicks, engine-local sounds and ClientHost::play_local_sound do not ask these level hooks; the sound engine's play_sound hook remains a separate, later interception point.

Client-predicted level sounds and LocalPlayer.playSound use those same hooks. Canceling their sound does not cancel the player action or undo a predicted block change. A local player's ordinary sound is an AtEntity request but still plays at the requested position; only a genuinely entity-bound sound (such as a goat horn) follows its emitter after playback starts.

Client routeLevel eventVanilla call being represented
Placement confirmation, predicted doors/buttons/leversAtPositionBlockItem.place, block useWithoutItem → Level.playSound
Waxing, tool transforms, bucket useAtPositionHoneycombItem.useOn, tool useOn, BucketItem → Level.playSound
Game-event arrow hit (Players), pufferfish sting (Neutral), elder-guardian curse (Hostile)AtPositionClientPacketListener.handleGameEvent → Level.playSound
Own steps, swimming, splash, amethyst chime, honey slide, fallAtEntityEntity/LivingEntity → virtual LocalPlayer.playSound
Own hurt/death, bundle menu clicks, consume effectsAtEntityLivingEntity, BundleItem, Consumable → LocalPlayer.playSound
Player-bound sounds, including the local goat hornAtEntityLevel.playSound(except, entity, ...)
Block-breaking/level-event effects, explosions, pickup packetsNoneClient-level playLocalSound or direct sound manager playback
Dragon/fang/sniffer local effects, ticking ambience, UINoneEntity-local effects, sound instances or widgets, not playSeededSound

Server-only gameplay sounds keep their existing broadcast-time event. They are not moved earlier merely because their implementation also calls Audio.

Engine playback and live parameters

play_sound also observes transient playback updates. event.starting is true for a new sound and false while it plays. event.instance identifies the same engine-local instance across those calls. At an update only volume and pitch edits apply; None stops playback. Invalid edited volume (negative or non-finite) or pitch (non-positive or non-finite) refuses that refresh. Updates do not replay the sound, resolve a different source, or modify the instance's stored settings. This is the same interception point, not a parallel sound_play hook.