diff --git a/Content.Shared/Body/Systems/SharedBodySystem.Body.cs b/Content.Shared/Body/Systems/SharedBodySystem.Body.cs index 74a202386e..d61ba1b7eb 100644 --- a/Content.Shared/Body/Systems/SharedBodySystem.Body.cs +++ b/Content.Shared/Body/Systems/SharedBodySystem.Body.cs @@ -25,63 +25,11 @@ public partial class SharedBodySystem private void InitializeBody() { - // Body here to handle root body parts. - SubscribeLocalEvent(OnBodyInserted); - SubscribeLocalEvent(OnBodyRemoved); - SubscribeLocalEvent(OnBodyInit); SubscribeLocalEvent(OnBodyMapInit); SubscribeLocalEvent(OnBodyCanDrag); } - private void OnBodyInserted(EntityUid uid, BodyComponent component, EntInsertedIntoContainerMessage args) - { - // Root body part? - var slotId = args.Container.ID; - - if (slotId != BodyRootContainerId) - return; - - var entity = args.Entity; - - if (TryComp(entity, out BodyPartComponent? childPart)) - { - AddPart(uid, entity, slotId, childPart); - RecursiveBodyUpdate(entity, uid, childPart); - } - - if (TryComp(entity, out OrganComponent? organ)) - { - AddOrgan(entity, uid, uid, organ); - } - } - - private void OnBodyRemoved(EntityUid uid, BodyComponent component, EntRemovedFromContainerMessage args) - { - // TODO: lifestage shenanigans - if (TerminatingOrDeleted(uid)) - return; - - // Root body part? - var slotId = args.Container.ID; - - if (slotId != BodyRootContainerId) - return; - - var entity = args.Entity; - - if (TryComp(entity, out BodyPartComponent? childPart)) - { - RemovePart(uid, entity, slotId, childPart); - RecursiveBodyUpdate(entity, null, childPart); - } - - if (TryComp(entity, out OrganComponent? organ)) - { - RemoveOrgan(entity, uid, organ); - } - } - private void OnBodyInit(EntityUid bodyId, BodyComponent body, ComponentInit args) { // Setup the initial container. @@ -229,6 +177,8 @@ public partial class SharedBodySystem yield break; } + yield return (body.RootContainer.ContainedEntity.Value, rootPart); + foreach (var child in GetBodyPartChildren(body.RootContainer.ContainedEntity.Value, rootPart)) { yield return child; diff --git a/Content.Shared/Body/Systems/SharedBodySystem.Organs.cs b/Content.Shared/Body/Systems/SharedBodySystem.Organs.cs index 6e392b9892..ee4485f32a 100644 --- a/Content.Shared/Body/Systems/SharedBodySystem.Organs.cs +++ b/Content.Shared/Body/Systems/SharedBodySystem.Organs.cs @@ -9,26 +9,50 @@ namespace Content.Shared.Body.Systems; public partial class SharedBodySystem { - private void AddOrgan(EntityUid uid, EntityUid bodyUid, EntityUid parentPartUid, OrganComponent component) + private void InitializeOrgans() { - component.Body = bodyUid; - RaiseLocalEvent(uid, new AddedToPartEvent(parentPartUid)); - - if (component.Body != null) - RaiseLocalEvent(uid, new AddedToPartInBodyEvent(component.Body.Value, parentPartUid)); - - Dirty(uid, component); + SubscribeLocalEvent(OnOrganInserted); + SubscribeLocalEvent(OnOrganRemoved); } - private void RemoveOrgan(EntityUid uid, EntityUid parentPartUid, OrganComponent component) + private void OnOrganInserted(EntityUid uid, OrganComponent component, EntGotInsertedIntoContainerMessage args) { - RaiseLocalEvent(uid, new RemovedFromPartEvent(parentPartUid)); + // No recursive updates for these as you can't insert organs into organsTM. + var parentUid = args.Container.Owner; - if (component.Body != null) + if (HasComp(parentUid)) { - RaiseLocalEvent(uid, new RemovedFromPartInBodyEvent(component.Body.Value, parentPartUid)); + component.Body = parentUid; + Dirty(uid, component); } + // Organ inserted into body part. + if (TryComp(parentUid, out BodyPartComponent? partComp)) + { + RaiseLocalEvent(uid, new AddedToPartEvent(parentUid)); + + if (partComp.Body != null) + { + component.Body = partComp.Body; + RaiseLocalEvent(uid, new AddedToPartInBodyEvent(partComp.Body.Value, parentUid)); + Dirty(uid, component); + } + } + } + + private void OnOrganRemoved(EntityUid uid, OrganComponent component, EntGotRemovedFromContainerMessage args) + { + // Lifestage shenanigans. + if (component.Body != null && TerminatingOrDeleted(component.Body.Value)) + return; + + if (HasComp(args.Container.Owner)) + RaiseLocalEvent(uid, new RemovedFromPartEvent(args.Container.Owner)); + + if (component.Body == null) + return; + + RaiseLocalEvent(uid, new RemovedFromPartInBodyEvent(component.Body.Value, args.Container.Owner)); component.Body = null; Dirty(uid, component); } diff --git a/Content.Shared/Body/Systems/SharedBodySystem.Parts.cs b/Content.Shared/Body/Systems/SharedBodySystem.Parts.cs index 463a4b7661..75a52ddbc5 100644 --- a/Content.Shared/Body/Systems/SharedBodySystem.Parts.cs +++ b/Content.Shared/Body/Systems/SharedBodySystem.Parts.cs @@ -19,89 +19,99 @@ public partial class SharedBodySystem // TODO: This doesn't handle comp removal on child ents. // If you modify this also see the Body partial for root parts. - SubscribeLocalEvent(OnBodyPartInserted); - SubscribeLocalEvent(OnBodyPartRemoved); + SubscribeLocalEvent(OnBodyPartInserted); + SubscribeLocalEvent(OnBodyPartRemoved); } - private void OnBodyPartInserted(EntityUid uid, BodyPartComponent component, EntInsertedIntoContainerMessage args) + private void OnBodyPartInserted(EntityUid uid, BodyPartComponent component, EntGotInsertedIntoContainerMessage args) { - // Body part inserted into another body part. - var entity = args.Entity; - var slotId = args.Container.ID; + var parentUid = args.Container.Owner; + if (HasComp(parentUid)) + { + AddPart(parentUid, uid, GetPartSlotContainerId(args.Container.ID), component); + RecursiveBodyUpdate(uid, parentUid, component); + } + + // Body part inserted into another body part. + if (TryComp(parentUid, out BodyPartComponent? partComp)) + { + if (partComp.Body == null) + return; + + AddPart(partComp.Body.Value, uid, GetPartSlotContainerId(args.Container.ID), component); + RecursiveBodyUpdate(uid, partComp.Body, component); + } + } + + private void OnBodyPartRemoved(EntityUid uid, BodyPartComponent component, EntGotRemovedFromContainerMessage args) + { if (component.Body != null) { - if (TryComp(entity, out BodyPartComponent? childPart)) - { - AddPart(component.Body.Value, entity, slotId, childPart); - RecursiveBodyUpdate(entity, component.Body.Value, childPart); - } + // Lifestage shenanigans. + if (TerminatingOrDeleted(component.Body.Value)) + return; - if (TryComp(entity, out OrganComponent? organ)) - { - AddOrgan(entity, component.Body.Value, uid, organ); - } - } - } - - private void OnBodyPartRemoved(EntityUid uid, BodyPartComponent component, EntRemovedFromContainerMessage args) - { - // TODO: lifestage shenanigans - if (TerminatingOrDeleted(uid)) - return; - - // Body part removed from another body part. - var entity = args.Entity; - var slotId = args.Container.ID; - - if (TryComp(entity, out BodyPartComponent? childPart) && childPart.Body != null) - { - RemovePart(childPart.Body.Value, entity, slotId, childPart); - RecursiveBodyUpdate(entity, null, childPart); - } - - if (TryComp(entity, out OrganComponent? organ)) - { - RemoveOrgan(entity, uid, organ); + RemovePart(component.Body.Value, uid, GetPartSlotContainerId(args.Container.ID), component); + RecursiveBodyUpdate(uid, null, component); } } + /// + /// Updates body parts recursively for a particular entity, including itself. + /// private void RecursiveBodyUpdate(EntityUid uid, EntityUid? bodyUid, BodyPartComponent component) { + // Recursively iterate all child parts and organs and ensure their body refs are updated. foreach (var children in GetBodyPartChildren(uid, component)) { - if (children.Component.Body != bodyUid) + if (children.Component.Body == bodyUid) + continue; + + // Raise the body part change event if relevant. + if (Containers.TryGetContainingContainer(children.Id, out var childContainer)) { - children.Component.Body = bodyUid; - Dirty(children.Id, children.Component); + var slotId = GetPartSlotContainerId(childContainer.ID); - foreach (var slotId in children.Component.Organs.Keys) + if (bodyUid != null) { - var organContainerId = GetOrganContainerId(slotId); + AddPart(bodyUid.Value, children.Id, slotId, children.Component); + } + else if (component.Body != null) + { + RemovePart(component.Body.Value, children.Id, slotId, children.Component); + } + } - if (!Containers.TryGetContainer(children.Id, organContainerId, out var container)) - continue; + children.Component.Body = bodyUid; + Dirty(children.Id, children.Component); - foreach (var organ in container.ContainedEntities) + foreach (var slotId in children.Component.Organs.Keys) + { + var organContainerId = GetOrganContainerId(slotId); + + if (!Containers.TryGetContainer(children.Id, organContainerId, out var container)) + continue; + + foreach (var organ in container.ContainedEntities) + { + if (TryComp(organ, out OrganComponent? organComp)) { - if (TryComp(organ, out OrganComponent? organComp)) + var oldBody = organComp.Body; + organComp.Body = bodyUid; + + if (bodyUid != null) { - var oldBody = organComp.Body; - organComp.Body = bodyUid; - - if (bodyUid != null) - { - var ev = new AddedToPartInBodyEvent(bodyUid.Value, children.Id); - RaiseLocalEvent(organ, ev); - } - else if (oldBody != null) - { - var ev = new RemovedFromPartInBodyEvent(oldBody.Value, children.Id); - RaiseLocalEvent(organ, ev); - } - - Dirty(organ, organComp); + var ev = new AddedToPartInBodyEvent(bodyUid.Value, children.Id); + RaiseLocalEvent(organ, ev); } + else if (oldBody != null) + { + var ev = new RemovedFromPartInBodyEvent(oldBody.Value, children.Id); + RaiseLocalEvent(organ, ev); + } + + Dirty(organ, organComp); } } } @@ -116,9 +126,8 @@ public partial class SharedBodySystem BodyComponent? bodyComp = null) { DebugTools.AssertOwner(partUid, component); - Dirty(partUid, component); component.Body = bodyUid; - + Dirty(partUid, component); var ev = new BodyPartAddedEvent(slotId, component); RaiseLocalEvent(bodyUid, ref ev); @@ -134,8 +143,8 @@ public partial class SharedBodySystem { DebugTools.AssertOwner(partUid, component); Resolve(bodyUid, ref bodyComp, false); - Dirty(partUid, component); component.Body = null; + Dirty(partUid, component); var ev = new BodyPartRemovedEvent(slotId, component); RaiseLocalEvent(bodyUid, ref ev); @@ -547,15 +556,13 @@ public partial class SharedBodySystem } /// - /// Returns all body part components for this entity including itself. + /// Returns all body part components for this entity not including itself. /// public IEnumerable<(EntityUid Id, BodyPartComponent Component)> GetBodyPartChildren(EntityUid partId, BodyPartComponent? part = null) { if (!Resolve(partId, ref part, false)) yield break; - yield return (partId, part); - foreach (var slotId in part.Children.Keys) { var containerSlotId = GetPartSlotContainerId(slotId); @@ -567,6 +574,8 @@ public partial class SharedBodySystem if (!TryComp(containedEnt, out BodyPartComponent? childPart)) continue; + yield return (containedEnt, childPart); + foreach (var value in GetBodyPartChildren(containedEnt, childPart)) { yield return value; @@ -629,6 +638,9 @@ public partial class SharedBodySystem return false; } + if (childId == parentId) + return true; + foreach (var (foundId, _) in GetBodyPartChildren(parentId, parent)) { if (foundId == childId) diff --git a/Content.Shared/Body/Systems/SharedBodySystem.cs b/Content.Shared/Body/Systems/SharedBodySystem.cs index 431503c96e..c10b3e9fca 100644 --- a/Content.Shared/Body/Systems/SharedBodySystem.cs +++ b/Content.Shared/Body/Systems/SharedBodySystem.cs @@ -39,6 +39,7 @@ public abstract partial class SharedBodySystem : EntitySystem base.Initialize(); InitializeBody(); + InitializeOrgans(); InitializeParts(); }