Utility/SoundExtensions.cs

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.

Networking
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;
	}
}