using System.Collections.Generic; using System.Linq; using Robust.Server.Player; using Robust.Shared.Enums; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Timing; using Robust.Shared.Utility; namespace Robust.Server.GameObjects { /// /// An entity system that displays temporary effects to the user /// public sealed class EffectSystem : EntitySystem { [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly IPlayerManager _playerManager = default!; /// /// Priority queue sorted by how soon the effect will die, we remove messages from the front of the queue during update until caught up /// private readonly PriorityQueue _currentEffects = new(new EffectMessageComparer()); /// /// Creates a particle effect and sends it to clients. /// /// /// Session to be excluded for prediction public void CreateParticle(EffectSystemMessage effect, IPlayerSession? excludedSession = null) { _currentEffects.Add(effect); //For now we will use this which sends to ALL clients //TODO: Client bubbling foreach (var player in _playerManager.ServerSessions) { if (player.Status != SessionStatus.InGame || player == excludedSession) continue; RaiseNetworkEvent(effect, player.ConnectedClient); } } public override void Update(float frameTime) { //Take elements from front of priority queue until they are old while (_currentEffects.Count != 0 && _currentEffects.Peek().DeathTime < _timing.CurTime) { _currentEffects.Take(); } } /// /// Comparer that keeps the device dictionary sorted by powernet priority /// public sealed class EffectMessageComparer : IComparer { public int Compare(EffectSystemMessage? x, EffectSystemMessage? y) { if (x == null && y == null) { return 0; } if (y == null) { return 1; } if (x == null) { return -1; } return y.DeathTime.CompareTo(x.DeathTime); } } //TODO: Send all current effects to new clients on login //TODO: Send effects only to relevant client bubbles } }