using System; using JetBrains.Annotations; using Robust.Shared.Collections; namespace Robust.Shared.GameObjects { public abstract partial class EntitySystem { private ValueList _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); } /// // [Obsolete("Subscribe to the event by ref instead (EntityEventRefHandler)")] 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); } /// // [Obsolete("Subscribe to the event by ref instead (EntityEventRefHandler)")] private void SubEvent( EventSource src, EntityEventHandler handler, Type[]? before, Type[]? after) where T : notnull { EntityManager.EventBus.SubscribeEvent(src, this, handler, GetType(), before, after); _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.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.Add(new SubBroadcast>(src)); } protected void SubscribeLocalEvent( EntityEventRefHandler handler, Type[]? before = null, Type[]? after = null) where TComp : IComponent where TEvent : notnull { EntityManager.EventBus.SubscribeLocalEvent(handler, GetType(), before, after); _subscriptions.Add(new SubLocal()); } /// // [Obsolete("Subscribe to the event by ref instead (ComponentEventRefHandler)")] 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.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.Add(new SubLocal()); } private void ShutdownSubscriptions() { foreach (var sub in _subscriptions) { sub.Unsubscribe(this, EntityManager.EventBus); } _subscriptions = default; } /// /// 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 : notnull { System.SubscribeLocalEvent(handler, before, after); } /// /// Proxy to /// on the owning system. /// public void SubscribeLocalEvent( ComponentEventRefHandler handler, Type[]? before = null, Type[]? after = null) where TComp : IComponent where TEvent : notnull { System.SubscribeLocalEvent(handler, before, after); } /// /// Proxy to /// on the owning system. /// public void SubscribeLocalEvent( EntityEventRefHandler handler, Type[]? before = null, Type[]? after = null) where TComp : IComponent where TEvent : notnull { System.SubscribeLocalEvent(handler, before, after); } /// /// Register an action to be ran when this entity system is shut down. /// /// /// This can be used by extension methods for /// to unsubscribe from external sources such as CVars. /// /// An action to be ran when the entity system is shut down. public void RegisterUnsubscription(Action action) { System._subscriptions.Add(new SubAction(action)); } } 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(); } } private sealed class SubAction(Action action) : SubBase { public override void Unsubscribe(EntitySystem sys, IEventBus bus) { action(); } } } }