using JetBrains.Annotations; using Robust.Shared.Utility; namespace Content.Shared.Body; public sealed partial class OrganRelationSystem : EntitySystem { [Dependency] private EntityQuery _child; [Dependency] private EntityQuery _parent; public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnParentShutdown); SubscribeLocalEvent(OnChildShutdown); } private void OnChildShutdown(Entity ent, ref ComponentShutdown args) { // Parent shut down before the child. if (ent.Comp.Parent is not { } parentUid || !_parent.TryComp(parentUid, out var parentComp)) return; parentComp.Children.Remove(ent); Dirty(parentUid, parentComp); } private void OnParentShutdown(Entity ent, ref ComponentShutdown args) { if (ent.Comp.Children.Count == 0) return; foreach (var childUid in ent.Comp.Children) { // Child shut down before the parent. if (!_child.TryComp(childUid, out var childComp)) continue; childComp.Parent = null; Dirty(childUid, childComp); } } /// /// Associates a parent organ and a child organ. /// [PublicAPI] public void Relate(Entity parent, Entity child) { if (!_parent.Resolve(parent, ref parent.Comp) || !_child.Resolve(child, ref child.Comp)) return; DebugTools.Assert(child.Comp.Parent == null); parent.Comp.Children.Add(child); Dirty(parent, parent.Comp); child.Comp.Parent = parent; Dirty(child, child.Comp); } /// /// Breaks the relationship between a child orphan and its parent. /// [PublicAPI] public void Orphan(Entity child) { if (!_child.Resolve(child, ref child.Comp)) return; if (child.Comp.Parent is not { } parentUid) return; child.Comp.Parent = null; Dirty(child, child.Comp); var parentComp = _parent.Comp(parentUid); parentComp.Children.Remove(child); Dirty(parentUid, parentComp); } /// /// Enumerates all parents of a child organ recursively. /// [PublicAPI] public IEnumerable> AllParents(Entity child) { if (!_child.Resolve(child, ref child.Comp)) yield break; while (child.Comp?.Parent is { } parent) { yield return (parent, _parent.Comp(parent)); if (!_child.TryGetComponent(parent, out var parentChild)) yield break; child = (parent, parentChild); } } /// /// Enumerates all children of a parent organ recursively. /// [PublicAPI] public IEnumerable> AllChildren(Entity parent) { if (!_parent.Resolve(parent, ref parent.Comp, false)) yield break; foreach (var child in parent.Comp.Children) { yield return (child, _child.Comp(child)); foreach (var childChild in AllChildren(child)) { yield return childChild; } } } }