#nullable enable using System.Collections.Generic; using Content.Server.NodeContainer.EntitySystems; using Content.Server.NodeContainer.NodeGroups; using Robust.Shared.GameObjects; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.ViewVariables; namespace Content.Server.NodeContainer.Nodes { /// /// Organizes themselves into distinct s with other s /// that they can "reach" and have the same . /// [ImplicitDataDefinitionForInheritors] public abstract class Node { /// /// An ID used as a criteria for combining into groups. Determines which /// implementation is used as a group, detailed in . /// [ViewVariables] [DataField("nodeGroupID")] public NodeGroupID NodeGroupID { get; private set; } = NodeGroupID.Default; /// /// The node group this node is a part of. /// [ViewVariables] public INodeGroup? NodeGroup; /// /// The entity that owns this node via its . /// [ViewVariables] public IEntity Owner { get; private set; } = default!; /// /// If this node should be considered for connection by other nodes. /// public bool Connectable => !Deleting && Anchored; protected bool Anchored => !NeedAnchored || Owner.Transform.Anchored; [ViewVariables(VVAccess.ReadWrite)] [DataField("needAnchored")] private bool NeedAnchored { get; } = true; /// /// Prevents a node from being used by other nodes while midway through removal. /// public bool Deleting; /// /// All compatible nodes that are reachable by this node. /// Effectively, active connections out of this node. /// public readonly HashSet ReachableNodes = new(); internal int FloodGen; internal int UndirectGen; internal bool FlaggedForFlood; internal int NetId; /// /// Name of this node on the owning . /// public string Name = default!; /// /// Invoked when the owning is initialized. /// /// The owning entity. public virtual void Initialize(IEntity owner) { Owner = owner; } /// /// Invoked when the owning is started. /// public virtual void OnContainerStartup() { EntitySystem.Get().QueueReflood(this); } /// /// Immediately create a single-node node group for this node if it does not have one yet. /// /// /// This can be useful for nodes like pipes /// that need immediate access to their node group to set parameters like node volume. /// The node group created by this function (if necessary) will still update and form new, /// merged groups later if necessary. /// Set parameters like pipe net volume should then be transferred/merged there. /// public void CreateSingleNetImmediate() { EntitySystem.Get().CreateSingleNetImmediate(this); } public void AnchorUpdate() { if (Anchored) { EntitySystem.Get().QueueReflood(this); } else { EntitySystem.Get().QueueNodeRemove(this); } } /// /// Called when the anchored state of the owning entity changes. /// public virtual void AnchorStateChanged() { } /// /// Called after the parent node group has been rebuilt. /// public virtual void OnPostRebuild() { } /// /// Called when the owning is shut down. /// public virtual void OnContainerShutdown() { Deleting = true; EntitySystem.Get().QueueNodeRemove(this); } /// /// How this node will attempt to find other reachable s to group with. /// Returns a set of s to consider grouping with. Should not return this current . /// /// /// /// The set of nodes returned can be asymmetrical /// (meaning that it can return other nodes whose does not return this node). /// If this is used, creation of a new node may not correctly merge networks unless both sides /// of this asymmetric relation are made to manually update with . /// /// public abstract IEnumerable GetReachableNodes(); } }