From 92f44b390eaf8a62c44f396dc9de3a2a042c99ae Mon Sep 17 00:00:00 2001 From: Acruid Date: Sun, 21 Mar 2021 08:35:52 -0700 Subject: [PATCH] SoundSystem Improvements (#1649) --- .../GameObjects/EntitySystems/AudioSystem.cs | 12 +- .../GameObjects/EntitySystems/AudioSystem.cs | 160 +----------------- Robust.Shared/Player/Filter.cs | 94 ++++++++-- 3 files changed, 97 insertions(+), 169 deletions(-) diff --git a/Robust.Client/GameObjects/EntitySystems/AudioSystem.cs b/Robust.Client/GameObjects/EntitySystems/AudioSystem.cs index 142e7103ca..9e4440ea83 100644 --- a/Robust.Client/GameObjects/EntitySystems/AudioSystem.cs +++ b/Robust.Client/GameObjects/EntitySystems/AudioSystem.cs @@ -193,7 +193,7 @@ namespace Robust.Client.GameObjects /// /// The resource path to the OGG Vorbis file to play. /// - public IPlayingAudioStream? Play(string filename, AudioParams? audioParams = null) + private IPlayingAudioStream? Play(string filename, AudioParams? audioParams = null) { if (_resourceCache.TryGetResource(new ResourcePath(filename), out var audio)) { @@ -209,7 +209,7 @@ namespace Robust.Client.GameObjects /// /// The audio stream to play. /// - public IPlayingAudioStream Play(AudioStream stream, AudioParams? audioParams = null) + private IPlayingAudioStream Play(AudioStream stream, AudioParams? audioParams = null) { var source = _clyde.CreateAudioSource(stream); ApplyAudioParams(audioParams, source); @@ -231,7 +231,7 @@ namespace Robust.Client.GameObjects /// The resource path to the OGG Vorbis file to play. /// The entity "emitting" the audio. /// - public IPlayingAudioStream? Play(string filename, IEntity entity, AudioParams? audioParams = null) + private IPlayingAudioStream? Play(string filename, IEntity entity, AudioParams? audioParams = null) { if (_resourceCache.TryGetResource(new ResourcePath(filename), out var audio)) { @@ -248,7 +248,7 @@ namespace Robust.Client.GameObjects /// The audio stream to play. /// The entity "emitting" the audio. /// - public IPlayingAudioStream? Play(AudioStream stream, IEntity entity, AudioParams? audioParams = null) + private IPlayingAudioStream? Play(AudioStream stream, IEntity entity, AudioParams? audioParams = null) { var source = _clyde.CreateAudioSource(stream); if (!source.SetPosition(entity.Transform.WorldPosition)) @@ -277,7 +277,7 @@ namespace Robust.Client.GameObjects /// The resource path to the OGG Vorbis file to play. /// The coordinates at which to play the audio. /// - public IPlayingAudioStream? Play(string filename, EntityCoordinates coordinates, AudioParams? audioParams = null) + private IPlayingAudioStream? Play(string filename, EntityCoordinates coordinates, AudioParams? audioParams = null) { if (_resourceCache.TryGetResource(new ResourcePath(filename), out var audio)) { @@ -294,7 +294,7 @@ namespace Robust.Client.GameObjects /// The audio stream to play. /// The coordinates at which to play the audio. /// - public IPlayingAudioStream? Play(AudioStream stream, EntityCoordinates coordinates, + private IPlayingAudioStream? Play(AudioStream stream, EntityCoordinates coordinates, AudioParams? audioParams = null) { var source = _clyde.CreateAudioSource(stream); diff --git a/Robust.Server/GameObjects/EntitySystems/AudioSystem.cs b/Robust.Server/GameObjects/EntitySystems/AudioSystem.cs index 622a828dba..12507f10cc 100644 --- a/Robust.Server/GameObjects/EntitySystems/AudioSystem.cs +++ b/Robust.Server/GameObjects/EntitySystems/AudioSystem.cs @@ -1,20 +1,17 @@ -using System; using System.Collections.Generic; using System.Linq; -using Robust.Server.Player; +using JetBrains.Annotations; using Robust.Shared.Audio; using Robust.Shared.GameObjects; -using Robust.Shared.IoC; using Robust.Shared.Map; using Robust.Shared.Player; using Robust.Shared.Players; namespace Robust.Server.GameObjects { + [UsedImplicitly] public class AudioSystem : EntitySystem, IAudioSystem { - [Dependency] private readonly IPlayerManager _playerManager = default!; - private const int AudioDistanceRange = 25; private uint _streamIndex; @@ -66,147 +63,6 @@ namespace Robust.Server.GameObjects return unchecked(_streamIndex++); } - /// - /// Play an audio file globally, without position. - /// - /// The resource path to the OGG Vorbis file to play. - /// - /// The predicate that will be used to send the audio to players, or null to send to everyone. - /// Session that won't receive the audio message. - /// - [Obsolete("Use the Play() overload.")] - public IPlayingAudioStream PlayGlobal(string filename, AudioParams? audioParams = null, Func? predicate = null, IPlayerSession? excludedSession = null) - { - var id = CacheIdentifier(); - var msg = new PlayAudioGlobalMessage - { - FileName = filename, - AudioParams = audioParams ?? AudioParams.Default, - Identifier = id - }; - - if (predicate == null && excludedSession == null) - { - RaiseNetworkEvent(msg); - return new AudioSourceServer(this, id); - } - - IList players = predicate != null ? _playerManager.GetPlayersBy(predicate) : _playerManager.GetAllPlayers(); - - for (var i = players.Count - 1; i >= 0; i--) - { - var player = players[i]; - if (player == excludedSession) - { - players.RemoveAt(i); - continue; - } - - RaiseNetworkEvent(msg, player.ConnectedClient); - } - - return new AudioSourceServer(this, id, players); - } - - /// - /// Play an audio file following an entity. - /// - /// The resource path to the OGG Vorbis file to play. - /// The entity "emitting" the audio. - /// - /// The max range at which the audio will be heard. Less than or equal to 0 to send to every player. - /// Sessions that won't receive the audio message. - [Obsolete("Use the Play() overload.")] - public IPlayingAudioStream PlayFromEntity(string filename, IEntity entity, AudioParams? audioParams = null, int range = AudioDistanceRange, IPlayerSession? excludedSession = null) - { - var id = CacheIdentifier(); - - var msg = new PlayAudioEntityMessage - { - FileName = filename, - Coordinates = entity.Transform.Coordinates, - EntityUid = entity.Uid, - AudioParams = audioParams ?? AudioParams.Default, - Identifier = id, - }; - - // send to every player - if (range <= 0 && excludedSession == null) - { - RaiseNetworkEvent(msg); - return new AudioSourceServer(this, id); - } - - List players; - - if (range > 0.0f) - players = _playerManager.GetPlayersInRange(entity.Transform.Coordinates, range); - else - players = _playerManager.GetAllPlayers(); - - for (var i = players.Count - 1; i >= 0; i--) - { - var player = players[i]; - if (player == excludedSession) - { - players.RemoveAt(i); - continue; - } - - RaiseNetworkEvent(msg, player.ConnectedClient); - } - - return new AudioSourceServer(this, id, players); - } - - /// - /// Play an audio file at a static position. - /// - /// The resource path to the OGG Vorbis file to play. - /// The coordinates at which to play the audio. - /// - /// The max range at which the audio will be heard. Less than or equal to 0 to send to every player. - /// Session that won't receive the audio message. - [Obsolete("Use the Play() overload.")] - public IPlayingAudioStream PlayAtCoords(string filename, EntityCoordinates coordinates, AudioParams? audioParams = null, int range = AudioDistanceRange, IPlayerSession? excludedSession = null) - { - var id = CacheIdentifier(); - var msg = new PlayAudioPositionalMessage - { - FileName = filename, - Coordinates = coordinates, - AudioParams = audioParams ?? AudioParams.Default, - Identifier = id - }; - - if (range <= 0 && excludedSession == null) - { - RaiseNetworkEvent(msg); - return new AudioSourceServer(this, id); - } - - List players; - - if (range > 0.0f) - players = _playerManager.GetPlayersInRange(coordinates, range); - else - players = _playerManager.GetAllPlayers(); - - for (var i = players.Count - 1; i >= 0; i--) - { - var player = players[i]; - if (player == excludedSession) - { - players.RemoveAt(i); - continue; - } - - RaiseNetworkEvent(msg, player.ConnectedClient); - } - - return new AudioSourceServer(this, id, players); - } - /// public int DefaultSoundRange => AudioDistanceRange; @@ -214,7 +70,7 @@ namespace Robust.Server.GameObjects public int OcclusionCollisionMask { get; set; } /// - public IPlayingAudioStream? Play(Filter playerFilter, string filename, AudioParams? audioParams = null) + public IPlayingAudioStream Play(Filter playerFilter, string filename, AudioParams? audioParams = null) { var id = CacheIdentifier(); var msg = new PlayAudioGlobalMessage @@ -234,7 +90,7 @@ namespace Robust.Server.GameObjects } /// - public IPlayingAudioStream? Play(Filter playerFilter, string filename, IEntity entity, AudioParams? audioParams = null) + public IPlayingAudioStream Play(Filter playerFilter, string filename, IEntity entity, AudioParams? audioParams = null) { //TODO: Calculate this from PAS var range = audioParams is null || audioParams.Value.MaxDistance <= 0 ? AudioDistanceRange : audioParams.Value.MaxDistance; @@ -254,7 +110,7 @@ namespace Robust.Server.GameObjects var recipients = (playerFilter as IFilter).Recipients; if (range > 0.0f) - players = PASInRange(recipients, entity.Transform.MapPosition, range); + players = PasInRange(recipients, entity.Transform.MapPosition, range); else players = recipients; @@ -267,7 +123,7 @@ namespace Robust.Server.GameObjects } /// - public IPlayingAudioStream? Play(Filter playerFilter, string filename, EntityCoordinates coordinates, AudioParams? audioParams = null) + public IPlayingAudioStream Play(Filter playerFilter, string filename, EntityCoordinates coordinates, AudioParams? audioParams = null) { //TODO: Calculate this from PAS var range = audioParams is null || audioParams.Value.MaxDistance <= 0 ? AudioDistanceRange : audioParams.Value.MaxDistance; @@ -285,7 +141,7 @@ namespace Robust.Server.GameObjects var recipients = (playerFilter as IFilter).Recipients; if (range > 0.0f) - players = PASInRange(recipients, coordinates.ToMap(EntityManager), range); + players = PasInRange(recipients, coordinates.ToMap(EntityManager), range); else players = recipients; @@ -297,7 +153,7 @@ namespace Robust.Server.GameObjects return new AudioSourceServer(this, id, players); } - private static List PASInRange(IEnumerable players, MapCoordinates position, float range) + private static List PasInRange(IEnumerable players, MapCoordinates position, float range) { return players.Where(x => x.AttachedEntity != null && diff --git a/Robust.Shared/Player/Filter.cs b/Robust.Shared/Player/Filter.cs index 3aa3f4ca08..3962d0e64e 100644 --- a/Robust.Shared/Player/Filter.cs +++ b/Robust.Shared/Player/Filter.cs @@ -1,8 +1,10 @@ using System; using System.Collections.Generic; +using System.Linq; using JetBrains.Annotations; +using Robust.Shared.GameObjects; using Robust.Shared.IoC; -using Robust.Shared.Maths; +using Robust.Shared.Map; using Robust.Shared.Players; using Robust.Shared.Utility; @@ -37,7 +39,7 @@ namespace Robust.Shared.Player [PublicAPI] public class Filter : IFilter { - private bool _prediction; + private bool _prediction = true; private List _recipients = new(); private bool _reliable; @@ -59,14 +61,51 @@ namespace Robust.Shared.Player /// /// Adds all players inside an entity's PVS. /// - protected Filter AddPlayersByPvs(Vector2 origin) + protected Filter AddPlayersByPvs(IEntity origin) { - // Calculate this from the PVS system that does not exist. - throw new NotImplementedException(); - - //return this; + return AddPlayersByPvs(origin.Transform.MapPosition); } + /// + /// Adds all players inside an entity's PVS. + /// + protected Filter AddPlayersByPvs(ITransformComponent origin) + { + return AddPlayersByPvs(origin.MapPosition); + } + + /// + /// Adds all players inside an entity's PVS. + /// + protected Filter AddPlayersByPvs(EntityCoordinates origin) + { + var entityMan = IoCManager.Resolve(); + return AddPlayersByPvs(origin.ToMap(entityMan)); + } + + /// + /// Adds all players inside an entity's PVS. + /// + protected Filter AddPlayersByPvs(MapCoordinates origin) + { + //TODO: Calculate this from the PVS system that does not exist. + var playerMan = IoCManager.Resolve(); + + const int range = 25; + var players = playerMan.NetworkedSessions.Where(x => + x.AttachedEntity != null && origin.InRange(x.AttachedEntity.Transform.MapPosition, range)); + + foreach (var session in players) + { + AddPlayer(session); + } + + return this; + } + + /// + /// Adds a set of players to the filter. + /// public Filter AddPlayers(IEnumerable players) { foreach (var player in players) @@ -98,6 +137,9 @@ namespace Robust.Shared.Player return this; } + /// + /// Removes all players from the filter that match a predicate. + /// public Filter RemoveWhere(Predicate predicate) { for (int i = 0; i < _recipients.Count; i++) @@ -114,6 +156,9 @@ namespace Robust.Shared.Player return this; } + /// + /// Adds all players that match a predicate. + /// public Filter AddWhere(Predicate predicate) { var playerMan = IoCManager.Resolve(); @@ -129,11 +174,13 @@ namespace Robust.Shared.Player } /// - /// This filter will properly be handled by prediction. + /// Normally a filter will properly handle client side prediction. Calling this + /// function disables that, and the event will be spammed during every prediction + /// tick. /// - public Filter HandlePrediction() + public Filter Unpredicted() { - _prediction = true; + _prediction = false; return this; } @@ -171,10 +218,35 @@ namespace Robust.Shared.Player return Empty().AddAllPlayers(); } + + /// + /// A filter with every player who's PVS overlaps this entity. + /// + public static Filter Pvs(IEntity origin) + { + return Empty().AddPlayersByPvs(origin); + } + /// /// A filter with every player who's PVS overlaps this point. /// - public static Filter Pvs(Vector2 origin) + public static Filter Pvs(ITransformComponent origin) + { + return Empty().AddPlayersByPvs(origin); + } + + /// + /// A filter with every player who's PVS overlaps this point. + /// + public static Filter Pvs(EntityCoordinates origin) + { + return Empty().AddPlayersByPvs(origin); + } + + /// + /// A filter with every player who's PVS overlaps this point. + /// + public static Filter Pvs(MapCoordinates origin) { return Empty().AddPlayersByPvs(origin); }