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;