Utility static class adding RPC broadcast helpers to play one-shot sounds on every client. It exposes BroadcastPlay for positional sounds and BroadcastPlay2D for non-positional sounds, both sent as unreliable network broadcasts and setting the returned sound handle volume.
using Sandbox;
namespace BrickJam;
/// <summary>
/// Networked one-shot sound helpers. A lot of gameplay audio (monster AI, doors, the player controller,
/// status effects) is triggered from code that only runs on ONE machine - host-only AI/doors, owner-only
/// controller/status - and a plain <see cref="Sound.Play(string)"/> is only audible on that machine. These
/// broadcast the play to EVERY client so remote players hear it too.
///
/// Broadcasts are <see cref="NetFlags.Unreliable"/>: a dropped cosmetic one-shot SFX packet is harmless and
/// we don't want to pay the retransmit/ordering cost for it. Use for fire-and-forget sounds only - a
/// continuous sound whose handle you keep (to reposition / stop) should instead be driven locally off a
/// <c>[Sync]</c> flag on every client (see <see cref="Player.IsSkidding"/>).
/// </summary>
public static class SoundExtensions
{
/// <summary>Play a positional one-shot sound on EVERY client (unreliable broadcast).</summary>
[Rpc.Broadcast( NetFlags.Unreliable )]
public static void BroadcastPlay( string path, Vector3 position, float volume = 1f )
{
if ( string.IsNullOrEmpty( path ) )
return;
var handle = Sound.Play( path, position );
if ( handle is not null )
handle.Volume = volume;
}
/// <summary>Play a non-positional (2D) one-shot sound on EVERY client (unreliable broadcast).</summary>
[Rpc.Broadcast( NetFlags.Unreliable )]
public static void BroadcastPlay2D( string path, float volume = 1f )
{
if ( string.IsNullOrEmpty( path ) )
return;
var handle = Sound.Play( path );
if ( handle is not null )
handle.Volume = volume;
}
}