From 140767c2627087cc0bec7b173fe3e2573289f558 Mon Sep 17 00:00:00 2001 From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Date: Fri, 23 Aug 2024 18:29:57 +1000 Subject: [PATCH] Move viewsubscriber to shared + handle eye targets (#5362) * Move viewsubscriber to shared + handle eye targets Need this stuff for AI. * Fix dumb * review --- .../EntitySystems/ViewSubscriberSystem.cs | 5 + .../Components/Eye/ViewSubscriberComponent.cs | 12 -- .../EntitySystems/ViewSubscriberSystem.cs | 128 +++++++++--------- .../Components/Eye/ViewSubscriberComponent.cs | 11 ++ .../GameObjects/Systems/SharedEyeSystem.cs | 48 +++++++ .../Systems/SharedViewSubscriberSystem.cs | 18 +++ 6 files changed, 145 insertions(+), 77 deletions(-) create mode 100644 Robust.Client/GameObjects/EntitySystems/ViewSubscriberSystem.cs delete mode 100644 Robust.Server/GameObjects/Components/Eye/ViewSubscriberComponent.cs create mode 100644 Robust.Shared/GameObjects/Components/Eye/ViewSubscriberComponent.cs create mode 100644 Robust.Shared/GameObjects/Systems/SharedViewSubscriberSystem.cs diff --git a/Robust.Client/GameObjects/EntitySystems/ViewSubscriberSystem.cs b/Robust.Client/GameObjects/EntitySystems/ViewSubscriberSystem.cs new file mode 100644 index 00000000000..1e0d0d97d17 --- /dev/null +++ b/Robust.Client/GameObjects/EntitySystems/ViewSubscriberSystem.cs @@ -0,0 +1,5 @@ +using Robust.Shared.GameObjects; + +namespace Robust.Client.GameObjects; + +public sealed class ViewSubscriberSystem : SharedViewSubscriberSystem; diff --git a/Robust.Server/GameObjects/Components/Eye/ViewSubscriberComponent.cs b/Robust.Server/GameObjects/Components/Eye/ViewSubscriberComponent.cs deleted file mode 100644 index eb078fc7058..00000000000 --- a/Robust.Server/GameObjects/Components/Eye/ViewSubscriberComponent.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Collections.Generic; -using Robust.Shared.GameObjects; -using Robust.Shared.Player; - -namespace Robust.Server.GameObjects -{ - [RegisterComponent] - internal sealed partial class ViewSubscriberComponent : Component - { - internal readonly HashSet SubscribedSessions = new(); - } -} diff --git a/Robust.Server/GameObjects/EntitySystems/ViewSubscriberSystem.cs b/Robust.Server/GameObjects/EntitySystems/ViewSubscriberSystem.cs index 9784d02f30d..6dec7e75a00 100644 --- a/Robust.Server/GameObjects/EntitySystems/ViewSubscriberSystem.cs +++ b/Robust.Server/GameObjects/EntitySystems/ViewSubscriberSystem.cs @@ -1,89 +1,87 @@ using Robust.Shared.GameObjects; using Robust.Shared.Player; -namespace Robust.Server.GameObjects +namespace Robust.Server.GameObjects; + +/// +/// Entity System that handles subscribing and unsubscribing to PVS views. +/// +public sealed class ViewSubscriberSystem : SharedViewSubscriberSystem { + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnViewSubscriberShutdown); + } + /// - /// Entity System that handles subscribing and unsubscribing to PVS views. + /// Subscribes the session to get PVS updates from the point of view of the specified entity. /// - public sealed class ViewSubscriberSystem : EntitySystem + public override void AddViewSubscriber(EntityUid uid, ICommonSession session) { - public override void Initialize() - { - base.Initialize(); - - SubscribeLocalEvent(OnViewSubscriberShutdown); - } - - /// - /// Subscribes the session to get PVS updates from the point of view of the specified entity. - /// - public void AddViewSubscriber(EntityUid uid, ICommonSession session) - { - // If the entity doesn't have the component, it will be added. - var viewSubscriber = EntityManager.EnsureComponent(uid); + // If the entity doesn't have the component, it will be added. + var viewSubscriber = EntityManager.EnsureComponent(uid); - if (viewSubscriber.SubscribedSessions.Contains(session)) - return; // Already subscribed, do nothing else. + if (viewSubscriber.SubscribedSessions.Contains(session)) + return; // Already subscribed, do nothing else. - viewSubscriber.SubscribedSessions.Add(session); - session.ViewSubscriptions.Add(uid); + viewSubscriber.SubscribedSessions.Add(session); + session.ViewSubscriptions.Add(uid); - RaiseLocalEvent(uid, new ViewSubscriberAddedEvent(uid, session), true); - } - - /// - /// Unsubscribes the session from getting PVS updates from the point of view of the specified entity. - /// - public void RemoveViewSubscriber(EntityUid uid, ICommonSession session) - { - if(!EntityManager.TryGetComponent(uid, out ViewSubscriberComponent? viewSubscriber)) - return; // Entity didn't have any subscriptions, do nothing. - - if (!viewSubscriber.SubscribedSessions.Remove(session)) - return; // Session wasn't subscribed, do nothing. - - session.ViewSubscriptions.Remove(uid); - RaiseLocalEvent(uid, new ViewSubscriberRemovedEvent(uid, session), true); - } - - private void OnViewSubscriberShutdown(EntityUid uid, ViewSubscriberComponent component, ComponentShutdown _) - { - foreach (var session in component.SubscribedSessions) - { - session.ViewSubscriptions.Remove(uid); - } - } + RaiseLocalEvent(uid, new ViewSubscriberAddedEvent(uid, session), true); } /// - /// Raised when a session subscribes to an entity's PVS view. + /// Unsubscribes the session from getting PVS updates from the point of view of the specified entity. /// - public sealed class ViewSubscriberAddedEvent : EntityEventArgs + public override void RemoveViewSubscriber(EntityUid uid, ICommonSession session) { - public EntityUid View { get; } - public ICommonSession Subscriber { get; } + if(!EntityManager.TryGetComponent(uid, out Shared.GameObjects.ViewSubscriberComponent? viewSubscriber)) + return; // Entity didn't have any subscriptions, do nothing. + + if (!viewSubscriber.SubscribedSessions.Remove(session)) + return; // Session wasn't subscribed, do nothing. - public ViewSubscriberAddedEvent(EntityUid view, ICommonSession subscriber) + session.ViewSubscriptions.Remove(uid); + RaiseLocalEvent(uid, new ViewSubscriberRemovedEvent(uid, session), true); + } + + private void OnViewSubscriberShutdown(EntityUid uid, ViewSubscriberComponent component, ComponentShutdown _) + { + foreach (var session in component.SubscribedSessions) { - View = view; - Subscriber = subscriber; + session.ViewSubscriptions.Remove(uid); } } +} - /// - /// Raised when a session is unsubscribed from an entity's PVS view. - /// Not raised when sessions are unsubscribed due to the component being removed. - /// - public sealed class ViewSubscriberRemovedEvent : EntityEventArgs +/// +/// Raised when a session subscribes to an entity's PVS view. +/// +public sealed class ViewSubscriberAddedEvent : EntityEventArgs +{ + public EntityUid View { get; } + public ICommonSession Subscriber { get; } + + public ViewSubscriberAddedEvent(EntityUid view, ICommonSession subscriber) { - public EntityUid View { get; } - public ICommonSession Subscriber { get; } + View = view; + Subscriber = subscriber; + } +} - public ViewSubscriberRemovedEvent(EntityUid view, ICommonSession subscriber) - { - View = view; - Subscriber = subscriber; - } +/// +/// Raised when a session is unsubscribed from an entity's PVS view. +/// Not raised when sessions are unsubscribed due to the component being removed. +/// +public sealed class ViewSubscriberRemovedEvent : EntityEventArgs +{ + public EntityUid View { get; } + public ICommonSession Subscriber { get; } + + public ViewSubscriberRemovedEvent(EntityUid view, ICommonSession subscriber) + { + View = view; + Subscriber = subscriber; } } diff --git a/Robust.Shared/GameObjects/Components/Eye/ViewSubscriberComponent.cs b/Robust.Shared/GameObjects/Components/Eye/ViewSubscriberComponent.cs new file mode 100644 index 00000000000..2c732853d94 --- /dev/null +++ b/Robust.Shared/GameObjects/Components/Eye/ViewSubscriberComponent.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; +using Robust.Shared.Player; + +namespace Robust.Shared.GameObjects; + +// Not networked because doesn't do anything on client. +[RegisterComponent] +internal sealed partial class ViewSubscriberComponent : Component +{ + internal readonly HashSet SubscribedSessions = new(); +} diff --git a/Robust.Shared/GameObjects/Systems/SharedEyeSystem.cs b/Robust.Shared/GameObjects/Systems/SharedEyeSystem.cs index 039201ca8dc..2091e271485 100644 --- a/Robust.Shared/GameObjects/Systems/SharedEyeSystem.cs +++ b/Robust.Shared/GameObjects/Systems/SharedEyeSystem.cs @@ -2,11 +2,41 @@ using System.Numerics; using Robust.Shared.IoC; using Robust.Shared.Maths; +using Robust.Shared.Player; namespace Robust.Shared.GameObjects; public abstract class SharedEyeSystem : EntitySystem { + [Dependency] private readonly SharedViewSubscriberSystem _views = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnEyePlayerAttached); + SubscribeLocalEvent(OnEyePlayerDetached); + } + + private void OnEyePlayerAttached(Entity ent, ref PlayerAttachedEvent args) + { + var value = ent.Comp.Target; + + if (value != null && TryComp(ent.Owner, out ActorComponent? actorComp)) + { + _views.AddViewSubscriber(value.Value, actorComp.PlayerSession); + } + } + + private void OnEyePlayerDetached(Entity ent, ref PlayerDetachedEvent args) + { + var value = ent.Comp.Target; + + if (value != null && TryComp(ent.Owner, out ActorComponent? actorComp)) + { + _views.RemoveViewSubscriber(value.Value, actorComp.PlayerSession); + } + } + /// /// Refreshes all values for IEye with the component. /// @@ -74,6 +104,10 @@ public void SetRotation(EntityUid uid, Angle rotation, EyeComponent? eyeComponen eyeComponent.Eye.Rotation = rotation; } + /// + /// Sets the eye component as tracking another entity. + /// Will also add the target to view subscribers so they can leave range and still work with PVS. + /// public void SetTarget(EntityUid uid, EntityUid? value, EyeComponent? eyeComponent = null) { if (!Resolve(uid, ref eyeComponent)) @@ -82,6 +116,20 @@ public void SetTarget(EntityUid uid, EntityUid? value, EyeComponent? eyeComponen if (eyeComponent.Target.Equals(value)) return; + // Automatically handle view subs. + if (TryComp(uid, out ActorComponent? actorComp)) + { + if (value != null) + { + _views.AddViewSubscriber(value.Value, actorComp.PlayerSession); + } + else + { + // Should never be null here + _views.RemoveViewSubscriber(eyeComponent.Target!.Value, actorComp.PlayerSession); + } + } + eyeComponent.Target = value; Dirty(uid, eyeComponent); } diff --git a/Robust.Shared/GameObjects/Systems/SharedViewSubscriberSystem.cs b/Robust.Shared/GameObjects/Systems/SharedViewSubscriberSystem.cs new file mode 100644 index 00000000000..77828075a59 --- /dev/null +++ b/Robust.Shared/GameObjects/Systems/SharedViewSubscriberSystem.cs @@ -0,0 +1,18 @@ +using Robust.Shared.Player; + +namespace Robust.Shared.GameObjects; + +public abstract class SharedViewSubscriberSystem : EntitySystem +{ + // NOOP on client + + /// + /// Subscribes the session to get PVS updates from the point of view of the specified entity. + /// + public virtual void AddViewSubscriber(EntityUid uid, ICommonSession session) {} + + /// + /// Unsubscribes the session from getting PVS updates from the point of view of the specified entity. + /// + public virtual void RemoveViewSubscriber(EntityUid uid, ICommonSession session) {} +}