using System.Diagnostics.CodeAnalysis; using Content.Shared.Body.Components; using Content.Shared.Body.Events; using Content.Shared.Body.Organ; using Content.Shared.Body.Part; using Robust.Shared.Containers; namespace Content.Shared.Body.Systems; public partial class SharedBodySystem { private void AddOrgan( Entity organEnt, EntityUid bodyUid, EntityUid parentPartUid) { organEnt.Comp.Body = bodyUid; var addedEv = new OrganAddedEvent(parentPartUid); RaiseLocalEvent(organEnt, ref addedEv); if (organEnt.Comp.Body is not null) { var addedInBodyEv = new OrganAddedToBodyEvent(bodyUid, parentPartUid); RaiseLocalEvent(organEnt, ref addedInBodyEv); } Dirty(organEnt, organEnt.Comp); } private void RemoveOrgan(Entity organEnt, EntityUid parentPartUid) { var removedEv = new OrganRemovedEvent(parentPartUid); RaiseLocalEvent(organEnt, ref removedEv); if (organEnt.Comp.Body is { Valid: true } bodyUid) { var removedInBodyEv = new OrganRemovedFromBodyEvent(bodyUid, parentPartUid); RaiseLocalEvent(organEnt, ref removedInBodyEv); } organEnt.Comp.Body = null; Dirty(organEnt, organEnt.Comp); } /// /// Creates the specified organ slot on the parent entity. /// private OrganSlot? CreateOrganSlot(Entity parentEnt, string slotId) { if (!Resolve(parentEnt, ref parentEnt.Comp, logMissing: false)) return null; Containers.EnsureContainer(parentEnt, GetOrganContainerId(slotId)); var slot = new OrganSlot(slotId); parentEnt.Comp.Organs.Add(slotId, slot); return slot; } /// /// Attempts to create the specified organ slot on the specified parent if it exists. /// public bool TryCreateOrganSlot( EntityUid? parent, string slotId, [NotNullWhen(true)] out OrganSlot? slot, BodyPartComponent? part = null) { slot = null; if (parent is null || !Resolve(parent.Value, ref part, logMissing: false)) { return false; } Containers.EnsureContainer(parent.Value, GetOrganContainerId(slotId)); slot = new OrganSlot(slotId); return part.Organs.TryAdd(slotId, slot.Value); } /// /// Returns whether the slotId exists on the partId. /// public bool CanInsertOrgan( EntityUid partId, string slotId, BodyPartComponent? part = null) { return Resolve(partId, ref part) && part.Organs.ContainsKey(slotId); } /// /// Returns whether the specified organ slot exists on the partId. /// public bool CanInsertOrgan( EntityUid partId, OrganSlot slot, BodyPartComponent? part = null) { return CanInsertOrgan(partId, slot.Id, part); } public bool InsertOrgan( EntityUid partId, EntityUid organId, string slotId, BodyPartComponent? part = null, OrganComponent? organ = null) { if (!Resolve(organId, ref organ, logMissing: false) || !Resolve(partId, ref part, logMissing: false) || !CanInsertOrgan(partId, slotId, part)) { return false; } var containerId = GetOrganContainerId(slotId); return Containers.TryGetContainer(partId, containerId, out var container) && Containers.Insert(organId, container); } /// /// Removes the organ if it is inside of a body part. /// public bool RemoveOrgan(EntityUid organId, OrganComponent? organ = null) { if (!Containers.TryGetContainingContainer((organId, null, null), out var container)) return false; var parent = container.Owner; return HasComp(parent) && Containers.Remove(organId, container); } /// /// Tries to add this organ to any matching slot on this body part. /// public bool AddOrganToFirstValidSlot( EntityUid partId, EntityUid organId, BodyPartComponent? part = null, OrganComponent? organ = null) { if (!Resolve(partId, ref part, logMissing: false) || !Resolve(organId, ref organ, logMissing: false)) { return false; } foreach (var slotId in part.Organs.Keys) { InsertOrgan(partId, organId, slotId, part, organ); return true; } return false; } /// /// Returns a list of Entity<, > /// for each organ of the body /// /// The component that we want to return /// The body to check the organs of public List> GetBodyOrganEntityComps( Entity entity) where T : IComponent { if (!Resolve(entity, ref entity.Comp)) return new List>(); var query = GetEntityQuery(); var list = new List>(3); foreach (var organ in GetBodyOrgans(entity.Owner, entity.Comp)) { if (query.TryGetComponent(organ.Id, out var comp)) list.Add((organ.Id, comp, organ.Component)); } return list; } /// /// Tries to get a list of ValueTuples of and OrganComponent on each organs /// in the given body. /// /// The body entity id to check on. /// The list of components. /// The body to check for organs on. /// The component to check for. /// Whether any were found. public bool TryGetBodyOrganEntityComps( Entity entity, [NotNullWhen(true)] out List>? comps) where T : IComponent { if (!Resolve(entity.Owner, ref entity.Comp)) { comps = null; return false; } comps = GetBodyOrganEntityComps(entity); if (comps.Count != 0) return true; comps = null; return false; } }