Remove IBody, IBodyPart, IMechanism and IMechanismBehavior (#4187)

* Remove IBody, IBodyPart, IMechanism and IMechanismBehavior interfaces

* Summary cleanup
This commit is contained in:
DrSmugleaf
2021-06-16 16:44:38 +02:00
committed by GitHub
parent 7cbfbad578
commit 69969bbdc6
72 changed files with 508 additions and 1142 deletions

View File

@@ -1,142 +0,0 @@
#nullable enable
using Content.Shared.Body.Components;
using Content.Shared.Body.Mechanism;
using Content.Shared.Body.Part;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Shared.Body.Behavior
{
/// <summary>
/// Gives functionality to a <see cref="IMechanism"/> when added to it.
/// </summary>
[ImplicitDataDefinitionForInheritors]
public interface IMechanismBehavior
{
/// <summary>
/// The body that owns the <see cref="IBodyPart"/> in which the
/// <see cref="IMechanism"/> that owns this
/// <see cref="IMechanismBehavior"/> is in.
/// </summary>
IBody? Body { get; }
/// <summary>
/// The part in which the <see cref="IMechanism"/> that owns this
/// <see cref="IMechanismBehavior"/> is in.
/// </summary>
IBodyPart? Part { get; }
/// <summary>
/// Upward reference to the parent <see cref="IMechanism"/> that this
/// behavior is attached to.
/// </summary>
IMechanism Parent { get; }
/// <summary>
/// The entity that owns <see cref="Parent"/>.
/// For the entity owning the body that this mechanism may be in,
/// see <see cref="Body"/>'s <see cref="IBody.Owner"/>.
/// </summary>
IEntity Owner { get; }
/// <summary>
/// Called when this <see cref="IMechanismBehavior"/> is added to a
/// <see cref="IMechanism"/>, during <see cref="IComponent.Initialize"/>.
/// If it is added after component initialization,
/// it is called immediately.
/// </summary>
/// <param name="parent">
/// The mechanism that owns this <see cref="IMechanismBehavior"/>.
/// </param>
void Initialize(IMechanism parent);
/// <summary>
/// Called when this <see cref="IMechanismBehavior"/> is added to a
/// <see cref="IMechanism"/>, during <see cref="IComponent.Startup"/>.
/// If it is added after component startup, it is called immediately.
/// </summary>
void Startup();
/// <summary>
/// Runs an update cycle on this <see cref="IMechanismBehavior"/>.
/// </summary>
/// <param name="frameTime">
/// The amount of seconds that passed since the last update.
/// </param>
void Update(float frameTime);
/// <summary>
/// Called when the containing <see cref="IBodyPart"/> is attached to a
/// <see cref="IBody"/>.
/// For instance, attaching a head with a brain inside to a body.
/// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY SYSTEM CODE!
/// </summary>
/// <param name="body">
/// The body that the containing <see cref="IMechanism"/> was added to.
/// </param>
void AddedToBody(IBody body);
/// <summary>
/// Called when the parent <see cref="IMechanism"/> is
/// added into a <see cref="IBodyPart"/> that is not attached to a
/// <see cref="IBody"/>.
/// For instance, adding a brain to a dismembered head.
/// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY SYSTEM CODE!
/// </summary>
/// <param name="part">
/// The part that the containing <see cref="IMechanism"/> was added to.
/// </param>
void AddedToPart(IBodyPart part);
/// <summary>
/// Called when the parent <see cref="IMechanism"/> is added to a
/// <see cref="IBodyPart"/> that is attached to a <see cref="IBody"/>.
/// For instance, adding a brain to a head that is attached to a body.
/// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY SYSTEM CODE!
/// </summary>
/// <param name="body">
/// The body that the containing <see cref="IMechanism"/> was added to.
/// </param>
/// <param name="part">
/// The part that the containing <see cref="IMechanism"/> was added to.
/// </param>
void AddedToPartInBody(IBody body, IBodyPart part);
/// <summary>
/// Called when the parent <see cref="IBodyPart"/> is removed from a
/// <see cref="IBody"/>.
/// For instance, removing a head with a brain inside from a body.
/// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY SYSTEM CODE!
/// </summary>
/// <param name="old">
/// The body that the containing <see cref="IMechanism"/> was removed from.
/// </param>
void RemovedFromBody(IBody old);
/// <summary>
/// Called when the parent <see cref="IMechanism"/> is
/// removed from a <see cref="IBodyPart"/> that is not attached to a
/// <see cref="IBody"/>.
/// For instance, removing a brain from a dismembered head.
/// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY SYSTEM CODE!
/// </summary>
/// <param name="old">
/// The part that the containing <see cref="IMechanism"/> was removed from.
/// </param>
void RemovedFromPart(IBodyPart old);
/// <summary>
/// Called when the parent <see cref="IMechanism"/> is removed from a
/// <see cref="IBodyPart"/> that is attached to a <see cref="IBody"/>.
/// For instance, removing a brain from a head that is attached to a body.
/// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY SYSTEM CODE!
/// </summary>
/// <param name="oldBody">
/// The body that the containing <see cref="IMechanism"/> was removed from.
/// </param>
/// <param name="oldPart">
/// The part that the containing <see cref="IMechanism"/> was removed from.
/// </param>
void RemovedFromPartInBody(IBody oldBody, IBodyPart oldPart);
}
}

View File

@@ -0,0 +1,119 @@
#nullable enable
using Content.Shared.Body.Components;
using Content.Shared.Body.Mechanism;
using Content.Shared.Body.Part;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Shared.Body.Behavior
{
/// <summary>
/// Gives functionality to a mechanism when added to it.
/// </summary>
[ImplicitDataDefinitionForInheritors]
public abstract class SharedMechanismBehavior
{
public abstract SharedBodyComponent? Body { get; }
public abstract SharedBodyPartComponent? Part { get; }
public abstract SharedMechanismComponent Parent { get; }
/// <summary>
/// The entity that owns <see cref="Parent"/>.
/// For the entity owning the body that this mechanism may be in,
/// see <see cref="Body"/>'s <see cref="SharedBodyComponent.Owner"/>.
/// </summary>
public abstract IEntity Owner { get; }
/// <summary>
/// Called when this behavior is added to a mechanism, during <see cref="IComponent.Initialize"/>.
/// If it is added after component initialization,
/// it is called immediately.
/// </summary>
/// <param name="parent">
/// The mechanism that owns this behavior.
/// </param>
public abstract void Initialize(SharedMechanismComponent parent);
/// <summary>
/// Called when this behavior is added to a mechanism, during <see cref="Component.Startup"/>.
/// If it is added after component startup, it is called immediately.
/// </summary>
public abstract void Startup();
/// <summary>
/// Runs an update cycle on this behavior.
/// </summary>
/// <param name="frameTime">
/// The amount of seconds that passed since the last update.
/// </param>
public abstract void Update(float frameTime);
/// <summary>
/// Called when the containing part is attached to a body.
/// For instance, attaching a head with a brain inside to a body.
/// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY SYSTEM CODE!
/// </summary>
/// <param name="body">
/// The body that the containing mechanism was added to.
/// </param>
public abstract void AddedToBody(SharedBodyComponent body);
/// <summary>
/// Called when the parent mechanism is added into a part that is not attached to a body.
/// For instance, adding a brain to a dismembered head.
/// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY SYSTEM CODE!
/// </summary>
/// <param name="part">
/// The part that the containing mechanism was added to.
/// </param>
public abstract void AddedToPart(SharedBodyPartComponent part);
/// <summary>
/// Called when the parent mechanism is added to a part that is attached to a body.
/// For instance, adding a brain to a head that is attached to a body.
/// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY SYSTEM CODE!
/// </summary>
/// <param name="body">
/// The body that the containing mechanism was added to.
/// </param>
/// <param name="part">
/// The part that the containing mechanism was added to.
/// </param>
public abstract void AddedToPartInBody(SharedBodyComponent body, SharedBodyPartComponent part);
/// <summary>
/// Called when the parent part is removed from a body.
/// For instance, removing a head with a brain inside from a body.
/// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY SYSTEM CODE!
/// </summary>
/// <param name="old">
/// The body that the containing mechanism was removed from.
/// </param>
public abstract void RemovedFromBody(SharedBodyComponent old);
/// <summary>
/// Called when the parent mechanism is removed from a part that is not attached to a body.
/// For instance, removing a brain from a dismembered head.
/// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY SYSTEM CODE!
/// </summary>
/// <param name="old">
/// The part that the containing mechanism was removed from.
/// </param>
public abstract void RemovedFromPart(SharedBodyPartComponent old);
/// <summary>
/// Called when the parent mechanism is removed from a part that is attached to a body.
/// For instance, removing a brain from a head that is attached to a body.
/// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY SYSTEM CODE!
/// </summary>
/// <param name="oldBody">
/// The body that the containing mechanism was removed from.
/// </param>
/// <param name="oldPart">
/// The part that the containing mechanism was removed from.
/// </param>
public abstract void RemovedFromPartInBody(SharedBodyComponent oldBody, SharedBodyPartComponent oldPart);
}
}

View File

@@ -1,256 +0,0 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Content.Shared.Body.Part;
using Content.Shared.Body.Part.Property;
using Content.Shared.Body.Preset;
using Content.Shared.Body.Slot;
using Content.Shared.Body.Template;
using Robust.Shared.GameObjects;
namespace Content.Shared.Body.Components
{
/// <summary>
/// Component representing a collection of <see cref="IBodyPart"/>s
/// attached to each other.
/// </summary>
public interface IBody : IComponent, IBodyPartContainer
{
/// <summary>
/// The <see cref="BodyTemplatePrototype"/> used to create this
/// <see cref="IBody"/>.
/// </summary>
public BodyTemplatePrototype? Template { get; }
/// <summary>
/// The <see cref="BodyPresetPrototype"/> used to create this
/// <see cref="IBody"/>.
/// </summary>
public BodyPresetPrototype? Preset { get; }
/// <summary>
/// An enumeration of the slots that make up this body, regardless
/// of if they contain a part or not.
/// </summary>
IEnumerable<BodyPartSlot> Slots { get; }
/// <summary>
/// An enumeration of the parts on this body paired with the slots
/// that they are in.
/// </summary>
IEnumerable<KeyValuePair<IBodyPart, BodyPartSlot>> Parts { get; }
/// <summary>
/// An enumeration of the slots on this body without a part in them.
/// </summary>
IEnumerable<BodyPartSlot> EmptySlots { get; }
/// <summary>
/// Finds the central <see cref="BodyPartSlot"/>, if any,
/// of this body.
/// </summary>
/// <returns>
/// The central <see cref="BodyPartSlot"/> if one exists,
/// null otherwise.
/// </returns>
BodyPartSlot? CenterSlot { get; }
/// <summary>
/// Finds the central <see cref="IBodyPart"/>, if any,
/// of this body.
/// </summary>
/// <returns>
/// The central <see cref="IBodyPart"/> if one exists,
/// null otherwise.
/// </returns>
IBodyPart? CenterPart { get; }
// TODO BODY Sensible templates
/// <summary>
/// Attempts to add a part to the given slot.
/// </summary>
/// <param name="slotId">The slot to add this part to.</param>
/// <param name="part">The part to add.</param>
/// <param name="checkSlotExists">
/// Whether to check if the slot exists, or create one otherwise.
/// </param>
/// <returns>
/// true if the part was added, false otherwise even if it was
/// already added.
/// </returns>
bool TryAddPart(string slotId, IBodyPart part);
void SetPart(string slotId, IBodyPart part);
/// <summary>
/// Checks if there is a <see cref="IBodyPart"/> in the given slot.
/// </summary>
/// <param name="slotId">The slot to look in.</param>
/// <returns>
/// true if there is a part in the given <see cref="slotId"/>,
/// false otherwise.
/// </returns>
bool HasPart(string slotId);
/// <summary>
/// Checks if this <see cref="IBody"/> contains the given <see cref="part"/>.
/// </summary>
/// <param name="part">The part to look for.</param>
/// <returns>
/// true if the given <see cref="part"/> is attached to the body,
/// false otherwise.
/// </returns>
bool HasPart(IBodyPart part);
/// <summary>
/// Removes the given <see cref="IBodyPart"/> from this body,
/// dropping other <see cref="IBodyPart"/> if they were hanging
/// off of it.
/// <param name="part">The part to remove.</param>
/// <returns>
/// true if the part was removed, false otherwise
/// even if the part was already removed previously.
/// </returns>
/// </summary>
bool RemovePart(IBodyPart part);
/// <summary>
/// Removes the body part in slot <see cref="slotId"/> from this body,
/// if one exists.
/// </summary>
/// <param name="slotId">The slot to remove it from.</param>
/// <returns>true if the part was removed, false otherwise.</returns>
bool RemovePart(string slotId);
/// <summary>
/// Removes the body part from this body, if one exists.
/// </summary>
/// <param name="part">The part to remove from this body.</param>
/// <param name="slotId">The slot that the part was in, if any.</param>
/// <returns>
/// true if <see cref="part"/> was removed, false otherwise.
/// </returns>
bool RemovePart(IBodyPart part, [NotNullWhen(true)] out BodyPartSlot? slotId);
/// <summary>
/// Disconnects the given <see cref="IBodyPart"/> reference, potentially
/// dropping other <see cref="IBodyPart">BodyParts</see> if they
/// were hanging off of it.
/// </summary>
/// <param name="slot">The part to drop.</param>
/// <param name="dropped">
/// All of the parts that were dropped, including the one in
/// <see cref="slot"/>.
/// </param>
/// <returns>
/// true if the part was dropped, false otherwise.
/// </returns>
bool TryDropPart(BodyPartSlot slot, [NotNullWhen(true)] out Dictionary<BodyPartSlot, IBodyPart>? dropped);
/// <summary>
/// Recursively searches for if <see cref="part"/> is connected to
/// the center.
/// </summary>
/// <param name="part">The body part to find the center for.</param>
/// <returns>
/// true if it is connected to the center, false otherwise.
/// </returns>
bool ConnectedToCenter(IBodyPart part);
/// <summary>
/// Returns whether the given part slot exists in this body.
/// </summary>
/// <param name="slot">The slot to check for.</param>
/// <returns>true if the slot exists in this body, false otherwise.</returns>
bool HasSlot(string slot);
BodyPartSlot? GetSlot(IBodyPart part);
/// <summary>
/// Finds the slot that the given <see cref="IBodyPart"/> resides in.
/// </summary>
/// <param name="part">
/// The <see cref="IBodyPart"/> to find the slot for.
/// </param>
/// <param name="slot">The slot found, if any.</param>
/// <returns>true if a slot was found, false otherwise</returns>
bool TryGetSlot(IBodyPart part, [NotNullWhen(true)] out BodyPartSlot? slot);
/// <summary>
/// Finds the <see cref="IBodyPart"/> in the given
/// <see cref="slotId"/> if one exists.
/// </summary>
/// <param name="slotId">The part slot to search in.</param>
/// <param name="result">The body part in that slot, if any.</param>
/// <returns>true if found, false otherwise.</returns>
bool TryGetPart(string slotId, [NotNullWhen(true)] out IBodyPart? result);
/// <summary>
/// Checks if a slot of the specified type exists on this body.
/// </summary>
/// <param name="type">The type to check for.</param>
/// <returns>true if present, false otherwise.</returns>
bool HasSlotOfType(BodyPartType type);
/// <summary>
/// Gets all slots of the specified type on this body.
/// </summary>
/// <param name="type">The type to check for.</param>
/// <returns>An enumerable of the found slots.</returns>
IEnumerable<BodyPartSlot> GetSlotsOfType(BodyPartType type);
/// <summary>
/// Checks if a part of the specified type exists on this body.
/// </summary>
/// <param name="type">The type to check for.</param>
/// <returns>true if present, false otherwise.</returns>
bool HasPartOfType(BodyPartType type);
/// <summary>
/// Gets all slots of the specified type on this body.
/// </summary>
/// <param name="type">The type to check for.</param>
/// <returns>An enumerable of the found slots.</returns>
IEnumerable<IBodyPart> GetPartsOfType(BodyPartType type);
/// <summary>
/// Finds all <see cref="IBodyPart"/>s with the given property in
/// this body.
/// </summary>
/// <type name="type">The property type to look for.</type>
/// <returns>A list of parts with that property.</returns>
IEnumerable<(IBodyPart part, IBodyPartProperty property)> GetPartsWithProperty(Type type);
/// <summary>
/// Finds all <see cref="IBodyPart"/>s with the given property in this body.
/// </summary>
/// <typeparam name="T">The property type to look for.</typeparam>
/// <returns>A list of parts with that property.</returns>
IEnumerable<(IBodyPart part, T property)> GetPartsWithProperty<T>() where T : class, IBodyPartProperty;
// TODO BODY Make a slot object that makes sense to the human mind, and make it serializable. Imagine the possibilities!
/// <summary>
/// Retrieves the slot at the given index.
/// </summary>
/// <param name="index">The index to look in.</param>
/// <returns>A pair of the slot name and part type occupying it.</returns>
BodyPartSlot SlotAt(int index);
/// <summary>
/// Retrieves the part at the given index.
/// </summary>
/// <param name="index">The index to look in.</param>
/// <returns>A pair of the part name and body part occupying it.</returns>
KeyValuePair<IBodyPart, BodyPartSlot> PartAt(int index);
/// <summary>
/// Gibs this body.
/// </summary>
/// <param name="gibParts">
/// Whether or not to also gib this body's parts.
/// </param>
void Gib(bool gibParts = false);
}
}

View File

@@ -3,6 +3,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Content.Shared.Body.Behavior;
using Content.Shared.Body.Part;
using Content.Shared.Body.Part.Property;
using Content.Shared.Body.Preset;
@@ -25,7 +26,7 @@ using Robust.Shared.ViewVariables;
namespace Content.Shared.Body.Components
{
// TODO BODY Damage methods for collections of IDamageableComponents
public abstract class SharedBodyComponent : Component, IBody, ISerializationHooks
public abstract class SharedBodyComponent : Component, IBodyPartContainer, ISerializationHooks
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
@@ -55,13 +56,13 @@ namespace Content.Shared.Body.Components
private Dictionary<string, BodyPartSlot> SlotIds { get; } = new();
[ViewVariables]
private Dictionary<IBodyPart, BodyPartSlot> SlotParts { get; } = new();
private Dictionary<SharedBodyPartComponent, BodyPartSlot> SlotParts { get; } = new();
[ViewVariables]
public IEnumerable<BodyPartSlot> Slots => SlotIds.Values;
[ViewVariables]
public IEnumerable<KeyValuePair<IBodyPart, BodyPartSlot>> Parts => SlotParts;
public IEnumerable<KeyValuePair<SharedBodyPartComponent, BodyPartSlot>> Parts => SlotParts;
[ViewVariables]
public IEnumerable<BodyPartSlot> EmptySlots => Slots.Where(slot => slot.Part == null);
@@ -71,7 +72,7 @@ namespace Content.Shared.Body.Components
? SlotIds.GetValueOrDefault(centerSlot)
: null;
public IBodyPart? CenterPart => CenterSlot?.Part;
public SharedBodyPartComponent? CenterPart => CenterSlot?.Part;
public override void Initialize()
{
@@ -119,9 +120,9 @@ namespace Content.Shared.Body.Components
return slot;
}
private Dictionary<BodyPartSlot, IBodyPart> GetHangingParts(BodyPartSlot from)
private Dictionary<BodyPartSlot, SharedBodyPartComponent> GetHangingParts(BodyPartSlot from)
{
var hanging = new Dictionary<BodyPartSlot, IBodyPart>();
var hanging = new Dictionary<BodyPartSlot, SharedBodyPartComponent>();
foreach (var connection in from.Connections)
{
@@ -135,7 +136,7 @@ namespace Content.Shared.Body.Components
return hanging;
}
protected virtual bool CanAddPart(string slotId, IBodyPart part)
protected virtual bool CanAddPart(string slotId, SharedBodyPartComponent part)
{
if (!SlotIds.TryGetValue(slotId, out var slot) ||
slot.CanAddPart(part))
@@ -146,7 +147,7 @@ namespace Content.Shared.Body.Components
return true;
}
protected virtual void OnAddPart(BodyPartSlot slot, IBodyPart part)
protected virtual void OnAddPart(BodyPartSlot slot, SharedBodyPartComponent part)
{
SlotParts[part] = slot;
part.Body = this;
@@ -162,7 +163,7 @@ namespace Content.Shared.Body.Components
OnBodyChanged();
}
protected virtual void OnRemovePart(BodyPartSlot slot, IBodyPart part)
protected virtual void OnRemovePart(BodyPartSlot slot, SharedBodyPartComponent part)
{
SlotParts.Remove(part);
@@ -203,7 +204,8 @@ namespace Content.Shared.Body.Components
OnBodyChanged();
}
public bool TryAddPart(string slotId, IBodyPart part)
// TODO BODY Sensible templates
public bool TryAddPart(string slotId, SharedBodyPartComponent part)
{
DebugTools.AssertNotNull(part);
DebugTools.AssertNotNull(slotId);
@@ -217,7 +219,7 @@ namespace Content.Shared.Body.Components
slot.TryAddPart(part);
}
public void SetPart(string slotId, IBodyPart part)
public void SetPart(string slotId, SharedBodyPartComponent part)
{
if (!SlotIds.TryGetValue(slotId, out var slot))
{
@@ -236,14 +238,14 @@ namespace Content.Shared.Body.Components
slot.Part != null;
}
public bool HasPart(IBodyPart part)
public bool HasPart(SharedBodyPartComponent part)
{
DebugTools.AssertNotNull(part);
return SlotParts.ContainsKey(part);
}
public bool RemovePart(IBodyPart part)
public bool RemovePart(SharedBodyPartComponent part)
{
DebugTools.AssertNotNull(part);
@@ -259,7 +261,7 @@ namespace Content.Shared.Body.Components
slot.RemovePart();
}
public bool RemovePart(IBodyPart part, [NotNullWhen(true)] out BodyPartSlot? slotId)
public bool RemovePart(SharedBodyPartComponent part, [NotNullWhen(true)] out BodyPartSlot? slotId)
{
DebugTools.AssertNotNull(part);
@@ -279,7 +281,7 @@ namespace Content.Shared.Body.Components
return true;
}
public bool TryDropPart(BodyPartSlot slot, [NotNullWhen(true)] out Dictionary<BodyPartSlot, IBodyPart>? dropped)
public bool TryDropPart(BodyPartSlot slot, [NotNullWhen(true)] out Dictionary<BodyPartSlot, SharedBodyPartComponent>? dropped)
{
DebugTools.AssertNotNull(slot);
@@ -304,7 +306,7 @@ namespace Content.Shared.Body.Components
return true;
}
public bool ConnectedToCenter(IBodyPart part)
public bool ConnectedToCenter(SharedBodyPartComponent part)
{
return TryGetSlot(part, out var result) &&
ConnectedToCenterPartRecursion(result);
@@ -343,7 +345,7 @@ namespace Content.Shared.Body.Components
return SlotIds.ContainsKey(slot);
}
public IEnumerable<IBodyPart> GetParts()
public IEnumerable<SharedBodyPartComponent> GetParts()
{
foreach (var slot in SlotIds.Values)
{
@@ -354,7 +356,7 @@ namespace Content.Shared.Body.Components
}
}
public bool TryGetPart(string slotId, [NotNullWhen(true)] out IBodyPart? result)
public bool TryGetPart(string slotId, [NotNullWhen(true)] out SharedBodyPartComponent? result)
{
result = null;
@@ -367,7 +369,7 @@ namespace Content.Shared.Body.Components
return SlotIds.GetValueOrDefault(id);
}
public BodyPartSlot? GetSlot(IBodyPart part)
public BodyPartSlot? GetSlot(SharedBodyPartComponent part)
{
return SlotParts.GetValueOrDefault(part);
}
@@ -377,12 +379,12 @@ namespace Content.Shared.Body.Components
return (slot = GetSlot(slotId)) != null;
}
public bool TryGetSlot(IBodyPart part, [NotNullWhen(true)] out BodyPartSlot? slot)
public bool TryGetSlot(SharedBodyPartComponent part, [NotNullWhen(true)] out BodyPartSlot? slot)
{
return (slot = GetSlot(part)) != null;
}
public bool TryGetPartConnections(string slotId, [NotNullWhen(true)] out List<IBodyPart>? connections)
public bool TryGetPartConnections(string slotId, [NotNullWhen(true)] out List<SharedBodyPartComponent>? connections)
{
if (!SlotIds.TryGetValue(slotId, out var slot))
{
@@ -390,7 +392,7 @@ namespace Content.Shared.Body.Components
return false;
}
connections = new List<IBodyPart>();
connections = new List<SharedBodyPartComponent>();
foreach (var connection in slot.Connections)
{
if (connection.Part != null)
@@ -439,7 +441,7 @@ namespace Content.Shared.Body.Components
return false;
}
public IEnumerable<IBodyPart> GetPartsOfType(BodyPartType type)
public IEnumerable<SharedBodyPartComponent> GetPartsOfType(BodyPartType type)
{
foreach (var slot in GetSlotsOfType(type))
{
@@ -450,7 +452,8 @@ namespace Content.Shared.Body.Components
}
}
public IEnumerable<(IBodyPart part, IBodyPartProperty property)> GetPartsWithProperty(Type type)
/// <returns>A list of parts with that property.</returns>
public IEnumerable<(SharedBodyPartComponent part, IBodyPartProperty property)> GetPartsWithProperty(Type type)
{
foreach (var slot in SlotIds.Values)
{
@@ -461,7 +464,7 @@ namespace Content.Shared.Body.Components
}
}
public IEnumerable<(IBodyPart part, T property)> GetPartsWithProperty<T>() where T : class, IBodyPartProperty
public IEnumerable<(SharedBodyPartComponent part, T property)> GetPartsWithProperty<T>() where T : class, IBodyPartProperty
{
foreach (var part in SlotParts.Keys)
{
@@ -509,9 +512,6 @@ namespace Content.Shared.Body.Components
}
}
/// <summary>
/// Called when the layout of this body changes.
/// </summary>
private void OnBodyChanged()
{
// Calculate move speed based on this body.
@@ -523,19 +523,7 @@ namespace Content.Shared.Body.Components
Dirty();
}
/// <summary>
/// Returns the combined length of the distance to the nearest
/// <see cref="IBodyPart"/> that is a foot.
/// If you consider a <see cref="IBody"/> a node map, then it will
/// look for a foot node from the given node. It can only search
/// through <see cref="IBodyPart"/>s with an
/// <see cref="ExtensionComponent"/>.
/// </summary>
/// <returns>
/// The distance to the foot if found, <see cref="float.MinValue"/>
/// otherwise.
/// </returns>
public float DistanceToNearestFoot(IBodyPart source)
public float DistanceToNearestFoot(SharedBodyPartComponent source)
{
if (source.PartType == BodyPartType.Foot &&
source.TryGetProperty<ExtensionComponent>(out var extension))
@@ -546,7 +534,7 @@ namespace Content.Shared.Body.Components
return LookForFootRecursion(source);
}
private float LookForFootRecursion(IBodyPart current, HashSet<BodyPartSlot>? searched = null)
private float LookForFootRecursion(SharedBodyPartComponent current, HashSet<BodyPartSlot>? searched = null)
{
searched ??= new HashSet<BodyPartSlot>();
@@ -555,13 +543,11 @@ namespace Content.Shared.Body.Components
return float.MinValue;
}
// Get all connected parts if the current part has an extension property
if (!TryGetSlot(current, out var slot))
{
return float.MinValue;
}
// If a connected BodyPart is a foot, return this BodyPart's length.
foreach (var connection in slot.Connections)
{
if (connection.PartType == BodyPartType.Foot &&
@@ -571,8 +557,6 @@ namespace Content.Shared.Body.Components
}
}
// Otherwise, get the recursion values of all connected BodyParts and
// store them in a list.
var distances = new List<float>();
foreach (var connection in slot.Connections)
{
@@ -589,8 +573,6 @@ namespace Content.Shared.Body.Components
}
}
// If one or more of the searches found a foot, return the smallest one
// and add this ones length.
if (distances.Count > 0)
{
return distances.Min<float>() + extProperty.Distance;
@@ -605,7 +587,7 @@ namespace Content.Shared.Body.Components
return SlotIds.Values.ElementAt(index);
}
public KeyValuePair<IBodyPart, BodyPartSlot> PartAt(int index)
public KeyValuePair<SharedBodyPartComponent, BodyPartSlot> PartAt(int index)
{
return SlotParts.ElementAt(index);
}
@@ -664,12 +646,68 @@ namespace Content.Shared.Body.Components
part.Gib();
}
}
public bool TryGetMechanismBehaviors([NotNullWhen(true)] out List<SharedMechanismBehavior>? behaviors)
{
behaviors = GetMechanismBehaviors().ToList();
if (behaviors.Count == 0)
{
behaviors = null;
return false;
}
return true;
}
public bool HasMechanismBehavior<T>() where T : SharedMechanismBehavior
{
return Parts.Any(p => p.Key.HasMechanismBehavior<T>());
}
// TODO cache these 2 methods jesus
public IEnumerable<SharedMechanismBehavior> GetMechanismBehaviors()
{
foreach (var (part, _) in Parts)
foreach (var mechanism in part.Mechanisms)
foreach (var behavior in mechanism.Behaviors.Values)
{
yield return behavior;
}
}
public IEnumerable<T> GetMechanismBehaviors<T>() where T : SharedMechanismBehavior
{
foreach (var (part, _) in Parts)
foreach (var mechanism in part.Mechanisms)
foreach (var behavior in mechanism.Behaviors.Values)
{
if (behavior is T tBehavior)
{
yield return tBehavior;
}
}
}
public bool TryGetMechanismBehaviors<T>([NotNullWhen(true)] out List<T>? behaviors)
where T : SharedMechanismBehavior
{
behaviors = GetMechanismBehaviors<T>().ToList();
if (behaviors.Count == 0)
{
behaviors = null;
return false;
}
return true;
}
}
[Serializable, NetSerializable]
public class BodyComponentState : ComponentState
{
private Dictionary<string, IBodyPart>? _parts;
private Dictionary<string, SharedBodyPartComponent>? _parts;
public readonly (string slot, EntityUid partId)[] PartIds;
@@ -678,7 +716,7 @@ namespace Content.Shared.Body.Components
PartIds = partIds;
}
public Dictionary<string, IBodyPart> Parts(IEntityManager? entityManager = null)
public Dictionary<string, SharedBodyPartComponent> Parts(IEntityManager? entityManager = null)
{
if (_parts != null)
{
@@ -687,7 +725,7 @@ namespace Content.Shared.Body.Components
entityManager ??= IoCManager.Resolve<IEntityManager>();
var parts = new Dictionary<string, IBodyPart>(PartIds.Length);
var parts = new Dictionary<string, SharedBodyPartComponent>(PartIds.Length);
foreach (var (slot, partId) in PartIds)
{
@@ -696,7 +734,7 @@ namespace Content.Shared.Body.Components
continue;
}
if (!entity.TryGetComponent(out IBodyPart? part))
if (!entity.TryGetComponent(out SharedBodyPartComponent? part))
{
continue;
}

View File

@@ -1,178 +0,0 @@
#nullable enable
using System;
using System.Collections.Generic;
using Content.Shared.Body.Behavior;
using Content.Shared.Body.Components;
using Content.Shared.Body.Part;
using Robust.Shared.GameObjects;
namespace Content.Shared.Body.Mechanism
{
public interface IMechanism : IComponent
{
/// <summary>
/// The body that owns the <see cref="IBodyPart"/> in which this
/// <see cref="IMechanism"/> is in.
/// </summary>
IBody? Body { get; }
/// <summary>
/// The part in which this <see cref="IMechanism"/> is in.
/// </summary>
IBodyPart? Part { get; set; }
/// <summary>
/// The behaviors attached to this <see cref="IMechanism"/>
/// mapped by their type.
/// </summary>
IReadOnlyDictionary<Type, IMechanismBehavior> Behaviors { get; }
/// <summary>
/// Max HP of this <see cref="IMechanism"/>.
/// </summary>
int MaxDurability { get; set; }
/// <summary>
/// Current HP of this <see cref="IMechanism"/>.
/// </summary>
int CurrentDurability { get; set; }
/// <summary>
/// At what HP this <see cref="IMechanism"/> is completely destroyed.
/// </summary>
int DestroyThreshold { get; set; }
/// <summary>
/// Armor of this <see cref="IMechanism"/> against attacks.
/// </summary>
int Resistance { get; set; }
/// <summary>
/// Determines a handful of things - mostly whether this
/// <see cref="IMechanism"/> can fit into a <see cref="IBodyPart"/>.
/// </summary>
// TODO BODY OnSizeChanged
int Size { get; set; }
/// <summary>
/// What kind of <see cref="IBodyPart"/> this
/// <see cref="IMechanism"/> can be easily installed into.
/// </summary>
BodyPartCompatibility Compatibility { get; set; }
/// <summary>
/// Adds a <see cref="IMechanismBehavior"/> if this
/// <see cref="IMechanism"/> does not have it already.
/// </summary>
/// <typeparam name="T">The behavior type to add.</typeparam>
/// <returns>
/// True if the behavior already existed, false if it had to be created.
/// </returns>
bool EnsureBehavior<T>(out T behavior) where T : IMechanismBehavior, new();
/// <summary>
/// Checks if this <see cref="IMechanism"/> has the specified
/// <see cref="IMechanismBehavior"/>.
/// </summary>
/// <typeparam name="T">
/// The type of <see cref="IMechanismBehavior"/> to check for.
/// </typeparam>
/// <returns>
/// true if it has the <see cref="IMechanismBehavior"/>, false otherwise.
/// </returns>
bool HasBehavior<T>() where T : IMechanismBehavior;
/// <summary>
/// Removes the specified <see cref="IMechanismBehavior"/> from this
/// <see cref="IMechanism"/> if it has it.
/// </summary>
/// <typeparam name="T">
/// The type of <see cref="IMechanismBehavior"/> to remove.
/// </typeparam>
/// <returns>true if it was removed, false otherwise.</returns>
bool TryRemoveBehavior<T>() where T : IMechanismBehavior;
/// <summary>
/// Runs an update cycle for this <see cref="IMechanism"/>.
/// </summary>
/// <param name="frameTime">
/// The amount of seconds that passed since the last update.
/// </param>
void Update(float frameTime);
// TODO BODY Turn these into event listeners so they dont need to be exposed
/// <summary>
/// Called when the containing <see cref="IBodyPart"/> is attached to a
/// <see cref="IBody"/>.
/// For instance, attaching a head with a brain inside to a body.
/// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY SYSTEM CODE!
/// </summary>
/// <param name="body">
/// The body that this <see cref="IMechanism"/> was added to.
/// </param>
void AddedToBody(IBody body);
/// <summary>
/// Called when the parent <see cref="IMechanism"/> is
/// added into a <see cref="IBodyPart"/> that is not attached to a
/// <see cref="IBody"/>.
/// For instance, adding a brain to a dismembered head.
/// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY SYSTEM CODE!
/// </summary>
/// <param name="part">
/// The part that this <see cref="IMechanism"/> was added to.
/// </param>
void AddedToPart(IBodyPart part);
/// <summary>
/// Called when the parent <see cref="IMechanism"/> is added to a
/// <see cref="IBodyPart"/> that is attached to a <see cref="IBody"/>.
/// For instance, adding a brain to a head that is attached to a body.
/// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY SYSTEM CODE!
/// </summary>
/// <param name="body">
/// The body that this <see cref="IMechanism"/> was added to.
/// </param>
/// <param name="part">
/// The part that this <see cref="IMechanism"/> was added to.
/// </param>
void AddedToPartInBody(IBody body, IBodyPart part);
/// <summary>
/// Called when the parent <see cref="IBodyPart"/> is removed from a
/// <see cref="IBody"/>.
/// For instance, removing a head with a brain inside from a body.
/// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY SYSTEM CODE!
/// </summary>
/// <param name="old">
/// The body that this <see cref="IMechanism"/> was removed from.
/// </param>
void RemovedFromBody(IBody old);
/// <summary>
/// Called when the parent <see cref="IMechanism"/> is
/// removed from a <see cref="IBodyPart"/> that is not attached to a
/// <see cref="IBody"/>.
/// For instance, removing a brain from a dismembered head.
/// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY SYSTEM CODE!
/// </summary>
/// <param name="old">
/// The part that this <see cref="IMechanism"/> was removed from.
/// </param>
void RemovedFromPart(IBodyPart old);
/// <summary>
/// Called when the parent <see cref="IMechanism"/> is removed from a
/// <see cref="IBodyPart"/> that is attached to a <see cref="IBody"/>.
/// For instance, removing a brain from a head that is attached to a body.
/// DO NOT CALL THIS DIRECTLY FROM OUTSIDE BODY SYSTEM CODE!
/// </summary>
/// <param name="oldBody">
/// The body that this <see cref="IMechanism"/> was removed from.
/// </param>
/// <param name="oldPart">
/// The part that this <see cref="IMechanism"/> was removed from.
/// </param>
void RemovedFromPartInBody(IBody oldBody, IBodyPart oldPart);
}
}

View File

@@ -11,7 +11,7 @@ namespace Content.Shared.Body.Mechanism
{
base.Update(frameTime);
foreach (var mechanism in ComponentManager.EntityQuery<IMechanism>(true))
foreach (var mechanism in ComponentManager.EntityQuery<SharedMechanismComponent>(true))
{
mechanism.Update(frameTime);
}

View File

@@ -14,23 +14,23 @@ using Robust.Shared.Utility;
namespace Content.Shared.Body.Mechanism
{
public abstract class SharedMechanismComponent : Component, IMechanism, ISerializationHooks
public abstract class SharedMechanismComponent : Component, ISerializationHooks
{
public override string Name => "Mechanism";
protected readonly Dictionary<int, object> OptionsCache = new();
protected IBody? BodyCache;
protected SharedBodyComponent? BodyCache;
protected int IdHash;
protected IEntity? PerformerCache;
private IBodyPart? _part;
private SharedBodyPartComponent? _part;
[DataField("behaviors", serverOnly: true)] private HashSet<IMechanismBehavior> _behaviorTypes = new();
[DataField("behaviors", serverOnly: true)] private HashSet<SharedMechanismBehavior> _behaviorTypes = new();
private readonly Dictionary<Type, IMechanismBehavior> _behaviors = new();
private readonly Dictionary<Type, SharedMechanismBehavior> _behaviors = new();
public IBody? Body => Part?.Body;
public SharedBodyComponent? Body => Part?.Body;
public IBodyPart? Part
public SharedBodyPartComponent? Part
{
get => _part;
set
@@ -69,7 +69,7 @@ namespace Content.Shared.Body.Mechanism
}
}
public IReadOnlyDictionary<Type, IMechanismBehavior> Behaviors => _behaviors;
public IReadOnlyDictionary<Type, SharedMechanismBehavior> Behaviors => _behaviors;
[DataField("maxDurability")] public int MaxDurability { get; set; } = 10;
@@ -82,8 +82,16 @@ namespace Content.Shared.Body.Mechanism
[DataField("resistance")] public int Resistance { get; set; } = 0;
// TODO BODY OnSizeChanged
/// <summary>
/// Determines whether this
/// <see cref="SharedMechanismComponent"/> can fit into a <see cref="SharedBodyPartComponent"/>.
/// </summary>
[DataField("size")] public int Size { get; set; } = 1;
/// <summary>
/// What kind of <see cref="SharedBodyPartComponent"/> this
/// <see cref="SharedMechanismComponent"/> can be easily installed into.
/// </summary>
[DataField("compatibility")]
public BodyPartCompatibility Compatibility { get; set; } = BodyPartCompatibility.Universal;
@@ -128,7 +136,7 @@ namespace Content.Shared.Body.Mechanism
}
}
public bool EnsureBehavior<T>(out T behavior) where T : IMechanismBehavior, new()
public bool EnsureBehavior<T>(out T behavior) where T : SharedMechanismBehavior, new()
{
if (_behaviors.TryGetValue(typeof(T), out var rawBehavior))
{
@@ -144,12 +152,12 @@ namespace Content.Shared.Body.Mechanism
return false;
}
public bool HasBehavior<T>() where T : IMechanismBehavior
public bool HasBehavior<T>() where T : SharedMechanismBehavior
{
return _behaviors.ContainsKey(typeof(T));
}
public bool TryRemoveBehavior<T>() where T : IMechanismBehavior
public bool TryRemoveBehavior<T>() where T : SharedMechanismBehavior
{
return _behaviors.Remove(typeof(T));
}
@@ -162,7 +170,8 @@ namespace Content.Shared.Body.Mechanism
}
}
public void AddedToBody(IBody body)
// TODO BODY Turn these into event listeners so they dont need to be exposed
public void AddedToBody(SharedBodyComponent body)
{
DebugTools.AssertNotNull(Body);
DebugTools.AssertNotNull(body);
@@ -173,7 +182,7 @@ namespace Content.Shared.Body.Mechanism
}
}
public void AddedToPart(IBodyPart part)
public void AddedToPart(SharedBodyPartComponent part)
{
DebugTools.AssertNotNull(Part);
DebugTools.AssertNotNull(part);
@@ -186,7 +195,7 @@ namespace Content.Shared.Body.Mechanism
}
}
public void AddedToPartInBody(IBody body, IBodyPart part)
public void AddedToPartInBody(SharedBodyComponent body, SharedBodyPartComponent part)
{
DebugTools.AssertNotNull(Body);
DebugTools.AssertNotNull(body);
@@ -201,7 +210,7 @@ namespace Content.Shared.Body.Mechanism
}
}
public void RemovedFromBody(IBody old)
public void RemovedFromBody(SharedBodyComponent old)
{
DebugTools.AssertNull(Body);
DebugTools.AssertNotNull(old);
@@ -212,7 +221,7 @@ namespace Content.Shared.Body.Mechanism
}
}
public void RemovedFromPart(IBodyPart old)
public void RemovedFromPart(SharedBodyPartComponent old)
{
DebugTools.AssertNull(Part);
DebugTools.AssertNotNull(old);
@@ -225,7 +234,7 @@ namespace Content.Shared.Body.Mechanism
}
}
public void RemovedFromPartInBody(IBody oldBody, IBodyPart oldPart)
public void RemovedFromPartInBody(SharedBodyComponent oldBody, SharedBodyPartComponent oldPart)
{
DebugTools.AssertNull(Body);
DebugTools.AssertNotNull(oldBody);

View File

@@ -5,7 +5,7 @@ using Robust.Shared.Serialization;
namespace Content.Shared.Body.Part
{
/// <summary>
/// Determines whether two <see cref="IBodyPart"/>s can connect.
/// Determines whether two <see cref="SharedBodyPartComponent"/>s can connect.
/// </summary>
[Serializable, NetSerializable]
public enum BodyPartCompatibility

View File

@@ -1,81 +0,0 @@
#nullable enable
using System;
using System.Diagnostics.CodeAnalysis;
using Content.Shared.Body.Part.Property;
namespace Content.Shared.Body.Part
{
public static class BodyPartExtensions
{
/// <summary>
/// Checks if the given <see cref="IBodyPart"/> has the specified property.
/// </summary>
/// <param name="part">The <see cref="IBodyPart"/> to check in.</param>
/// <param name="type">
/// The type of <see cref="IBodyPartProperty"/> to check for.
/// </param>
/// <returns>true if found, false otherwise.</returns>
public static bool HasProperty(this IBodyPart part, Type type)
{
return part.Owner.HasComponent(type);
}
/// <summary>
/// Checks if the given <see cref="IBodyPart"/> has the specified property.
/// </summary>
/// <param name="part">The <see cref="IBodyPart"/> to check in.</param>
/// <typeparam name="T">
/// The type of <see cref="IBodyPartProperty"/> to check for.
/// </typeparam>
/// <returns>true if found, false otherwise.</returns>
public static bool HasProperty<T>(this IBodyPart part) where T : class, IBodyPartProperty
{
return part.HasProperty(typeof(T));
}
/// <summary>
/// Tries to retrieve the <see cref="IBodyPartProperty"/> with the
/// specified type.
/// </summary>
/// <param name="part">The <see cref="IBodyPart"/> to search in.</param>
/// <param name="type">
/// The type of <see cref="IBodyPartProperty"/> to search for.
/// </param>
/// <param name="property">
/// The property, if it was found. Null otherwise.
/// </param>
/// <returns>
/// true if a component with the specified type was found, false otherwise.
/// </returns>
public static bool TryGetProperty(this IBodyPart part, Type type,
[NotNullWhen(true)] out IBodyPartProperty? property)
{
if (!part.Owner.TryGetComponent(type, out var component))
{
property = null;
return false;
}
return (property = component as IBodyPartProperty) != null;
}
/// <summary>
/// Tries to retrieve the <see cref="IBodyPartProperty"/> with the
/// specified type.
/// </summary>
/// <param name="part">The <see cref="IBodyPart"/> to search in.</param>
/// <typeparam name="T">
/// The type of <see cref="IBodyPartProperty"/> to search for.
/// </typeparam>
/// <param name="property">
/// The property, if it was found. Null otherwise.
/// </param>
/// <returns>
/// true if a component with the specified type was found, false otherwise.
/// </returns>
public static bool TryGetProperty<T>(this IBodyPart part, [NotNullWhen(true)] out T? property) where T : class, IBodyPartProperty
{
return part.Owner.TryGetComponent(out property);
}
}
}

View File

@@ -5,7 +5,7 @@ using Robust.Shared.Serialization;
namespace Content.Shared.Body.Part
{
/// <summary>
/// Defines the symmetry of a <see cref="IBodyPart"/>.
/// Defines the symmetry of a <see cref="SharedBodyPartComponent"/>.
/// </summary>
[Serializable, NetSerializable]
public enum BodyPartSymmetry

View File

@@ -5,7 +5,7 @@ using Robust.Shared.Serialization;
namespace Content.Shared.Body.Part
{
/// <summary>
/// Defines the type of a <see cref="IBodyPart"/>.
/// Defines the type of a <see cref="SharedBodyPartComponent"/>.
/// </summary>
[Serializable, NetSerializable]
public enum BodyPartType

View File

@@ -1,131 +0,0 @@
#nullable enable
using System.Collections.Generic;
using Content.Shared.Body.Components;
using Content.Shared.Body.Mechanism;
using Content.Shared.Body.Surgery;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
namespace Content.Shared.Body.Part
{
public interface IBodyPart : IComponent, IBodyPartContainer
{
/// <summary>
/// The <see cref="IBody"/> to which this <see cref="IBodyPart"/> is
/// attached to.
/// </summary>
IBody? Body { get; set; }
/// <summary>
/// The string to show when displaying this part's name to players.
/// </summary>
string DisplayName { get; }
/// <summary>
/// <see cref="BodyPartType"/> that this <see cref="IBodyPart"/> is considered
/// to be.
/// For example, <see cref="BodyPartType.Arm"/>.
/// </summary>
BodyPartType PartType { get; }
/// <summary>
/// Determines how many mechanisms can be fit inside this
/// <see cref="IBodyPart"/>.
/// </summary>
int Size { get; }
// TODO BODY Mechanisms occupying different parts at the body level
/// <summary>
/// Collection of all <see cref="IMechanism"/>s currently inside this
/// <see cref="IBodyPart"/>.
/// To add and remove from this list see <see cref="TryAddMechanism"/> and
/// <see cref="RemoveMechanism"/>
/// </summary>
IReadOnlyCollection<IMechanism> Mechanisms { get; }
/// <summary>
/// Whether or not the owning <see cref="Body"/> will die if all
/// <see cref="IBodyPart"/>s of this type are removed from it.
/// </summary>
public bool IsVital { get; }
/// <summary>
/// The symmetry of this <see cref="IBodyPart"/>.
/// </summary>
public BodyPartSymmetry Symmetry { get; }
/// <summary>
/// Checks if the given <see cref="SurgeryType"/> can be used on
/// the current state of this <see cref="IBodyPart"/>.
/// </summary>
/// <returns>True if it can be used, false otherwise.</returns>
bool SurgeryCheck(SurgeryType surgery);
/// <summary>
/// Attempts to perform surgery on this <see cref="IBodyPart"/> with the given
/// tool.
/// </summary>
/// <returns>True if successful, false if there was an error.</returns>
public bool AttemptSurgery(SurgeryType toolType, IBodyPartContainer target, ISurgeon surgeon,
IEntity performer);
/// <summary>
/// Checks if another <see cref="IBodyPart"/> can be connected to this one.
/// </summary>
/// <param name="part">The part to connect.</param>
/// <returns>True if it can be connected, false otherwise.</returns>
bool CanAttachPart(IBodyPart part);
/// <summary>
/// Checks if a <see cref="IMechanism"/> can be added on this
/// <see cref="IBodyPart"/>.
/// </summary>
/// <returns>True if it can be added, false otherwise.</returns>
bool CanAddMechanism(IMechanism mechanism);
/// <summary>
/// Tries to add a <see cref="IMechanism"/> to this body.
/// </summary>
/// <param name="mechanism">The mechanism to add.</param>
/// <param name="force">
/// Whether or not to check if the mechanism is compatible.
/// Passing true does not guarantee it to be added, for example if
/// it was already added before.
/// </param>
/// <returns>true if added, false otherwise even if it was already added.</returns>
bool TryAddMechanism(IMechanism mechanism, bool force = false);
/// <summary>
/// Tries to remove the given <see cref="mechanism"/> from this
/// <see cref="IBodyPart"/>.
/// </summary>
/// <param name="mechanism">The mechanism to remove.</param>
/// <returns>True if it was removed, false otherwise.</returns>
bool RemoveMechanism(IMechanism mechanism);
/// <summary>
/// Tries to remove the given <see cref="mechanism"/> from this
/// <see cref="IBodyPart"/> and drops it at the specified coordinates.
/// </summary>
/// <param name="mechanism">The mechanism to remove.</param>
/// <param name="dropAt">The coordinates to drop it at.</param>
/// <returns>True if it was removed, false otherwise.</returns>
bool RemoveMechanism(IMechanism mechanism, EntityCoordinates dropAt);
/// <summary>
/// Tries to destroy the given <see cref="IMechanism"/> from
/// this <see cref="IBodyPart"/>.
/// The mechanism won't be deleted if it is not in this body part.
/// </summary>
/// <returns>
/// True if the mechanism was in this body part and destroyed,
/// false otherwise.
/// </returns>
bool DeleteMechanism(IMechanism mechanism);
/// <summary>
/// Gibs the body part.
/// </summary>
void Gib();
}
}

View File

@@ -11,7 +11,7 @@ namespace Content.Shared.Body.Part
public interface IBodyPartAdded : IComponent
{
/// <summary>
/// Called when a <see cref="IBodyPart"/> is added to the
/// Called when a <see cref="SharedBodyPartComponent"/> is added to the
/// entity owning this component.
/// </summary>
/// <param name="args">Information about the part that was added.</param>
@@ -20,7 +20,7 @@ namespace Content.Shared.Body.Part
public class BodyPartAddedEventArgs : EventArgs
{
public BodyPartAddedEventArgs(string slot, IBodyPart part)
public BodyPartAddedEventArgs(string slot, SharedBodyPartComponent part)
{
Slot = slot;
Part = part;
@@ -34,6 +34,6 @@ namespace Content.Shared.Body.Part
/// <summary>
/// The part that was added.
/// </summary>
public IBodyPart Part { get; }
public SharedBodyPartComponent Part { get; }
}
}

View File

@@ -10,7 +10,7 @@ namespace Content.Shared.Body.Part
public interface IBodyPartRemoved
{
/// <summary>
/// Called when a <see cref="IBodyPart"/> is removed from the
/// Called when a <see cref="SharedBodyPartComponent"/> is removed from the
/// entity owning this component.
/// </summary>
/// <param name="args">Information about the part that was removed.</param>
@@ -19,7 +19,7 @@ namespace Content.Shared.Body.Part
public class BodyPartRemovedEventArgs : EventArgs
{
public BodyPartRemovedEventArgs(string slot, IBodyPart part)
public BodyPartRemovedEventArgs(string slot, SharedBodyPartComponent part)
{
Slot = slot;
Part = part;
@@ -33,6 +33,6 @@ namespace Content.Shared.Body.Part
/// <summary>
/// The part that was removed.
/// </summary>
public IBodyPart Part { get; }
public SharedBodyPartComponent Part { get; }
}
}

View File

@@ -5,10 +5,10 @@ using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Shared.Body.Part.Property
{
/// <summary>
/// Property attachable to a <see cref="IBodyPart"/>.
/// Property attachable to a <see cref="SharedBodyPartComponent"/>.
/// For example, this is used to define the speed capabilities of a leg.
/// The movement system will look for a <see cref="LegComponent"/> on all
/// <see cref="IBodyPart"/>.
/// <see cref="SharedBodyPartComponent"/>.
/// </summary>
public abstract class BodyPartPropertyComponent : Component, IBodyPartProperty
{

View File

@@ -5,7 +5,7 @@ using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Shared.Body.Part.Property
{
/// <summary>
/// Defines the length of a <see cref="IBodyPart"/>.
/// Defines the length of a <see cref="SharedBodyPartComponent"/>.
/// </summary>
[RegisterComponent]
public class ExtensionComponent : BodyPartPropertyComponent

View File

@@ -4,7 +4,7 @@ using Robust.Shared.GameObjects;
namespace Content.Shared.Body.Part.Property
{
/// <summary>
/// Defines a <see cref="IBodyPart"/> as being able to grasp around an entity,
/// Defines a <see cref="SharedBodyPartComponent"/> as being able to grasp around an entity,
/// for example picking up an item.
/// </summary>
// TODO BODY Implement

View File

@@ -4,7 +4,7 @@ using Robust.Shared.GameObjects;
namespace Content.Shared.Body.Part.Property
{
/// <summary>
/// Defines a property for a <see cref="IBodyPart"/>.
/// Defines a property for a <see cref="SharedBodyPartComponent"/>.
/// </summary>
public interface IBodyPartProperty : IComponent
{

View File

@@ -5,7 +5,7 @@ using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Shared.Body.Part.Property
{
/// <summary>
/// Defines the speed at which a <see cref="IBodyPart"/> can move.
/// Defines the speed at which a <see cref="SharedBodyPartComponent"/> can move.
/// </summary>
[RegisterComponent]
public class LegComponent : BodyPartPropertyComponent

View File

@@ -1,9 +1,12 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Content.Shared.Body.Behavior;
using Content.Shared.Body.Components;
using Content.Shared.Body.Mechanism;
using Content.Shared.Body.Part.Property;
using Content.Shared.Body.Surgery;
using Content.Shared.NetIDs;
using Robust.Shared.GameObjects;
@@ -17,24 +20,24 @@ using Robust.Shared.ViewVariables;
namespace Content.Shared.Body.Part
{
public abstract class SharedBodyPartComponent : Component, IBodyPart
public abstract class SharedBodyPartComponent : Component, IBodyPartContainer
{
public override string Name => "BodyPart";
public override uint? NetID => ContentNetIDs.BODY_PART;
private IBody? _body;
private SharedBodyComponent? _body;
// TODO BODY Remove
[DataField("mechanisms")]
private List<string> _mechanismIds = new();
private readonly List<string> _mechanismIds = new();
public IReadOnlyList<string> MechanismIds => _mechanismIds;
[ViewVariables]
private readonly HashSet<IMechanism> _mechanisms = new();
private readonly HashSet<SharedMechanismComponent> _mechanisms = new();
[ViewVariables]
public IBody? Body
public SharedBodyComponent? Body
{
get => _body;
set
@@ -59,13 +62,25 @@ namespace Content.Shared.Body.Part
}
}
/// <summary>
/// The string to show when displaying this part's name to players.
/// </summary>
[ViewVariables]
public string DisplayName => Name;
/// <summary>
/// <see cref="BodyPartType"/> that this <see cref="IBodyPart"/> is considered
/// to be.
/// For example, <see cref="BodyPartType.Arm"/>.
/// </summary>
[ViewVariables]
[DataField("partType")]
public BodyPartType PartType { get; private set; } = BodyPartType.Other;
/// <summary>
/// Determines how many mechanisms can be fit inside this
/// <see cref="SharedBodyPartComponent"/>.
/// </summary>
[ViewVariables] [DataField("size")] public int Size { get; private set; } = 1;
[ViewVariables] public int SizeUsed { get; private set; }
@@ -74,7 +89,7 @@ namespace Content.Shared.Body.Part
// TODO BODY surgerydata
/// <summary>
/// What types of BodyParts this <see cref="IBodyPart"/> can easily attach to.
/// What types of BodyParts this <see cref="SharedBodyPartComponent"/> can easily attach to.
/// For the most part, most limbs aren't universal and require extra work to
/// attach between types.
/// </summary>
@@ -82,17 +97,14 @@ namespace Content.Shared.Body.Part
[DataField("compatibility")]
public BodyPartCompatibility Compatibility { get; private set; } = BodyPartCompatibility.Universal;
/// <summary>
/// Set of all <see cref="IMechanism"/> currently inside this
/// <see cref="IBodyPart"/>.
/// </summary>
// TODO BODY Mechanisms occupying different parts at the body level
[ViewVariables]
public IReadOnlyCollection<IMechanism> Mechanisms => _mechanisms;
public IReadOnlyCollection<SharedMechanismComponent> Mechanisms => _mechanisms;
// TODO BODY Replace with a simulation of organs
/// <summary>
/// Represents if body part is vital for creature.
/// If the last vital body part is removed creature dies
/// Whether or not the owning <see cref="Body"/> will die if all
/// <see cref="SharedBodyPartComponent"/>s of this type are removed from it.
/// </summary>
[ViewVariables]
[DataField("vital")]
@@ -105,7 +117,7 @@ namespace Content.Shared.Body.Part
[ViewVariables]
public ISurgeryData? SurgeryDataComponent => Owner.GetComponentOrNull<ISurgeryData>();
protected virtual void OnAddMechanism(IMechanism mechanism)
protected virtual void OnAddMechanism(SharedMechanismComponent mechanism)
{
var prototypeId = mechanism.Owner.Prototype!.ID;
@@ -120,7 +132,7 @@ namespace Content.Shared.Body.Part
Dirty();
}
protected virtual void OnRemoveMechanism(IMechanism mechanism)
protected virtual void OnRemoveMechanism(SharedMechanismComponent mechanism)
{
_mechanismIds.Remove(mechanism.Owner.Prototype!.ID);
mechanism.Part = null;
@@ -176,11 +188,6 @@ namespace Content.Shared.Body.Part
return SurgeryDataComponent?.CheckSurgery(surgery) ?? false;
}
/// <summary>
/// Attempts to perform surgery on this <see cref="IBodyPart"/> with the given
/// tool.
/// </summary>
/// <returns>True if successful, false if there was an error.</returns>
public bool AttemptSurgery(SurgeryType toolType, IBodyPartContainer target, ISurgeon surgeon, IEntity performer)
{
DebugTools.AssertNotNull(toolType);
@@ -191,14 +198,14 @@ namespace Content.Shared.Body.Part
return SurgeryDataComponent?.PerformSurgery(toolType, target, surgeon, performer) ?? false;
}
public bool CanAttachPart(IBodyPart part)
public bool CanAttachPart(SharedBodyPartComponent part)
{
DebugTools.AssertNotNull(part);
return SurgeryDataComponent?.CanAttachBodyPart(part) ?? false;
}
public virtual bool CanAddMechanism(IMechanism mechanism)
public virtual bool CanAddMechanism(SharedMechanismComponent mechanism)
{
DebugTools.AssertNotNull(mechanism);
@@ -208,19 +215,16 @@ namespace Content.Shared.Body.Part
}
/// <summary>
/// Tries to add a mechanism onto this body part.
/// Tries to add a <see cref="SharedMechanismComponent"/> to this part.
/// </summary>
/// <param name="mechanism">The mechanism to try to add.</param>
/// <param name="mechanism">The mechanism to add.</param>
/// <param name="force">
/// Whether or not to check if the mechanism can be added.
/// Whether or not to check if the mechanism is compatible.
/// Passing true does not guarantee it to be added, for example if
/// it was already added before.
/// </param>
/// <returns>
/// True if successful, false if there was an error
/// (e.g. not enough room in <see cref="IBodyPart"/>).
/// Will return false even when forced if the mechanism is already
/// added in this <see cref="IBodyPart"/>.
/// </returns>
public bool TryAddMechanism(IMechanism mechanism, bool force = false)
/// <returns>true if added, false otherwise even if it was already added.</returns>
public bool TryAddMechanism(SharedMechanismComponent mechanism, bool force = false)
{
DebugTools.AssertNotNull(mechanism);
@@ -239,7 +243,12 @@ namespace Content.Shared.Body.Part
return true;
}
public bool RemoveMechanism(IMechanism mechanism)
/// <summary>
/// Tries to remove the given <see cref="mechanism"/> from this part.
/// </summary>
/// <param name="mechanism">The mechanism to remove.</param>
/// <returns>True if it was removed, false otherwise.</returns>
public bool RemoveMechanism(SharedMechanismComponent mechanism)
{
DebugTools.AssertNotNull(mechanism);
@@ -253,7 +262,14 @@ namespace Content.Shared.Body.Part
return true;
}
public bool RemoveMechanism(IMechanism mechanism, EntityCoordinates coordinates)
/// <summary>
/// Tries to remove the given <see cref="mechanism"/> from this
/// part and drops it at the specified coordinates.
/// </summary>
/// <param name="mechanism">The mechanism to remove.</param>
/// <param name="coordinates">The coordinates to drop it at.</param>
/// <returns>True if it was removed, false otherwise.</returns>
public bool RemoveMechanism(SharedMechanismComponent mechanism, EntityCoordinates coordinates)
{
if (RemoveMechanism(mechanism))
{
@@ -264,7 +280,16 @@ namespace Content.Shared.Body.Part
return false;
}
public bool DeleteMechanism(IMechanism mechanism)
/// <summary>
/// Tries to destroy the given <see cref="SharedMechanismComponent"/> from
/// this part.
/// The mechanism won't be deleted if it is not in this body part.
/// </summary>
/// <returns>
/// True if the mechanism was in this body part and destroyed,
/// false otherwise.
/// </returns>
public bool DeleteMechanism(SharedMechanismComponent mechanism)
{
DebugTools.AssertNotNull(mechanism);
@@ -277,7 +302,7 @@ namespace Content.Shared.Body.Part
return true;
}
private void AddedToBody(IBody body)
private void AddedToBody(SharedBodyComponent body)
{
Owner.Transform.LocalRotation = 0;
Owner.Transform.AttachParent(body.Owner);
@@ -289,7 +314,7 @@ namespace Content.Shared.Body.Part
}
}
private void RemovedFromBody(IBody old)
private void RemovedFromBody(SharedBodyComponent old)
{
if (!Owner.Transform.Deleted)
{
@@ -304,10 +329,13 @@ namespace Content.Shared.Body.Part
}
}
protected virtual void OnAddedToBody(IBody body) { }
protected virtual void OnAddedToBody(SharedBodyComponent body) { }
protected virtual void OnRemovedFromBody(IBody old) { }
protected virtual void OnRemovedFromBody(SharedBodyComponent old) { }
/// <summary>
/// Gibs the body part.
/// </summary>
public virtual void Gib()
{
foreach (var mechanism in _mechanisms)
@@ -315,12 +343,44 @@ namespace Content.Shared.Body.Part
RemoveMechanism(mechanism);
}
}
public bool HasProperty(Type type)
{
return Owner.HasComponent(type);
}
public bool HasProperty<T>() where T : class, IBodyPartProperty
{
return HasProperty(typeof(T));
}
public bool TryGetProperty(Type type,
[NotNullWhen(true)] out IBodyPartProperty? property)
{
if (!Owner.TryGetComponent(type, out var component))
{
property = null;
return false;
}
return (property = component as IBodyPartProperty) != null;
}
public bool TryGetProperty<T>([NotNullWhen(true)] out T? property) where T : class, IBodyPartProperty
{
return Owner.TryGetComponent(out property);
}
public bool HasMechanismBehavior<T>() where T : SharedMechanismBehavior
{
return Mechanisms.Any(m => m.HasBehavior<T>());
}
}
[Serializable, NetSerializable]
public class BodyPartComponentState : ComponentState
{
[NonSerialized] private List<IMechanism>? _mechanisms;
[NonSerialized] private List<SharedMechanismComponent>? _mechanisms;
public readonly EntityUid[] MechanismIds;
@@ -329,7 +389,7 @@ namespace Content.Shared.Body.Part
MechanismIds = mechanismIds;
}
public List<IMechanism> Mechanisms(IEntityManager? entityManager = null)
public List<SharedMechanismComponent> Mechanisms(IEntityManager? entityManager = null)
{
if (_mechanisms != null)
{
@@ -338,7 +398,7 @@ namespace Content.Shared.Body.Part
entityManager ??= IoCManager.Resolve<IEntityManager>();
var mechanisms = new List<IMechanism>(MechanismIds.Length);
var mechanisms = new List<SharedMechanismComponent>(MechanismIds.Length);
foreach (var id in MechanismIds)
{
@@ -347,7 +407,7 @@ namespace Content.Shared.Body.Part
continue;
}
if (!entity.TryGetComponent(out IMechanism? mechanism))
if (!entity.TryGetComponent(out SharedMechanismComponent? mechanism))
{
continue;
}

View File

@@ -11,7 +11,7 @@ using Robust.Shared.ViewVariables;
namespace Content.Shared.Body.Preset
{
/// <summary>
/// Defines the <see cref="IBodyPart"/>s used in a <see cref="IBody"/>.
/// Defines the parts used in a body.
/// </summary>
[Prototype("bodyPreset")]
[Serializable, NetSerializable]

View File

@@ -37,7 +37,7 @@ namespace Content.Shared.Body.Slot
/// The part currently in this slot, if any.
/// </summary>
[ViewVariables]
public IBodyPart? Part { get; private set; }
public SharedBodyPartComponent? Part { get; private set; }
/// <summary>
/// List of slots that this slot connects to.
@@ -45,21 +45,21 @@ namespace Content.Shared.Body.Slot
[ViewVariables]
public HashSet<BodyPartSlot> Connections { get; private set; }
public event Action<IBodyPart>? PartAdded;
public event Action<SharedBodyPartComponent>? PartAdded;
public event Action<IBodyPart>? PartRemoved;
public event Action<SharedBodyPartComponent>? PartRemoved;
internal void SetConnectionsInternal(IEnumerable<BodyPartSlot> connections)
{
Connections = new HashSet<BodyPartSlot>(connections);
}
public bool CanAddPart(IBodyPart part)
public bool CanAddPart(SharedBodyPartComponent part)
{
return Part == null && part.PartType == PartType;
}
public bool TryAddPart(IBodyPart part)
public bool TryAddPart(SharedBodyPartComponent part)
{
if (!CanAddPart(part))
{
@@ -70,7 +70,7 @@ namespace Content.Shared.Body.Slot
return true;
}
public void SetPart(IBodyPart part)
public void SetPart(SharedBodyPartComponent part)
{
if (Part != null)
{

View File

@@ -12,7 +12,7 @@ namespace Content.Shared.Body.Surgery
public interface ISurgeon
{
public delegate void MechanismRequestCallback(
IMechanism target,
SharedMechanismComponent target,
IBodyPartContainer container,
ISurgeon surgeon,
IEntity performer);
@@ -25,10 +25,10 @@ namespace Content.Shared.Body.Surgery
/// <summary>
/// When performing a surgery, the <see cref="SurgeryDataComponent"/>
/// may sometimes require selecting from a set of
/// <see cref="IMechanism"/>s to operate on.
/// <see cref="SharedMechanismComponent"/>s to operate on.
/// This function is called in that scenario, and it is expected that you call
/// the callback with one <see cref="IMechanism"/> from the provided list.
/// the callback with one <see cref="SharedMechanismComponent"/> from the provided list.
/// </summary>
public void RequestMechanism(IEnumerable<IMechanism> options, MechanismRequestCallback callback);
public void RequestMechanism(IEnumerable<SharedMechanismComponent> options, MechanismRequestCallback callback);
}
}

View File

@@ -6,21 +6,21 @@ using Robust.Shared.GameObjects;
namespace Content.Shared.Body.Surgery
{
/// <summary>
/// Represents the current surgery state of a <see cref="IBodyPart"/>.
/// Represents the current surgery state of a <see cref="SharedBodyPartComponent"/>.
/// </summary>
public interface ISurgeryData : IComponent
{
public delegate void SurgeryAction(IBodyPartContainer container, ISurgeon surgeon, IEntity performer);
/// <summary>
/// The <see cref="IBodyPart"/> this
/// The <see cref="SharedBodyPartComponent"/> this
/// <see cref="ISurgeryData"/> is attached to.
/// </summary>
public IBodyPart? Parent { get; }
public SharedBodyPartComponent? Parent { get; }
/// <summary>
/// The <see cref="BodyPartType"/> of the parent
/// <see cref="IBodyPart"/>.
/// <see cref="SharedBodyPartComponent"/>.
/// </summary>
public BodyPartType? ParentType { get; }
@@ -31,18 +31,18 @@ namespace Content.Shared.Body.Surgery
public string GetDescription();
/// <summary>
/// Returns whether a <see cref="IMechanism"/> can be added into the
/// <see cref="IBodyPart"/> this <see cref="ISurgeryData"/>
/// Returns whether a <see cref="SharedMechanismComponent"/> can be added into the
/// <see cref="SharedBodyPartComponent"/> this <see cref="ISurgeryData"/>
/// represents.
/// </summary>
public bool CanAddMechanism(IMechanism mechanism);
public bool CanAddMechanism(SharedMechanismComponent mechanism);
/// <summary>
/// Returns whether the given <see cref="IBodyPart"/> can be connected
/// to the <see cref="IBodyPart"/> this <see cref="ISurgeryData"/>
/// Returns whether the given <see cref="SharedBodyPartComponent"/> can be connected
/// to the <see cref="SharedBodyPartComponent"/> this <see cref="ISurgeryData"/>
/// represents.
/// </summary>
public bool CanAttachBodyPart(IBodyPart part);
public bool CanAttachBodyPart(SharedBodyPartComponent part);
/// <summary>
/// Gets the delegate corresponding to the surgery step using the given
@@ -56,7 +56,7 @@ namespace Content.Shared.Body.Surgery
/// <summary>
/// Returns whether the given <see cref="SurgeryType"/> can be used to
/// perform a surgery on the <see cref="IBodyPart"/> this
/// perform a surgery on the <see cref="SharedBodyPartComponent"/> this
/// <see cref="ISurgeryData"/> represents.
/// </summary>
public bool CheckSurgery(SurgeryType toolType)

View File

@@ -11,7 +11,7 @@ using Robust.Shared.ViewVariables;
namespace Content.Shared.Body.Template
{
/// <summary>
/// Defines the layout of a <see cref="IBody"/>.
/// Defines the layout of a body.
/// </summary>
[Prototype("bodyTemplate")]
[Serializable, NetSerializable]

View File

@@ -5,7 +5,7 @@ namespace Content.Shared.CharacterAppearance
{
public static class HumanoidVisualLayersExtension
{
public static HumanoidVisualLayers? ToHumanoidLayer(this IBodyPart part)
public static HumanoidVisualLayers? ToHumanoidLayer(this SharedBodyPartComponent part)
{
return part.PartType switch
{

View File

@@ -12,6 +12,7 @@ namespace Content.Shared.Damage
/// <see cref="SharedBodyComponent"/> may require it for extra data
/// (such as selecting which limb to target).
/// </summary>
// TODO BODY: Remove and pretend it never existed
public class DamageChangeParams : EventArgs
{
}

View File

@@ -131,7 +131,7 @@ namespace Content.Shared.Disposal.Components
// TODO: Probably just need a disposable tag.
if (!entity.TryGetComponent(out SharedItemComponent? storable) &&
!entity.HasComponent<IBody>())
!entity.HasComponent<SharedBodyComponent>())
{
return false;
}

View File

@@ -82,7 +82,7 @@ namespace Content.Shared.MedicalScanner
bool IDragDropOn.CanDragDropOn(DragDropEvent eventArgs)
{
return eventArgs.Dragged.HasComponent<IBody>();
return eventArgs.Dragged.HasComponent<SharedBodyComponent>();
}
public abstract bool DragDropOn(DragDropEvent eventArgs);