mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-14 19:29:36 +01:00
SoundSystem (#1604)
* Adds the SoundSystem static proxy class for the AudioSystem. Added a shared IAudioSystem interface for the future. * Moved ConnectedClient property from IPlayerSession down to ICommonSession. * Connected up the SoundSystem to the client/server AudioSystems. * Converted client calls over to the new system. * Marked the old serverside functions to play sound obsolete, use the new ones from the IAudioSystem. * Added ISharedPlayerManager to the IoC registration.
This commit is contained in:
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Player;
|
||||
|
||||
namespace Robust.Client.Animations
|
||||
{
|
||||
@@ -36,8 +37,7 @@ namespace Robust.Client.Animations
|
||||
|
||||
var keyFrame = KeyFrames[keyFrameIndex];
|
||||
|
||||
EntitySystem.Get<AudioSystem>()
|
||||
.Play(keyFrame.Resource, entity, keyFrame.AudioParamsFunc.Invoke());
|
||||
SoundSystem.Play(Filter.Local(), keyFrame.Resource, entity, keyFrame.AudioParamsFunc.Invoke());
|
||||
}
|
||||
|
||||
return (keyFrameIndex, playingTime);
|
||||
|
||||
@@ -24,6 +24,7 @@ using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Players;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Reflection;
|
||||
|
||||
@@ -53,6 +54,7 @@ namespace Robust.Client
|
||||
IoCManager.Register<IClientGameStateManager, ClientGameStateManager>();
|
||||
IoCManager.Register<IBaseClient, BaseClient>();
|
||||
IoCManager.Register<IPlayerManager, PlayerManager>();
|
||||
IoCManager.Register<ISharedPlayerManager, PlayerManager>();
|
||||
IoCManager.Register<IStateManager, StateManager>();
|
||||
IoCManager.Register<IUserInterfaceManager, UserInterfaceManager>();
|
||||
IoCManager.Register<IUserInterfaceManagerInternal, UserInterfaceManager>();
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.Audio;
|
||||
@@ -11,12 +10,13 @@ using Robust.Shared.Log;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Client.GameObjects
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public class AudioSystem : EntitySystem
|
||||
public class AudioSystem : EntitySystem, IAudioSystem
|
||||
{
|
||||
[Dependency] private readonly IResourceCache _resourceCache = default!;
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
@@ -25,9 +25,7 @@ namespace Robust.Client.GameObjects
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
|
||||
private readonly List<PlayingStream> _playingClydeStreams = new();
|
||||
|
||||
public int OcclusionCollisionMask;
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -35,6 +33,8 @@ namespace Robust.Client.GameObjects
|
||||
SubscribeNetworkEvent<PlayAudioGlobalMessage>(PlayAudioGlobalHandler);
|
||||
SubscribeNetworkEvent<PlayAudioPositionalMessage>(PlayAudioPositionalHandler);
|
||||
SubscribeNetworkEvent<StopAudioMessageClient>(StopAudioMessageHandler);
|
||||
|
||||
SubscribeLocalEvent<SoundSystem.QueryAudioSystem>((ev => ev.Audio = this));
|
||||
}
|
||||
|
||||
private void StopAudioMessageHandler(StopAudioMessageClient ev)
|
||||
@@ -176,7 +176,6 @@ namespace Robust.Client.GameObjects
|
||||
{
|
||||
stream.Source.Dispose();
|
||||
stream.Done = true;
|
||||
stream.DoPlaybackDone();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -335,92 +334,30 @@ namespace Robust.Client.GameObjects
|
||||
{
|
||||
Source.StopPlaying();
|
||||
}
|
||||
|
||||
public event Action? PlaybackDone;
|
||||
|
||||
public void DoPlaybackDone()
|
||||
{
|
||||
PlaybackDone?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface IPlayingAudioStream
|
||||
{
|
||||
void Stop();
|
||||
|
||||
event Action PlaybackDone;
|
||||
}
|
||||
|
||||
public static class AudioSystemExtensions
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Play an audio file following an entity.
|
||||
/// </summary>
|
||||
/// <param name="filename">The resource path to the OGG Vorbis file to play.</param>
|
||||
/// <param name="entity">The entity "emitting" the audio.</param>
|
||||
/// <param name="audioParams"></param>
|
||||
/// <param name="audioSystem">A pre-fetched instance of <see cref="AudioSystem"/> to use, can be null.</param>
|
||||
public static IPlayingAudioStream? Play(
|
||||
this IEntity entity,
|
||||
string filename,
|
||||
AudioParams? audioParams,
|
||||
AudioSystem? audioSystem = null)
|
||||
{
|
||||
audioSystem ??= EntitySystem.Get<AudioSystem>();
|
||||
return audioSystem.Play(filename, entity, audioParams);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Play an audio stream following an entity.
|
||||
/// </summary>
|
||||
/// <param name="stream">The audio stream to play.</param>
|
||||
/// <param name="entity">The entity "emitting" the audio.</param>
|
||||
/// <param name="audioParams"></param>
|
||||
/// <param name="audioSystem">A pre-fetched instance of <see cref="AudioSystem"/> to use, can be null.</param>
|
||||
public static IPlayingAudioStream? Play(
|
||||
this IEntity entity,
|
||||
AudioStream stream,
|
||||
AudioParams? audioParams = null,
|
||||
AudioSystem? audioSystem = null)
|
||||
/// <inheritdoc />
|
||||
public int DefaultSoundRange => 25;
|
||||
|
||||
/// <inheritdoc />
|
||||
public int OcclusionCollisionMask { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public IPlayingAudioStream? Play(Filter playerFilter, string filename, AudioParams? audioParams = null)
|
||||
{
|
||||
audioSystem ??= EntitySystem.Get<AudioSystem>();
|
||||
return audioSystem.Play(stream, entity, audioParams);
|
||||
return Play(filename, audioParams);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Play an audio file at a static position.
|
||||
/// </summary>
|
||||
/// <param name="filename">The resource path to the OGG Vorbis file to play.</param>
|
||||
/// <param name="coordinates">The coordinates at which to play the audio.</param>
|
||||
/// <param name="audioParams"></param>
|
||||
/// <param name="audioSystem">A pre-fetched instance of <see cref="AudioSystem"/> to use, can be null.</param>
|
||||
public static IPlayingAudioStream? Play(
|
||||
this EntityCoordinates coordinates,
|
||||
string filename,
|
||||
AudioParams? audioParams = null,
|
||||
AudioSystem? audioSystem = null)
|
||||
/// <inheritdoc />
|
||||
public IPlayingAudioStream? Play(Filter playerFilter, string filename, IEntity entity, AudioParams? audioParams = null)
|
||||
{
|
||||
audioSystem ??= EntitySystem.Get<AudioSystem>();
|
||||
return audioSystem.Play(filename, coordinates, audioParams);
|
||||
return Play(filename, entity, audioParams);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Play an audio stream at a static position.
|
||||
/// </summary>
|
||||
/// <param name="stream">The audio stream to play.</param>
|
||||
/// <param name="coordinates">The coordinates at which to play the audio.</param>
|
||||
/// <param name="audioParams"></param>
|
||||
/// <param name="audioSystem">A pre-fetched instance of <see cref="AudioSystem"/> to use, can be null.</param>
|
||||
public static IPlayingAudioStream? Play(
|
||||
this EntityCoordinates coordinates,
|
||||
AudioStream stream,
|
||||
AudioParams? audioParams = null,
|
||||
AudioSystem? audioSystem = null)
|
||||
/// <inheritdoc />
|
||||
public IPlayingAudioStream? Play(Filter playerFilter, string filename, EntityCoordinates coordinates, AudioParams? audioParams = null)
|
||||
{
|
||||
audioSystem ??= EntitySystem.Get<AudioSystem>();
|
||||
return audioSystem.Play(stream, coordinates, audioParams);
|
||||
return Play(filename, coordinates, audioParams);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,7 +207,7 @@ namespace Robust.Client.Player
|
||||
if (state.UserId == LocalPlayer!.UserId)
|
||||
{
|
||||
LocalPlayer.InternalSession = newSession;
|
||||
|
||||
newSession.ConnectedClient = _network.ServerChannel!;
|
||||
// We just connected to the server, hurray!
|
||||
LocalPlayer.SwitchState(SessionStatus.Connecting, newSession.Status);
|
||||
}
|
||||
|
||||
@@ -39,6 +39,9 @@ namespace Robust.Client.Player
|
||||
/// <inheritdoc />
|
||||
internal short Ping { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public INetChannel ConnectedClient { get; internal set; } = null!;
|
||||
|
||||
/// <inheritdoc />
|
||||
short ICommonSession.Ping
|
||||
{
|
||||
|
||||
@@ -1,29 +1,31 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Map;
|
||||
using static Robust.Server.GameObjects.AudioSystem;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Players;
|
||||
|
||||
namespace Robust.Server.GameObjects
|
||||
{
|
||||
public class AudioSystem : EntitySystem
|
||||
public class AudioSystem : EntitySystem, IAudioSystem
|
||||
{
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
|
||||
public const int AudioDistanceRange = 25;
|
||||
private const int AudioDistanceRange = 25;
|
||||
|
||||
private uint _streamIndex;
|
||||
|
||||
public class AudioSourceServer
|
||||
private class AudioSourceServer : IPlayingAudioStream
|
||||
{
|
||||
private readonly uint _id;
|
||||
private readonly AudioSystem _audioSystem;
|
||||
private readonly IEnumerable<IPlayerSession>? _sessions;
|
||||
private readonly IEnumerable<ICommonSession>? _sessions;
|
||||
|
||||
internal AudioSourceServer(AudioSystem parent, uint identifier, IEnumerable<IPlayerSession>? sessions = null)
|
||||
internal AudioSourceServer(AudioSystem parent, uint identifier, IEnumerable<ICommonSession>? sessions = null)
|
||||
{
|
||||
_audioSystem = parent;
|
||||
_id = identifier;
|
||||
@@ -35,7 +37,13 @@ namespace Robust.Server.GameObjects
|
||||
}
|
||||
}
|
||||
|
||||
private void InternalStop(uint id, IEnumerable<IPlayerSession>? sessions = null)
|
||||
/// <inheritdoc />
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<SoundSystem.QueryAudioSystem>((ev => ev.Audio = this));
|
||||
}
|
||||
|
||||
private void InternalStop(uint id, IEnumerable<ICommonSession>? sessions = null)
|
||||
{
|
||||
var msg = new StopAudioMessageClient
|
||||
{
|
||||
@@ -65,7 +73,9 @@ namespace Robust.Server.GameObjects
|
||||
/// <param name="audioParams"></param>
|
||||
/// <param name="predicate">The predicate that will be used to send the audio to players, or null to send to everyone.</param>
|
||||
/// <param name="excludedSession">Session that won't receive the audio message.</param>
|
||||
public AudioSourceServer PlayGlobal(string filename, AudioParams? audioParams = null, Func<IPlayerSession, bool>? predicate = null, IPlayerSession? excludedSession = null)
|
||||
/// <param name="recipients"></param>
|
||||
[Obsolete("Use the Play() overload.")]
|
||||
public IPlayingAudioStream PlayGlobal(string filename, AudioParams? audioParams = null, Func<IPlayerSession, bool>? predicate = null, IPlayerSession? excludedSession = null)
|
||||
{
|
||||
var id = CacheIdentifier();
|
||||
var msg = new PlayAudioGlobalMessage
|
||||
@@ -81,7 +91,7 @@ namespace Robust.Server.GameObjects
|
||||
return new AudioSourceServer(this, id);
|
||||
}
|
||||
|
||||
var players = predicate != null ? _playerManager.GetPlayersBy(predicate) : _playerManager.GetAllPlayers();
|
||||
IList<IPlayerSession> players = predicate != null ? _playerManager.GetPlayersBy(predicate) : _playerManager.GetAllPlayers();
|
||||
|
||||
for (var i = players.Count - 1; i >= 0; i--)
|
||||
{
|
||||
@@ -96,7 +106,6 @@ namespace Robust.Server.GameObjects
|
||||
}
|
||||
|
||||
return new AudioSourceServer(this, id, players);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -107,7 +116,8 @@ namespace Robust.Server.GameObjects
|
||||
/// <param name="audioParams"></param>
|
||||
/// <param name="range">The max range at which the audio will be heard. Less than or equal to 0 to send to every player.</param>
|
||||
/// <param name="excludedSession">Sessions that won't receive the audio message.</param>
|
||||
public AudioSourceServer PlayFromEntity(string filename, IEntity entity, AudioParams? audioParams = null, int range = AudioDistanceRange, IPlayerSession? excludedSession = null)
|
||||
[Obsolete("Use the Play() overload.")]
|
||||
public IPlayingAudioStream PlayFromEntity(string filename, IEntity entity, AudioParams? audioParams = null, int range = AudioDistanceRange, IPlayerSession? excludedSession = null)
|
||||
{
|
||||
var id = CacheIdentifier();
|
||||
|
||||
@@ -120,13 +130,19 @@ namespace Robust.Server.GameObjects
|
||||
Identifier = id,
|
||||
};
|
||||
|
||||
// send to every player
|
||||
if (range <= 0 && excludedSession == null)
|
||||
{
|
||||
RaiseNetworkEvent(msg);
|
||||
return new AudioSourceServer(this, id);
|
||||
}
|
||||
|
||||
var players = range > 0.0f ? _playerManager.GetPlayersInRange(entity.Transform.Coordinates, range) : _playerManager.GetAllPlayers();
|
||||
List<IPlayerSession> 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--)
|
||||
{
|
||||
@@ -151,7 +167,8 @@ namespace Robust.Server.GameObjects
|
||||
/// <param name="audioParams"></param>
|
||||
/// <param name="range">The max range at which the audio will be heard. Less than or equal to 0 to send to every player.</param>
|
||||
/// <param name="excludedSession">Session that won't receive the audio message.</param>
|
||||
public AudioSourceServer PlayAtCoords(string filename, EntityCoordinates coordinates, AudioParams? audioParams = null, int range = AudioDistanceRange, IPlayerSession? excludedSession = null)
|
||||
[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
|
||||
@@ -168,7 +185,12 @@ namespace Robust.Server.GameObjects
|
||||
return new AudioSourceServer(this, id);
|
||||
}
|
||||
|
||||
var players = range > 0.0f ? _playerManager.GetPlayersInRange(coordinates, range) : _playerManager.GetAllPlayers();
|
||||
List<IPlayerSession> players;
|
||||
|
||||
if (range > 0.0f)
|
||||
players = _playerManager.GetPlayersInRange(coordinates, range);
|
||||
else
|
||||
players = _playerManager.GetAllPlayers();
|
||||
|
||||
for (var i = players.Count - 1; i >= 0; i--)
|
||||
{
|
||||
@@ -185,88 +207,102 @@ namespace Robust.Server.GameObjects
|
||||
return new AudioSourceServer(this, id, players);
|
||||
}
|
||||
|
||||
#region DEPRECATED
|
||||
/// <summary>
|
||||
/// Play an audio file globally, without position.
|
||||
/// </summary>
|
||||
/// <param name="filename">The resource path to the OGG Vorbis file to play.</param>
|
||||
/// <param name="audioParams"></param>
|
||||
[Obsolete("Deprecated. Use PlayGlobal instead.")]
|
||||
public void Play(string filename, AudioParams? audioParams = null)
|
||||
/// <inheritdoc />
|
||||
public int DefaultSoundRange => AudioDistanceRange;
|
||||
|
||||
/// <inheritdoc />
|
||||
public int OcclusionCollisionMask { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public IPlayingAudioStream? Play(Filter playerFilter, string filename, AudioParams? audioParams = null)
|
||||
{
|
||||
PlayGlobal(filename, audioParams);
|
||||
var id = CacheIdentifier();
|
||||
var msg = new PlayAudioGlobalMessage
|
||||
{
|
||||
FileName = filename,
|
||||
AudioParams = audioParams ?? AudioParams.Default,
|
||||
Identifier = id
|
||||
};
|
||||
|
||||
var players = (playerFilter as IFilter).Recipients;
|
||||
foreach (var player in players)
|
||||
{
|
||||
RaiseNetworkEvent(msg, player.ConnectedClient);
|
||||
}
|
||||
|
||||
return new AudioSourceServer(this, id, players);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Play an audio file following an entity.
|
||||
/// </summary>
|
||||
/// <param name="filename">The resource path to the OGG Vorbis file to play.</param>
|
||||
/// <param name="entity">The entity "emitting" the audio.</param>
|
||||
/// <param name="audioParams"></param>
|
||||
[Obsolete("Deprecated. Use PlayFromEntity instead.")]
|
||||
public void Play(string filename, IEntity entity, AudioParams? audioParams = null)
|
||||
/// <inheritdoc />
|
||||
public IPlayingAudioStream? Play(Filter playerFilter, string filename, IEntity entity, AudioParams? audioParams = null)
|
||||
{
|
||||
PlayFromEntity(filename, entity, audioParams);
|
||||
//TODO: Calculate this from PAS
|
||||
var range = audioParams is null || audioParams.Value.MaxDistance <= 0 ? AudioDistanceRange : audioParams.Value.MaxDistance;
|
||||
|
||||
var id = CacheIdentifier();
|
||||
|
||||
var msg = new PlayAudioEntityMessage
|
||||
{
|
||||
FileName = filename,
|
||||
Coordinates = entity.Transform.Coordinates,
|
||||
EntityUid = entity.Uid,
|
||||
AudioParams = audioParams ?? AudioParams.Default,
|
||||
Identifier = id,
|
||||
};
|
||||
|
||||
IList<ICommonSession> players;
|
||||
var recipients = (playerFilter as IFilter).Recipients;
|
||||
|
||||
if (range > 0.0f)
|
||||
players = PASInRange(recipients, entity.Transform.MapPosition, range);
|
||||
else
|
||||
players = recipients;
|
||||
|
||||
foreach (var player in players)
|
||||
{
|
||||
RaiseNetworkEvent(msg, player.ConnectedClient);
|
||||
}
|
||||
|
||||
return new AudioSourceServer(this, id, players);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Play an audio file at a static position.
|
||||
/// </summary>
|
||||
/// <param name="filename">The resource path to the OGG Vorbis file to play.</param>
|
||||
/// <param name="coordinates">The coordinates at which to play the audio.</param>
|
||||
/// <param name="audioParams"></param>
|
||||
[Obsolete("Deprecated. Use PlayAtCoords instead.")]
|
||||
public void Play(string filename, EntityCoordinates coordinates, AudioParams? audioParams = null)
|
||||
/// <inheritdoc />
|
||||
public IPlayingAudioStream? Play(Filter playerFilter, string filename, EntityCoordinates coordinates, AudioParams? audioParams = null)
|
||||
{
|
||||
PlayAtCoords(filename, coordinates, audioParams);
|
||||
//TODO: Calculate this from PAS
|
||||
var range = audioParams is null || audioParams.Value.MaxDistance <= 0 ? AudioDistanceRange : audioParams.Value.MaxDistance;
|
||||
|
||||
var id = CacheIdentifier();
|
||||
var msg = new PlayAudioPositionalMessage
|
||||
{
|
||||
FileName = filename,
|
||||
Coordinates = coordinates,
|
||||
AudioParams = audioParams ?? AudioParams.Default,
|
||||
Identifier = id
|
||||
};
|
||||
|
||||
IList<ICommonSession> players;
|
||||
var recipients = (playerFilter as IFilter).Recipients;
|
||||
|
||||
if (range > 0.0f)
|
||||
players = PASInRange(recipients, coordinates.ToMap(EntityManager), range);
|
||||
else
|
||||
players = recipients;
|
||||
|
||||
foreach (var player in players)
|
||||
{
|
||||
RaiseNetworkEvent(msg, player.ConnectedClient);
|
||||
}
|
||||
|
||||
return new AudioSourceServer(this, id, players);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public static class AudioSystemExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Play an audio file following an entity.
|
||||
/// </summary>
|
||||
/// <param name="filename">The resource path to the OGG Vorbis file to play.</param>
|
||||
/// <param name="entity">The entity "emitting" the audio.</param>
|
||||
/// <param name="audioParams"></param>
|
||||
/// <param name="range">The max range at which the audio will be heard. Less than or equal to 0 to send to every player.</param>
|
||||
/// <param name="excludedSession">Sessions that won't receive the audio message.</param>
|
||||
/// <param name="audioSystem">A pre-fetched instance of <see cref="AudioSystem"/> to use, can be null.</param>
|
||||
public static void PlaySoundFrom(
|
||||
this IEntity entity,
|
||||
string filename,
|
||||
AudioParams? audioParams = null,
|
||||
int range = AudioDistanceRange,
|
||||
IPlayerSession? excludedSession = null,
|
||||
AudioSystem? audioSystem = null)
|
||||
private static List<ICommonSession> PASInRange(IEnumerable<ICommonSession> players, MapCoordinates position, float range)
|
||||
{
|
||||
audioSystem ??= EntitySystem.Get<AudioSystem>();
|
||||
audioSystem.PlayFromEntity(filename, entity, audioParams, range, excludedSession);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Play an audio file at a static position.
|
||||
/// </summary>
|
||||
/// <param name="filename">The resource path to the OGG Vorbis file to play.</param>
|
||||
/// <param name="coordinates">The coordinates at which to play the audio.</param>
|
||||
/// <param name="audioParams"></param>
|
||||
/// <param name="range">The max range at which the audio will be heard. Less than or equal to 0 to send to every player.</param>
|
||||
/// <param name="excludedSession">Session that won't receive the audio message.</param>
|
||||
/// <param name="audioSystem">A pre-fetched instance of <see cref="AudioSystem"/> to use, can be null.</param>
|
||||
public static void PlaySoundFrom(
|
||||
this EntityCoordinates coordinates,
|
||||
string filename,
|
||||
AudioParams? audioParams = null,
|
||||
int range = AudioDistanceRange,
|
||||
IPlayerSession? excludedSession = null,
|
||||
AudioSystem? audioSystem = null)
|
||||
{
|
||||
audioSystem ??= EntitySystem.Get<AudioSystem>();
|
||||
audioSystem.PlayAtCoords(filename, coordinates, audioParams, range, excludedSession);
|
||||
return players.Where(x =>
|
||||
x.AttachedEntity != null &&
|
||||
position.InRange(x.AttachedEntity.Transform.MapPosition, range))
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ namespace Robust.Server.Player
|
||||
{
|
||||
public interface IPlayerSession : ICommonSession
|
||||
{
|
||||
INetChannel ConnectedClient { get; }
|
||||
DateTime ConnectedTime { get; }
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -18,6 +18,7 @@ using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Players;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Reflection;
|
||||
using Robust.Shared.Timing;
|
||||
@@ -45,6 +46,7 @@ namespace Robust.Server
|
||||
IoCManager.Register<IMapLoader, MapLoader>();
|
||||
IoCManager.Register<IPlacementManager, PlacementManager>();
|
||||
IoCManager.Register<IPlayerManager, PlayerManager>();
|
||||
IoCManager.Register<ISharedPlayerManager, PlayerManager>();
|
||||
IoCManager.Register<IPrototypeManager, ServerPrototypeManager>();
|
||||
IoCManager.Register<IReflectionManager, ServerReflectionManager>();
|
||||
IoCManager.Register<IResourceManager, ResourceManager>();
|
||||
|
||||
48
Robust.Shared/Audio/IAudioSystem.cs
Normal file
48
Robust.Shared/Audio/IAudioSystem.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Player;
|
||||
|
||||
namespace Robust.Shared.Audio
|
||||
{
|
||||
/// <summary>
|
||||
/// Common interface for the Audio System, which is used to play sounds on clients.
|
||||
/// </summary>
|
||||
public interface IAudioSystem
|
||||
{
|
||||
/// <summary>
|
||||
/// Default max range at which the sound can be heard.
|
||||
/// </summary>
|
||||
int DefaultSoundRange { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Used in the PAS to designate the physics collision mask of occluders.
|
||||
/// </summary>
|
||||
int OcclusionCollisionMask { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Play an audio file globally, without position.
|
||||
/// </summary>
|
||||
/// <param name="playerFilter">The set of players that will hear the sound.</param>
|
||||
/// <param name="filename">The resource path to the OGG Vorbis file to play.</param>
|
||||
/// <param name="audioParams">Audio parameters to apply when playing the sound.</param>
|
||||
IPlayingAudioStream? Play(Filter playerFilter, string filename, AudioParams? audioParams = null);
|
||||
|
||||
/// <summary>
|
||||
/// Play an audio file following an entity.
|
||||
/// </summary>
|
||||
/// <param name="playerFilter">The set of players that will hear the sound.</param>
|
||||
/// <param name="filename">The resource path to the OGG Vorbis file to play.</param>
|
||||
/// <param name="entity">The entity "emitting" the audio.</param>
|
||||
/// <param name="audioParams">Audio parameters to apply when playing the sound.</param>
|
||||
IPlayingAudioStream? Play(Filter playerFilter, string filename, IEntity entity, AudioParams? audioParams = null);
|
||||
|
||||
/// <summary>
|
||||
/// Play an audio file at a static position.
|
||||
/// </summary>
|
||||
/// <param name="playerFilter">The set of players that will hear the sound.</param>
|
||||
/// <param name="filename">The resource path to the OGG Vorbis file to play.</param>
|
||||
/// <param name="coordinates">The coordinates at which to play the audio.</param>
|
||||
/// <param name="audioParams">Audio parameters to apply when playing the sound.</param>
|
||||
IPlayingAudioStream? Play(Filter playerFilter, string filename, EntityCoordinates coordinates, AudioParams? audioParams = null);
|
||||
}
|
||||
}
|
||||
7
Robust.Shared/Audio/IPlayingAudioStream.cs
Normal file
7
Robust.Shared/Audio/IPlayingAudioStream.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace Robust.Shared.Audio
|
||||
{
|
||||
public interface IPlayingAudioStream
|
||||
{
|
||||
void Stop();
|
||||
}
|
||||
}
|
||||
82
Robust.Shared/Audio/SoundSystem.cs
Normal file
82
Robust.Shared/Audio/SoundSystem.cs
Normal file
@@ -0,0 +1,82 @@
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Player;
|
||||
|
||||
namespace Robust.Shared.Audio
|
||||
{
|
||||
/// <summary>
|
||||
/// A static proxy class for interfacing with the AudioSystem.
|
||||
/// </summary>
|
||||
public static class SoundSystem
|
||||
{
|
||||
/// <summary>
|
||||
/// Default max range at which the sound can be heard.
|
||||
/// </summary>
|
||||
public static int DefaultSoundRange => GetAudio()?.DefaultSoundRange ?? 0;
|
||||
|
||||
/// <summary>
|
||||
/// Used in the PAS to designate the physics collision mask of occluders.
|
||||
/// </summary>
|
||||
public static int OcclusionCollisionMask
|
||||
{
|
||||
get => GetAudio()?.OcclusionCollisionMask ?? 0;
|
||||
set
|
||||
{
|
||||
var audio = GetAudio();
|
||||
|
||||
if (audio is null)
|
||||
return;
|
||||
audio.OcclusionCollisionMask = value;
|
||||
}
|
||||
}
|
||||
|
||||
private static IAudioSystem? GetAudio()
|
||||
{
|
||||
// There appears to be no way to get a System by interface.
|
||||
var args = new QueryAudioSystem();
|
||||
IoCManager.Resolve<IEntityManager>().EventBus.RaiseEvent(EventSource.Local, args);
|
||||
return args.Audio;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Play an audio file globally, without position.
|
||||
/// </summary>
|
||||
/// <param name="playerFilter">The set of players that will hear the sound.</param>
|
||||
/// <param name="filename">The resource path to the OGG Vorbis file to play.</param>
|
||||
/// <param name="audioParams">Audio parameters to apply when playing the sound.</param>
|
||||
public static IPlayingAudioStream? Play(Filter playerFilter, string filename, AudioParams? audioParams = null)
|
||||
{
|
||||
return GetAudio()?.Play(playerFilter, filename, audioParams);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Play an audio file following an entity.
|
||||
/// </summary>
|
||||
/// <param name="playerFilter">The set of players that will hear the sound.</param>
|
||||
/// <param name="filename">The resource path to the OGG Vorbis file to play.</param>
|
||||
/// <param name="entity">The entity "emitting" the audio.</param>
|
||||
/// <param name="audioParams">Audio parameters to apply when playing the sound.</param>
|
||||
public static IPlayingAudioStream? Play(Filter playerFilter, string filename, IEntity entity, AudioParams? audioParams = null)
|
||||
{
|
||||
return GetAudio()?.Play(playerFilter, filename, entity, audioParams);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Play an audio file at a static position.
|
||||
/// </summary>
|
||||
/// <param name="playerFilter">The set of players that will hear the sound.</param>
|
||||
/// <param name="filename">The resource path to the OGG Vorbis file to play.</param>
|
||||
/// <param name="coordinates">The coordinates at which to play the audio.</param>
|
||||
/// <param name="audioParams">Audio parameters to apply when playing the sound.</param>
|
||||
public static IPlayingAudioStream? Play(Filter playerFilter, string filename, EntityCoordinates coordinates, AudioParams? audioParams = null)
|
||||
{
|
||||
return GetAudio()?.Play(playerFilter, filename, coordinates, audioParams);
|
||||
}
|
||||
|
||||
internal class QueryAudioSystem : EntitySystemMessage
|
||||
{
|
||||
public IAudioSystem? Audio { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,5 +38,14 @@ namespace Robust.Shared.Players
|
||||
/// Current connection latency of this session from the server to their client.
|
||||
/// </summary>
|
||||
short Ping { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// The current network channel for this player.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// On the Server every player has a network channel,
|
||||
/// on the Client only the LocalPlayer has a network channel.
|
||||
/// </remarks>
|
||||
INetChannel ConnectedClient { get; }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user