#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 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 { public string? TemplateName { get; } public string? PresetName { get; } // TODO BODY tf is this /// /// Maps all parts on this template to its BodyPartType. /// For instance, "right arm" is mapped to "BodyPartType.arm" on the humanoid /// template. /// public Dictionary Slots { get; } /// /// Maps slots to the part filling each one. /// public IReadOnlyDictionary Parts { get; } // TODO BODY what am i doing /// /// Maps limb name to the list of their connections to other limbs. /// For instance, on the humanoid template "torso" is 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 only one /// way has to be defined, i.e., "torso" to "left arm" will automatically /// map "left arm" to "torso". /// public Dictionary> Connections { get; } /// /// Maps a template slot to the ID of the /// that should fill it. E.g. "right arm" : "BodyPart.arm.basic_human". /// public IReadOnlyDictionary PartIds { get; } /// /// Adds the given into the given slot. /// /// True if successful, false otherwise. bool TryAddPart(string slot, IBodyPart part, bool force = false); bool HasPart(string slot); /// /// 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! KeyValuePair SlotAt(int index); KeyValuePair PartAt(int index); } }