#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.Template; using Robust.Shared.Interfaces.GameObjects; namespace Content.Shared.GameObjects.Components.Body { /// /// Component representing a collection of s /// attached to each other. /// public interface IBody : IComponent, IBodyPartContainer { /// /// The name of the used by this /// . /// public string? TemplateName { get; } /// /// The name of the used by this /// . /// public string? PresetName { get; } // TODO BODY Part slots // TODO BODY Sensible templates /// /// Mapping of slots in this body to their /// . /// public Dictionary Slots { get; } /// /// Mapping of slots to the filling each one. /// public IReadOnlyDictionary Parts { get; } /// /// Mapping of slots to which other slots they connect to. /// For example, the torso could be mapped to a list containing /// "right arm", "left arm", "left leg", and "right leg". /// This is mapped both ways during runtime, but in the prototype /// it only has to be defined one-way, "torso": "left arm" will automatically /// map "left arm" to "torso" as well. /// public Dictionary> Connections { get; } /// /// Mapping of template slots to the ID of the /// that should fill it. E.g. "right arm" : "BodyPart.arm.basic_human". /// public IReadOnlyDictionary PartIds { get; } /// /// Attempts to add a part to the given slot. /// /// The slot to add this part to. /// The part to add. /// /// Whether or not to check for the validity of the given . /// Passing true does not guarantee it to be added, for example if it /// had already been added before. /// /// /// true if the part was added, false otherwise even if it was already added. /// bool TryAddPart(string slot, IBodyPart part, bool force = false); /// /// 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 slot); /// /// 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 reference, potentially /// dropping other BodyParts if they /// were hanging off of it. /// void 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 slot); /// /// 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 string? slotName); /// /// 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 . /// /// /// True if the part was dropped, false otherwise. /// bool TryDropPart(IBodyPart part, [NotNullWhen(true)] out List? 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); /// /// Finds the central , if any, of this body based on /// the . For humans, this is the torso. /// /// The if one exists, null otherwise. IBodyPart? CenterPart(); /// /// Returns whether the given part slot name exists within the current /// . /// /// The slot to check for. /// True if the slot exists in this body, false otherwise. bool HasSlot(string 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 slot, [NotNullWhen(true)] out IBodyPart? result); /// /// Finds the slotName 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 string? slot); /// /// Finds the in the given /// if one exists. /// /// The slot to search in. /// /// The of that slot, if any. /// /// True if found, false otherwise. bool TryGetSlotType(string slot, out BodyPartType result); /// /// Finds the names of all slots connected to the given /// for the template. /// /// The slot to search in. /// The connections found, if any. /// True if the connections are found, false otherwise. bool TryGetSlotConnections(string slot, [NotNullWhen(true)] out List? connections); /// /// Grabs all occupied slots connected to the given slot, /// regardless of whether the given is occupied. /// /// The slot name to find connections from. /// The connected body parts, if any. /// /// True if successful, false if the slot couldn't be found on this body. /// bool TryGetPartConnections(string slot, [NotNullWhen(true)] out List? connections); /// /// Grabs all parts connected to the given , regardless /// of whether the given is occupied. /// /// The part to find connections from. /// The connected body parts, if any. /// /// True if successful, false if the part couldn't be found on this body. /// bool TryGetPartConnections(IBodyPart part, [NotNullWhen(true)] out List? connections); /// /// Finds all s of the given type in this body. /// /// A list of parts of that type. List 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. List<(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. List<(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. KeyValuePair 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. /// void Gib(bool gibParts = false); } }