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