using System.Collections.Generic; namespace Encompass { internal abstract class TypedMessageStore { public abstract void ProcessDelayedMessages(double dilatedDelta, double realtimeDelta); public abstract void Clear(); } internal class TypedMessageStore : TypedMessageStore where TMessage : struct, IMessage { private readonly List _indices = new List(); private readonly TMessage[] _store = new TMessage[128]; private readonly List<(TMessage, double)> _delayedStore = new List<(TMessage, double)>(128); private readonly List<(TMessage, double)> _delayedStoreIgnoringTimeDilation = new List<(TMessage, double)>(128); private readonly Dictionary> _entityToIndices = new Dictionary>(); private readonly IDManager _idManager = new IDManager(); public override void ProcessDelayedMessages(double dilatedDelta, double realtimeDelta) { for (var i = _delayedStore.Count - 1; i >= 0; i--) { var (message, time) = _delayedStore[i]; var updatedTime = time - dilatedDelta; if (updatedTime <= 0) { Add(message); _delayedStore.RemoveAt(i); } else { _delayedStore[i] = (message, updatedTime); } } for (var i = _delayedStoreIgnoringTimeDilation.Count - 1; i >= 0; i--) { var (message, time) = _delayedStoreIgnoringTimeDilation[i]; var updatedTime = time - realtimeDelta; if (updatedTime <= 0) { Add(message); _delayedStoreIgnoringTimeDilation.RemoveAt(i); } else { _delayedStoreIgnoringTimeDilation[i] = (message, updatedTime); } } } public void Add(in TMessage message) { var index = _idManager.NextID(); _indices.Add(index); _store[index] = message; if (message is IHasEntity entityMessage) { var entityID = entityMessage.Entity.ID; if (!_entityToIndices.ContainsKey(entityID)) { _entityToIndices.Add(entityID, new HashSet()); } _entityToIndices[entityID].Add(index); } } public void Add(in TMessage message, double time) { _delayedStore.Add((message, time)); } public void AddIgnoringTimeDilation(in TMessage message, double time) { _delayedStoreIgnoringTimeDilation.Add((message, time)); } public TMessage First() { return _store[_indices[0]]; } public bool Any() { return _indices.Count > 0; } public IEnumerable All() { foreach (var index in _indices) { yield return _store[index]; } } public IEnumerable WithEntity(int entityID) { if (_entityToIndices.ContainsKey(entityID)) { foreach (var index in _entityToIndices[entityID]) { yield return _store[index]; } } } public bool SomeWithEntity(int entityID) { return _entityToIndices.ContainsKey(entityID) && _entityToIndices[entityID].Count > 0; } public override void Clear() { _indices.Clear(); foreach (var set in _entityToIndices.Values) { set.Clear(); } } } }