mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-09-04 11:07:12 +02:00
- Recipients is now of type `IEnumerable<ICommonSession>`.
- This way, people need to use the Filter API to modify the recipients, instead of being allowed to modify the underlying collection directly.
- Underlying collection is now a HashSet.
- We want no duplicates at all. This will ensure that while being quite performant.
- Removes `IFilter`.
- Let's face it, everyone is gonna end up using `Filter` instead as it has a much more convenient API, and nothing else will EVER implement `IFilter`. For this reason, I've just gone ahead and removed it. Every method used `Filter` already, anyway.
- Adds EntitySystem `RaiseNetworkEvent` overload that takes in a `Filter`.
- This deduplicates a lot of code that enumerated the recipients and raised a network event per each one.
- Made AddPlayersByPvs aware of `net.pvs` and `net.maxupdaterange`, has a range multiplier parameter.
- Now it will simply add all players to the filter if PVS is disabled, and add all players in range if it's enabled.
- The range multiplier parameter allows us to make the PVS filter a bit more permissive, and generally better. The range is doubled by default, as it was already before.
- Adds `AddInRange` method to filters.
- This is useful for the AudioSystem, and the PVS methods use it, too!
- Adds `RemoveByVisibility` method to filters.
- This will remove all recipients that don't have a visibility flag in their entity's EyeComponent from the filter.
- (This will be VERY useful for Ghost Pointing, for example)
- Adds `Clone` method to filters.
- This is useful in cases where methods take in a filter and want to modify it without modifying the original instance. (See AudioSystem)
139 lines
4.5 KiB
C#
139 lines
4.5 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using JetBrains.Annotations;
|
|
using Robust.Shared.Audio;
|
|
using Robust.Shared.GameObjects;
|
|
using Robust.Shared.Map;
|
|
using Robust.Shared.Player;
|
|
using Robust.Shared.Players;
|
|
|
|
namespace Robust.Server.GameObjects
|
|
{
|
|
[UsedImplicitly]
|
|
public class AudioSystem : EntitySystem, IAudioSystem
|
|
{
|
|
private const int AudioDistanceRange = 25;
|
|
|
|
private uint _streamIndex;
|
|
|
|
private class AudioSourceServer : IPlayingAudioStream
|
|
{
|
|
private readonly uint _id;
|
|
private readonly AudioSystem _audioSystem;
|
|
private readonly IEnumerable<ICommonSession>? _sessions;
|
|
|
|
internal AudioSourceServer(AudioSystem parent, uint identifier, IEnumerable<ICommonSession>? sessions = null)
|
|
{
|
|
_audioSystem = parent;
|
|
_id = identifier;
|
|
_sessions = sessions;
|
|
}
|
|
public void Stop()
|
|
{
|
|
_audioSystem.InternalStop(_id, _sessions);
|
|
}
|
|
}
|
|
|
|
/// <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
|
|
{
|
|
Identifier = id
|
|
};
|
|
|
|
if (sessions == null)
|
|
RaiseNetworkEvent(msg);
|
|
else
|
|
{
|
|
foreach (var session in sessions)
|
|
{
|
|
RaiseNetworkEvent(msg, session.ConnectedClient);
|
|
}
|
|
}
|
|
}
|
|
|
|
private uint CacheIdentifier()
|
|
{
|
|
return unchecked(_streamIndex++);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public int DefaultSoundRange => AudioDistanceRange;
|
|
|
|
/// <inheritdoc />
|
|
public int OcclusionCollisionMask { get; set; }
|
|
|
|
/// <inheritdoc />
|
|
public IPlayingAudioStream Play(Filter playerFilter, string filename, AudioParams? audioParams = null)
|
|
{
|
|
var id = CacheIdentifier();
|
|
var msg = new PlayAudioGlobalMessage
|
|
{
|
|
FileName = filename,
|
|
AudioParams = audioParams ?? AudioParams.Default,
|
|
Identifier = id
|
|
};
|
|
|
|
RaiseNetworkEvent(msg, playerFilter);
|
|
|
|
return new AudioSourceServer(this, id, playerFilter.Recipients.ToArray());
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
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;
|
|
|
|
var id = CacheIdentifier();
|
|
|
|
var msg = new PlayAudioEntityMessage
|
|
{
|
|
FileName = filename,
|
|
Coordinates = entity.Transform.Coordinates,
|
|
EntityUid = entity.Uid,
|
|
AudioParams = audioParams ?? AudioParams.Default,
|
|
Identifier = id,
|
|
};
|
|
|
|
// We clone the filter here as to not modify the original instance.
|
|
if (range > 0.0f)
|
|
playerFilter = playerFilter.Clone().AddInRange(entity.Transform.MapPosition, range);
|
|
|
|
RaiseNetworkEvent(msg, playerFilter);
|
|
|
|
return new AudioSourceServer(this, id, playerFilter.Recipients.ToArray());
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
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;
|
|
|
|
var id = CacheIdentifier();
|
|
var msg = new PlayAudioPositionalMessage
|
|
{
|
|
FileName = filename,
|
|
Coordinates = coordinates,
|
|
AudioParams = audioParams ?? AudioParams.Default,
|
|
Identifier = id
|
|
};
|
|
|
|
// We clone the filter here as to not modify the original instance.
|
|
if (range > 0.0f)
|
|
playerFilter = playerFilter.Clone().AddInRange(coordinates.ToMap(EntityManager), range);
|
|
|
|
RaiseNetworkEvent(msg, playerFilter);
|
|
|
|
return new AudioSourceServer(this, id, playerFilter.Recipients.ToArray());
|
|
}
|
|
}
|
|
}
|