using System; using Svelto.DataStructures; using Svelto.ECS.Internal; namespace Svelto.ECS { /// /// I eventually realised that, with the ECS design, no form of engines (systems) communication other /// than polling entity components is effective. /// The only purpose of this publisher/consumer model is to let two enginesroots communicate with each other /// through a thread safe ring buffer. /// The engines root A publishes entities. /// The engines root B can consume those entities at any time, as they will be a copy of the original /// entities and won't point directly to the database of the engines root A /// struct EntitiesStreams : IDisposable { internal Consumer GenerateConsumer(string name, uint capacity) where T : unmanaged, _IInternalEntityComponent { var componentId = ComponentTypeID.id; if (_streams.ContainsKey(componentId) == false) _streams[componentId] = new EntityStream(); return (_streams[componentId] as EntityStream).GenerateConsumer(name, capacity); } public Consumer GenerateConsumer(ExclusiveGroupStruct group, string name, uint capacity) where T : unmanaged, _IInternalEntityComponent { var componentId = ComponentTypeID.id; if (_streams.ContainsKey(componentId) == false) _streams[componentId] = new EntityStream(); var typeSafeStream = (EntityStream) _streams[componentId]; return typeSafeStream.GenerateConsumer(group, name, capacity); } internal void PublishEntity(ref T entity, EGID egid) where T : unmanaged, _IInternalEntityComponent { if (_streams.TryGetValue(ComponentTypeID.id, out var typeSafeStream)) (typeSafeStream as EntityStream).PublishEntity(ref entity, egid); else Console.LogDebug($"No Consumers are waiting for this entity to change {typeof(T)}"); } public void Dispose() { foreach (var stream in _streams) stream.value.Dispose(); } public static EntitiesStreams Create() { var stream = new EntitiesStreams(); stream._streams = FasterDictionary.Construct(); return stream; } FasterDictionary _streams; } }