From 465a1fb5bd91bcb7ed17cfc8c9e3b342e5997e89 Mon Sep 17 00:00:00 2001 From: Nemanja <98561806+EmoGarbage404@users.noreply.github.com> Date: Sun, 30 Nov 2025 11:32:26 -0500 Subject: [PATCH] Allow content to override ProcessStream and GetOcclusion in AudioSystem (#6268) * Add optional override methods for ProcessStream and GetOcclusion * Mark override events as static * Change audio actions to non-static --- Robust.Client/Audio/AudioSystem.cs | 38 ++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/Robust.Client/Audio/AudioSystem.cs b/Robust.Client/Audio/AudioSystem.cs index 3492e5b96..acf412008 100644 --- a/Robust.Client/Audio/AudioSystem.cs +++ b/Robust.Client/Audio/AudioSystem.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Numerics; +using JetBrains.Annotations; using OpenTK.Audio.OpenAL; using Robust.Client.GameObjects; using Robust.Client.Graphics; @@ -45,6 +46,26 @@ public sealed partial class AudioSystem : SharedAudioSystem [Dependency] private readonly SharedTransformSystem _xformSys = default!; [Dependency] private readonly SharedPhysicsSystem _physics = default!; + /// + /// An optional method that, if provided, will override the behavior of . + /// Contains the same parameters in the same order as the method it overrides. + /// + /// + /// This event only supports a single invocation target. + /// + [PublicAPI] + public event Action? ProcessStreamOverride; + + /// + /// An optional method that, if provided, will override the behavior of . + /// Contains the same parameters in the same order as the method it overrides. + /// + /// + /// This event only supports a single invocation target. + /// + [PublicAPI] + public event Func? GetOcclusionOverride; + /// /// Per-tick cache of relevant streams. /// @@ -341,6 +362,15 @@ public sealed partial class AudioSystem : SharedAudioSystem private void ProcessStream(EntityUid entity, AudioComponent component, TransformComponent xform, MapCoordinates listener) { + // If content wants to process the stream in their own special way, we simply let them handle that. + if (ProcessStreamOverride is not null) + { + // Assert that we are not processing audio multiple times. + DebugTools.Assert(ProcessStreamOverride.HasSingleTarget, $"Event {nameof(ProcessStreamOverride)} has multiple invocation targets. This is not permitted."); + ProcessStreamOverride.Invoke(entity, component, xform, listener); + return; // Exit and do not perform remaining function behavior + } + // TODO: // I Originally tried to be fancier here but it caused audio issues so just trying // to replicate the old behaviour for now. @@ -434,6 +464,14 @@ public sealed partial class AudioSystem : SharedAudioSystem /// public float GetOcclusion(MapCoordinates listener, Vector2 delta, float distance, EntityUid? ignoredEnt = null) { + // If content has defined a custom occlusion method, use that instead. + if (GetOcclusionOverride is not null) + { + // There can only be one occlusion override defined. + DebugTools.Assert(GetOcclusionOverride.HasSingleTarget, $"Event {nameof(GetOcclusionOverride)} has multiple invocation targets. This is not permitted."); + return GetOcclusionOverride.Invoke(listener, delta, distance, ignoredEnt); + } + float occlusion = 0; if (distance > 0.1)