diff --git a/Content.Client/GameObjects/Components/Body/Mechanism/MechanismComponent.cs b/Content.Client/GameObjects/Components/Body/Mechanism/MechanismComponent.cs index 0c80dbccf1..fed6fb82e0 100644 --- a/Content.Client/GameObjects/Components/Body/Mechanism/MechanismComponent.cs +++ b/Content.Client/GameObjects/Components/Body/Mechanism/MechanismComponent.cs @@ -11,9 +11,9 @@ namespace Content.Client.GameObjects.Components.Body.Mechanism [ComponentReference(typeof(IMechanism))] public class MechanismComponent : SharedMechanismComponent { - protected override void OnPartAdd(IBodyPart? old, IBodyPart current) + protected override void OnAddedToPart() { - base.OnPartAdd(old, current); + base.OnAddedToPart(); if (Owner.TryGetComponent(out ISpriteComponent? sprite)) { @@ -21,9 +21,9 @@ namespace Content.Client.GameObjects.Components.Body.Mechanism } } - protected override void OnPartRemove(IBodyPart old) + protected override void OnRemovedFromPart(IBodyPart old) { - base.OnPartRemove(old); + base.OnRemovedFromPart(old); if (Owner.TryGetComponent(out ISpriteComponent? sprite)) { diff --git a/Content.Server/GameObjects/Components/Body/MechanismComponent.cs b/Content.Server/GameObjects/Components/Body/MechanismComponent.cs index 10629b48f5..acd65c616f 100644 --- a/Content.Server/GameObjects/Components/Body/MechanismComponent.cs +++ b/Content.Server/GameObjects/Components/Body/MechanismComponent.cs @@ -158,9 +158,9 @@ namespace Content.Server.GameObjects.Components.Body } } - protected override void OnPartAdd(IBodyPart? old, IBodyPart current) + protected override void OnAddedToPart() { - base.OnPartAdd(old, current); + base.OnAddedToPart(); if (Owner.TryGetComponent(out SpriteComponent? sprite)) { @@ -168,9 +168,9 @@ namespace Content.Server.GameObjects.Components.Body } } - protected override void OnPartRemove(IBodyPart old) + protected override void OnRemovedFromPart(IBodyPart old) { - base.OnPartRemove(old); + base.OnRemovedFromPart(old); if (Owner.TryGetComponent(out SpriteComponent? sprite)) { diff --git a/Content.Shared/GameObjects/Components/Body/Behavior/IMechanismBehavior.cs b/Content.Shared/GameObjects/Components/Body/Behavior/IMechanismBehavior.cs index 64415689bd..893d8055aa 100644 --- a/Content.Shared/GameObjects/Components/Body/Behavior/IMechanismBehavior.cs +++ b/Content.Shared/GameObjects/Components/Body/Behavior/IMechanismBehavior.cs @@ -15,5 +15,55 @@ namespace Content.Shared.GameObjects.Components.Body.Behavior IMechanism? Mechanism { get; } void Update(float frameTime); + + /// + /// Called when the containing is attached to a + /// . + /// For instance, attaching a head with a brain inside to a body. + /// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY SYSTEM CODE! + /// + void AddedToBody(); + + /// + /// Called when the parent is + /// added into a that is not attached to a + /// . + /// For instance, adding a brain to a dismembered head. + /// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY SYSTEM CODE! + /// + void AddedToPart(); + + /// + /// Called when the parent is removed from a + /// . + /// For instance, removing a head with a brain inside from a body. + /// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY SYSTEM CODE! + /// + void RemovedFromBody(IBody old); + + /// + /// Called when the parent is + /// removed from a that is not attached to a + /// . + /// For instance, removing a brain from a dismembered head. + /// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY SYSTEM CODE! + /// + void RemovedFromPart(IBodyPart old); + + /// + /// Called when the parent is added to a + /// that is attached to a . + /// For instance, adding a brain to a head that is attached to a body. + /// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY SYSTEM CODE! + /// + void AddedToPartInBody(); + + /// + /// Called when the parent is removed from a + /// that is attached to a . + /// For instance, removing a brain from a head that is attached to a body. + /// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY SYSTEM CODE! + /// + void RemovedFromPartInBody(IBody? oldBody, IBodyPart? oldPart); } } diff --git a/Content.Shared/GameObjects/Components/Body/Behavior/MechanismBehaviorComponent.cs b/Content.Shared/GameObjects/Components/Body/Behavior/MechanismBehaviorComponent.cs index 1ace5e007e..209d9d7910 100644 --- a/Content.Shared/GameObjects/Components/Body/Behavior/MechanismBehaviorComponent.cs +++ b/Content.Shared/GameObjects/Components/Body/Behavior/MechanismBehaviorComponent.cs @@ -15,72 +15,46 @@ namespace Content.Shared.GameObjects.Components.Body.Behavior public abstract void Update(float frameTime); - /// - /// Called when the containing is attached to a - /// . - /// For instance, attaching a head to a body will call this on the brain inside. - /// public void AddedToBody() { OnAddedToBody(); } - /// - /// Called when the parent is - /// added into a . - /// For instance, putting a brain into an empty head. - /// public void AddedToPart() { OnAddedToPart(); } - /// - /// Called when the containing is removed from a - /// . - /// For instance, cutting off ones head will call this on the brain inside. - /// public void RemovedFromBody(IBody old) { OnRemovedFromBody(old); } - /// - /// Called when the parent is - /// removed from a . - /// For instance, taking a brain out of ones head. - /// public void RemovedFromPart(IBodyPart old) { OnRemovedFromPart(old); } - /// - /// Called when the containing is attached to a - /// . - /// For instance, attaching a head to a body will call this on the brain inside. - /// + public void AddedToPartInBody() + { + OnAddedToPart(); + } + + public void RemovedFromPartInBody(IBody? oldBody, IBodyPart? oldPart) + { + OnRemovedFromPartInBody(oldBody, oldPart); + } + protected virtual void OnAddedToBody() { } - /// - /// Called when the parent is - /// added into a . - /// For instance, putting a brain into an empty head. - /// protected virtual void OnAddedToPart() { } - /// - /// Called when the containing is removed from a - /// . - /// For instance, cutting off ones head will call this on the brain inside. - /// protected virtual void OnRemovedFromBody(IBody old) { } - /// - /// Called when the parent is - /// removed from a . - /// For instance, taking a brain out of ones head. - /// protected virtual void OnRemovedFromPart(IBodyPart old) { } + + protected virtual void OnAddedToPartInBody() { } + + protected virtual void OnRemovedFromPartInBody(IBody? oldBody, IBodyPart? oldPart) { } } } diff --git a/Content.Shared/GameObjects/Components/Body/Mechanism/IMechanism.cs b/Content.Shared/GameObjects/Components/Body/Mechanism/IMechanism.cs index 16287138a2..33357d7136 100644 --- a/Content.Shared/GameObjects/Components/Body/Mechanism/IMechanism.cs +++ b/Content.Shared/GameObjects/Components/Body/Mechanism/IMechanism.cs @@ -52,20 +52,55 @@ namespace Content.Shared.GameObjects.Components.Body.Mechanism /// BodyPartCompatibility Compatibility { get; set; } + // TODO BODY Turn these into event listeners so they dont need to be exposed /// - /// Called when the part housing this mechanism is added to a body. - /// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY PART CODE! + /// Called when the containing is attached to a + /// . + /// For instance, attaching a head with a brain inside to a body. + /// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY SYSTEM CODE! /// - /// The previous body, if any. - /// The new body. - void OnBodyAdd(IBody? old, IBody current); + void AddedToBody(); /// - /// Called when the part housing this mechanism is removed from - /// a body. - /// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY PART CODE! + /// Called when the parent is + /// added into a that is not attached to a + /// . + /// For instance, adding a brain to a dismembered head. + /// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY SYSTEM CODE! /// - /// The old body. - void OnBodyRemove(IBody old); + void AddedToPart(); + + /// + /// Called when the parent is removed from a + /// . + /// For instance, removing a head with a brain inside from a body. + /// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY SYSTEM CODE! + /// + void RemovedFromBody(IBody old); + + /// + /// Called when the parent is + /// removed from a that is not attached to a + /// . + /// For instance, removing a brain from a dismembered head. + /// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY SYSTEM CODE! + /// + void RemovedFromPart(IBodyPart old); + + /// + /// Called when the parent is added to a + /// that is attached to a . + /// For instance, adding a brain to a head that is attached to a body. + /// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY SYSTEM CODE! + /// + void AddedToPartInBody(); + + /// + /// Called when the parent is removed from a + /// that is attached to a . + /// For instance, removing a brain from a head that is attached to a body. + /// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY SYSTEM CODE! + /// + void RemovedFromPartInBody(IBody? oldBody, IBodyPart? oldPart); } } diff --git a/Content.Shared/GameObjects/Components/Body/Mechanism/MechanismExtensions.cs b/Content.Shared/GameObjects/Components/Body/Mechanism/MechanismExtensions.cs index 34eaa521eb..3fa8be233a 100644 --- a/Content.Shared/GameObjects/Components/Body/Mechanism/MechanismExtensions.cs +++ b/Content.Shared/GameObjects/Components/Body/Mechanism/MechanismExtensions.cs @@ -16,6 +16,35 @@ namespace Content.Shared.GameObjects.Components.Body.Mechanism body.Parts.Values.Any(p => p.Mechanisms.Any(m => m.Owner.HasComponent())); } + public static IEnumerable GetMechanismBehaviors(this IEntity entity) + { + if (!entity.TryGetBody(out var body)) + { + yield break; + } + + foreach (var part in body.Parts.Values) + foreach (var mechanism in part.Mechanisms) + foreach (var behavior in mechanism.Owner.GetAllComponents()) + { + yield return behavior; + } + } + + public static bool TryGetMechanismBehaviors(this IEntity entity, + [NotNullWhen(true)] out List? behaviors) + { + behaviors = entity.GetMechanismBehaviors().ToList(); + + if (behaviors.Count == 0) + { + behaviors = null; + return false; + } + + return true; + } + public static IEnumerable GetMechanismBehaviors(this IEntity entity) where T : class, IMechanismBehavior { if (!entity.TryGetBody(out var body)) diff --git a/Content.Shared/GameObjects/Components/Body/Mechanism/SharedMechanismComponent.cs b/Content.Shared/GameObjects/Components/Body/Mechanism/SharedMechanismComponent.cs index 2a79091c68..5d41036f22 100644 --- a/Content.Shared/GameObjects/Components/Body/Mechanism/SharedMechanismComponent.cs +++ b/Content.Shared/GameObjects/Components/Body/Mechanism/SharedMechanismComponent.cs @@ -4,6 +4,7 @@ using Content.Shared.GameObjects.Components.Body.Part; using Robust.Shared.GameObjects; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Serialization; +using Robust.Shared.Utility; namespace Content.Shared.GameObjects.Components.Body.Mechanism { @@ -36,13 +37,14 @@ namespace Content.Shared.GameObjects.Components.Body.Mechanism var old = _part; _part = value; + if (old != null) + { + OnRemovedFromPart(old); + } + if (value != null) { - OnPartAdd(old, value); - } - else if (old != null) - { - OnPartRemove(old); + OnAddedToPart(); } } } @@ -86,18 +88,87 @@ namespace Content.Shared.GameObjects.Components.Body.Mechanism serializer.DataField(this, m => m.Compatibility, "compatibility", BodyPartCompatibility.Universal); } - public virtual void OnBodyAdd(IBody? old, IBody current) { } - - public virtual void OnBodyRemove(IBody old) { } - - protected virtual void OnPartAdd(IBodyPart? old, IBodyPart current) + public void AddedToBody() { - Owner.Transform.AttachParent(current.Owner); + DebugTools.AssertNotNull(Body); + + OnAddedToBody(); + + foreach (var behavior in Owner.GetMechanismBehaviors()) + { + behavior.AddedToBody(); + } } - protected virtual void OnPartRemove(IBodyPart old) + public void RemovedFromBody(IBody old) + { + OnRemovedFromBody(old); + + foreach (var behavior in Owner.GetMechanismBehaviors()) + { + behavior.RemovedFromBody(old); + } + } + + public void AddedToPart() + { + DebugTools.AssertNotNull(Part); + + Owner.Transform.AttachParent(Part!.Owner); + OnAddedToPart(); + + foreach (var behavior in Owner.GetMechanismBehaviors()) + { + behavior.AddedToPart(); + } + } + + public void RemovedFromPart(IBodyPart old) { Owner.Transform.AttachToGridOrMap(); + OnRemovedFromPart(old); + + foreach (var behavior in Owner.GetMechanismBehaviors()) + { + behavior.RemovedFromPart(old); + } } + + public void AddedToPartInBody() + { + DebugTools.AssertNotNull(Body); + DebugTools.AssertNotNull(Part); + + Owner.Transform.AttachParent(Part!.Owner); + OnAddedToPartInBody(); + + foreach (var behavior in Owner.GetMechanismBehaviors()) + { + behavior.AddedToPartInBody(); + } + } + + public void RemovedFromPartInBody(IBody? oldBody, IBodyPart? oldPart) + { + Owner.Transform.AttachToGridOrMap(); + OnRemovedFromPartInBody(); + + foreach (var behavior in Owner.GetMechanismBehaviors()) + { + behavior.RemovedFromPartInBody(oldBody, oldPart); + } + } + + protected virtual void OnAddedToBody() { } + + protected virtual void OnRemovedFromBody(IBody old) { } + + protected virtual void OnAddedToPart() { } + + protected virtual void OnRemovedFromPart(IBodyPart old) { } + + protected virtual void OnAddedToPartInBody() { } + + protected virtual void OnRemovedFromPartInBody() { } } } diff --git a/Content.Shared/GameObjects/Components/Body/Part/SharedBodyPartComponent.cs b/Content.Shared/GameObjects/Components/Body/Part/SharedBodyPartComponent.cs index efcca24342..06ef4ddbb9 100644 --- a/Content.Shared/GameObjects/Components/Body/Part/SharedBodyPartComponent.cs +++ b/Content.Shared/GameObjects/Components/Body/Part/SharedBodyPartComponent.cs @@ -43,18 +43,19 @@ namespace Content.Shared.GameObjects.Components.Body.Part var old = _body; _body = value; + if (old != null) + { + foreach (var mechanism in _mechanisms) + { + mechanism.RemovedFromBody(old); + } + } + if (value != null) { foreach (var mechanism in _mechanisms) { - mechanism.OnBodyAdd(old, value); - } - } - else if (old != null) - { - foreach (var mechanism in _mechanisms) - { - mechanism.OnBodyRemove(old); + mechanism.AddedToBody(); } } } @@ -113,6 +114,15 @@ namespace Content.Shared.GameObjects.Components.Body.Part mechanism.Part = this; SizeUsed += mechanism.Size; + if (Body == null) + { + mechanism.AddedToPart(); + } + else + { + mechanism.AddedToPartInBody(); + } + Dirty(); } @@ -122,6 +132,15 @@ namespace Content.Shared.GameObjects.Components.Body.Part mechanism.Part = null; SizeUsed -= mechanism.Size; + if (Body == null) + { + mechanism.RemovedFromPart(this); + } + else + { + mechanism.RemovedFromPartInBody(Body, this); + } + Dirty(); } @@ -305,7 +324,7 @@ namespace Content.Shared.GameObjects.Components.Body.Part [Serializable, NetSerializable] public class BodyPartComponentState : ComponentState { - private List? _mechanisms; + [NonSerialized] private List? _mechanisms; public readonly EntityUid[] MechanismIds;