using Content.Server.GameObjects.Components.NodeContainer.Nodes; using Robust.Shared.ViewVariables; using System.Collections.Generic; namespace Content.Server.GameObjects.Components.NodeContainer.NodeGroups { /// /// Maintains a collection of s, and performs operations requiring a list of /// all connected s. /// public interface INodeGroup { public IReadOnlyList Nodes { get; } void AddNode(Node node); void RemoveNode(Node node); void CombineGroup(INodeGroup newGroup); void BeforeCombine(); void AfterCombine(); void BeforeRemakeSpread(); void AfterRemakeSpread(); } [NodeGroup(NodeGroupID.Default)] public class BaseNodeGroup : INodeGroup { [ViewVariables] public IReadOnlyList Nodes => _nodes; private readonly List _nodes = new List(); [ViewVariables] public int NodeCount => Nodes.Count; public static readonly INodeGroup NullGroup = new NullNodeGroup(); public void AddNode(Node node) { _nodes.Add(node); OnAddNode(node); } public void RemoveNode(Node node) { _nodes.Remove(node); OnRemoveNode(node); RemakeGroup(); } public void CombineGroup(INodeGroup newGroup) { if (newGroup.Nodes.Count < Nodes.Count) { newGroup.CombineGroup(this); return; } BeforeCombine(); newGroup.BeforeCombine(); foreach (var node in Nodes) { node.NodeGroup = newGroup; } AfterCombine(); newGroup.AfterCombine(); } /// /// Causes all s to remake their groups. Called when a is removed /// and may have split a group in two, so multiple new groups may need to be formed. /// private void RemakeGroup() { BeforeRemake(); foreach (var node in Nodes) { node.ClearNodeGroup(); } foreach (var node in Nodes) { if (node.TryAssignGroupIfNeeded()) { node.StartSpreadingGroup(); } } } protected virtual void OnAddNode(Node node) { } protected virtual void OnRemoveNode(Node node) { } protected virtual void BeforeRemake() { } protected virtual void AfterRemake() { } public virtual void BeforeCombine() { } public virtual void AfterCombine() { } public virtual void BeforeRemakeSpread() { } public virtual void AfterRemakeSpread() { } private class NullNodeGroup : INodeGroup { public IReadOnlyList Nodes => _nodes; private readonly List _nodes = new List(); public void AddNode(Node node) { } public void CombineGroup(INodeGroup newGroup) { } public void RemoveNode(Node node) { } public void BeforeCombine() { } public void AfterCombine() { } public void BeforeRemakeSpread() { } public void AfterRemakeSpread() { } } } }