using System; using System.Collections.Generic; using JetBrains.Annotations; namespace Robust.Shared.GameObjects { public abstract partial class EntitySystem { private List? _subscriptions; /// /// A handle to allow subscription on this entity system's behalf. /// protected Subscriptions Subs { get; } // NOTE: EntityEventHandler and EntitySessionEventHandler CANNOT BE ORDERED BETWEEN EACH OTHER. // EntityEventRefHandler and EntityEventHandler can be, however. They're essentially the same. protected void SubscribeNetworkEvent( EntityEventHandler handler, Type[]? before = null, Type[]? after = null) where T : notnull { SubEvent(EventSource.Network, handler, before, after); } protected void SubscribeLocalEvent( EntityEventHandler handler, Type[]? before = null, Type[]? after = null) where T : notnull { SubEvent(EventSource.Local, handler, before, after); } protected void SubscribeLocalEvent( EntityEventRefHandler handler, Type[]? before = null, Type[]? after = null) where T : notnull { SubEvent(EventSource.Local, handler, before, after); } protected void SubscribeAllEvent( EntityEventHandler handler, Type[]? before = null, Type[]? after = null) where T : notnull { SubEvent(EventSource.All, handler, before, after); } protected void SubscribeNetworkEvent( EntitySessionEventHandler handler, Type[]? before = null, Type[]? after = null) where T : notnull { SubSessionEvent(EventSource.Network, handler, before, after); } protected void SubscribeLocalEvent( EntitySessionEventHandler handler, Type[]? before = null, Type[]? after = null) where T : notnull { SubSessionEvent(EventSource.Local, handler, before, after); } protected void SubscribeAllEvent( EntitySessionEventHandler handler, Type[]? before = null, Type[]? after = null) where T : notnull { SubSessionEvent(EventSource.All, handler, before, after); } private void SubEvent( EventSource src, EntityEventHandler handler, Type[]? before, Type[]? after) where T : notnull { EntityManager.EventBus.SubscribeEvent(src, this, handler, GetType(), before, after); _subscriptions ??= new(); _subscriptions.Add(new SubBroadcast(src)); } private void SubEvent( EventSource src, EntityEventRefHandler handler, Type[]? before, Type[]? after) where T : notnull { EntityManager.EventBus.SubscribeEvent(src, this, handler, GetType(), before, after); _subscriptions ??= new(); _subscriptions.Add(new SubBroadcast(src)); } private void SubSessionEvent( EventSource src, EntitySessionEventHandler handler, Type[]? before, Type[]? after) where T : notnull { EntityManager.EventBus.SubscribeSessionEvent(src, this, handler, GetType(), before, after); _subscriptions ??= new(); _subscriptions.Add(new SubBroadcast>(src)); } protected void SubscribeLocalEvent( ComponentEventHandler handler, Type[]? before = null, Type[]? after = null) where TComp : IComponent where TEvent : notnull { EntityManager.EventBus.SubscribeLocalEvent(handler, GetType(), before, after); _subscriptions ??= new(); _subscriptions.Add(new SubLocal()); } protected void SubscribeLocalEvent( ComponentEventRefHandler handler, Type[]? before = null, Type[]? after = null) where TComp : IComponent where TEvent : notnull { EntityManager.EventBus.SubscribeLocalEvent(handler, GetType(), before, after); _subscriptions ??= new(); _subscriptions.Add(new SubLocal()); } private void ShutdownSubscriptions() { if (_subscriptions == null) return; foreach (var sub in _subscriptions) { sub.Unsubscribe(this, EntityManager.EventBus); } _subscriptions = null; } /// /// API class to allow registering on an EntitySystem's behalf. /// Intended to support creation of boilerplate-reduction-methods /// that need to subscribe stuff on an entity system. /// [PublicAPI] public sealed class Subscriptions { public EntitySystem System { get; } internal Subscriptions(EntitySystem system) { System = system; } // Intended for helper methods, so minimal API. public void SubEvent( EventSource src, EntityEventHandler handler, Type[]? before = null, Type[]? after = null) where T : notnull { System.SubEvent(src, handler, before, after); } public void SubSessionEvent( EventSource src, EntitySessionEventHandler handler, Type[]? before = null, Type[]? after = null) where T : notnull { System.SubSessionEvent(src, handler, before, after); } public void SubscribeLocalEvent( ComponentEventHandler handler, Type[]? before = null, Type[]? after = null) where TComp : IComponent where TEvent : EntityEventArgs { System.SubscribeLocalEvent(handler, before, after); } } private abstract class SubBase { public abstract void Unsubscribe(EntitySystem sys, IEventBus bus); } private sealed class SubBroadcast : SubBase where T : notnull { private readonly EventSource _source; public SubBroadcast(EventSource source) { _source = source; } public override void Unsubscribe(EntitySystem sys, IEventBus bus) { bus.UnsubscribeEvent(_source, sys); } } private sealed class SubLocal : SubBase where TComp : IComponent where TBase : notnull { public override void Unsubscribe(EntitySystem sys, IEventBus bus) { bus.UnsubscribeLocalEvent(); } } } }