]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Body code cleanup (#24946)
author0x6273 <0x40@keemail.me>
Thu, 28 Mar 2024 00:48:37 +0000 (01:48 +0100)
committerGitHub <noreply@github.com>
Thu, 28 Mar 2024 00:48:37 +0000 (17:48 -0700)
* Fix test

* Kill float accumulators

* Use entity proxy methods

* DataField auto name generation where possible

* Kill comp properties

* Clean up server comps

* Make events record structs

* Clean up shared body code

* Clean up server body code

* Rename organ events to be same names as in med refactor

32 files changed:
Content.IntegrationTests/Tests/Body/LungTest.cs
Content.Server/Bed/BedSystem.cs
Content.Server/Body/Commands/AddHandCommand.cs
Content.Server/Body/Commands/AttachBodyPartCommand.cs
Content.Server/Body/Components/BeingGibbedEvent.cs
Content.Server/Body/Components/BloodstreamComponent.cs
Content.Server/Body/Components/InternalsComponent.cs
Content.Server/Body/Components/LungComponent.cs
Content.Server/Body/Components/MetabolizerComponent.cs
Content.Server/Body/Components/RespiratorComponent.cs
Content.Server/Body/Components/StomachComponent.cs
Content.Server/Body/Components/ThermalRegulatorComponent.cs
Content.Server/Body/Systems/BloodstreamSystem.cs
Content.Server/Body/Systems/BodySystem.cs
Content.Server/Body/Systems/BrainSystem.cs
Content.Server/Body/Systems/InternalsSystem.cs
Content.Server/Body/Systems/LungSystem.cs
Content.Server/Body/Systems/MetabolizerSystem.cs
Content.Server/Body/Systems/RespiratorSystem.cs
Content.Server/Body/Systems/StomachSystem.cs
Content.Server/Body/Systems/ThermalRegulatorSystem.cs
Content.Server/Hands/Systems/HandsSystem.cs
Content.Server/Species/Systems/NymphSystem.cs
Content.Shared/ActionBlocker/ActionBlockerSystem.cs
Content.Shared/Body/Events/MechanismBodyEvents.cs
Content.Shared/Body/Events/ShiverAttemptEvent.cs
Content.Shared/Body/Events/SweatAttemptEvent.cs
Content.Shared/Body/Organ/OrganComponent.cs
Content.Shared/Body/Part/BodyPartEvents.cs
Content.Shared/Body/Systems/SharedBodySystem.Body.cs
Content.Shared/Body/Systems/SharedBodySystem.Organs.cs
Content.Shared/Body/Systems/SharedBodySystem.Parts.cs

index f2e19849b0022528b20edffb56005297ffd49ae8..dce3741c98dcf7f8412e3b9197a784336547b20d 100644 (file)
@@ -9,7 +9,6 @@ using Robust.Shared.Configuration;
 using Robust.Shared.GameObjects;
 using Robust.Shared.Map;
 using Robust.Shared.Map.Components;
-using Robust.Shared.Maths;
 using System.Linq;
 using System.Numerics;
 
@@ -61,12 +60,11 @@ namespace Content.IntegrationTests.Tests.Body
             var mapManager = server.ResolveDependency<IMapManager>();
             var entityManager = server.ResolveDependency<IEntityManager>();
             var mapLoader = entityManager.System<MapLoaderSystem>();
-            RespiratorSystem respSys = default;
-            MetabolizerSystem metaSys = default;
 
             MapId mapId;
             EntityUid? grid = null;
             BodyComponent body = default;
+            RespiratorComponent resp = default;
             EntityUid human = default;
             GridAtmosphereComponent relevantAtmos = default;
             var startingMoles = 0.0f;
@@ -99,17 +97,15 @@ namespace Content.IntegrationTests.Tests.Body
 
             await server.WaitAssertion(() =>
             {
-                var coords = new Vector2(0.5f, -1f);
-                var coordinates = new EntityCoordinates(grid.Value, coords);
+                var center = new Vector2(0.5f, 0.5f);
+                var coordinates = new EntityCoordinates(grid.Value, center);
                 human = entityManager.SpawnEntity("HumanLungDummy", coordinates);
-                respSys = entityManager.System<RespiratorSystem>();
-                metaSys = entityManager.System<MetabolizerSystem>();
                 relevantAtmos = entityManager.GetComponent<GridAtmosphereComponent>(grid.Value);
-                startingMoles = GetMapMoles();
+                startingMoles = 100f; // Hardcoded because GetMapMoles returns 900 here for some reason.
 
 #pragma warning disable NUnit2045
                 Assert.That(entityManager.TryGetComponent(human, out body), Is.True);
-                Assert.That(entityManager.HasComponent<RespiratorComponent>(human), Is.True);
+                Assert.That(entityManager.TryGetComponent(human, out resp), Is.True);
 #pragma warning restore NUnit2045
             });
 
@@ -118,18 +114,19 @@ namespace Content.IntegrationTests.Tests.Body
             var inhaleCycles = 100;
             for (var i = 0; i < inhaleCycles; i++)
             {
-                await server.WaitAssertion(() =>
-                {
-                    // inhale
-                    respSys.Update(2.0f);
-                    Assert.That(GetMapMoles(), Is.LessThan(startingMoles));
-
-                    // metabolize + exhale
-                    metaSys.Update(1.0f);
-                    metaSys.Update(1.0f);
-                    respSys.Update(2.0f);
-                    Assert.That(GetMapMoles(), Is.EqualTo(startingMoles).Within(0.0002));
-                });
+                // Breathe in
+                await PoolManager.WaitUntil(server, () => resp.Status == RespiratorStatus.Exhaling);
+                Assert.That(
+                    GetMapMoles(), Is.LessThan(startingMoles),
+                    "Did not inhale in any gas"
+                );
+
+                // Breathe out
+                await PoolManager.WaitUntil(server, () => resp.Status == RespiratorStatus.Inhaling);
+                Assert.That(
+                    GetMapMoles(), Is.EqualTo(startingMoles).Within(0.0002),
+                    "Did not exhale as much gas as was inhaled"
+                );
             }
 
             await pair.CleanReturnAsync();
index 131bd4b18298177f63cf13098995e6436ad97af2..49021c142f4fc6939716cac2a22ac8b262cb6517 100644 (file)
@@ -93,9 +93,8 @@ namespace Content.Server.Bed
             if (!this.IsPowered(uid, EntityManager))
                 return;
 
-            var metabolicEvent = new ApplyMetabolicMultiplierEvent
-                {Uid = args.BuckledEntity, Multiplier = component.Multiplier, Apply = args.Buckling};
-            RaiseLocalEvent(args.BuckledEntity, metabolicEvent);
+            var metabolicEvent = new ApplyMetabolicMultiplierEvent(args.BuckledEntity, component.Multiplier, args.Buckling);
+            RaiseLocalEvent(args.BuckledEntity, ref metabolicEvent);
         }
 
         private void OnPowerChanged(EntityUid uid, StasisBedComponent component, ref PowerChangedEvent args)
@@ -121,9 +120,8 @@ namespace Content.Server.Bed
 
             foreach (var buckledEntity in strap.BuckledEntities)
             {
-                var metabolicEvent = new ApplyMetabolicMultiplierEvent
-                    {Uid = buckledEntity, Multiplier = component.Multiplier, Apply = shouldApply};
-                RaiseLocalEvent(buckledEntity, metabolicEvent);
+                var metabolicEvent = new ApplyMetabolicMultiplierEvent(buckledEntity, component.Multiplier, shouldApply);
+                RaiseLocalEvent(buckledEntity, ref metabolicEvent);
             }
         }
     }
index 655d0c88f9ba10bca9fa948a3c9c64fb91d4d2f7..3e006c539c778a94409d6f805f666278742ec870 100644 (file)
@@ -34,7 +34,6 @@ namespace Content.Server.Body.Commands
             switch (args.Length)
             {
                 case 0:
-                {
                     if (player == null)
                     {
                         shell.WriteLine("Only a player can run this command without arguments.");
@@ -50,71 +49,68 @@ namespace Content.Server.Body.Commands
                     entity = player.AttachedEntity.Value;
                     hand = _entManager.SpawnEntity(DefaultHandPrototype, _entManager.GetComponent<TransformComponent>(entity).Coordinates);
                     break;
-                }
                 case 1:
-                {
-                    if (NetEntity.TryParse(args[0], out var uidNet) && _entManager.TryGetEntity(uidNet, out var uid))
                     {
-                        if (!_entManager.EntityExists(uid))
+                        if (NetEntity.TryParse(args[0], out var uidNet) && _entManager.TryGetEntity(uidNet, out var uid))
                         {
-                            shell.WriteLine($"No entity found with uid {uid}");
-                            return;
+                            if (!_entManager.EntityExists(uid))
+                            {
+                                shell.WriteLine($"No entity found with uid {uid}");
+                                return;
+                            }
+
+                            entity = uid.Value;
+                            hand = _entManager.SpawnEntity(DefaultHandPrototype, _entManager.GetComponent<TransformComponent>(entity).Coordinates);
+                        }
+                        else
+                        {
+                            if (player == null)
+                            {
+                                shell.WriteLine("You must specify an entity to add a hand to when using this command from the server terminal.");
+                                return;
+                            }
+
+                            if (player.AttachedEntity == null)
+                            {
+                                shell.WriteLine("You don't have an entity to add a hand to.");
+                                return;
+                            }
+
+                            entity = player.AttachedEntity.Value;
+                            hand = _entManager.SpawnEntity(args[0], _entManager.GetComponent<TransformComponent>(entity).Coordinates);
                         }
 
-                        entity = uid.Value;
-                        hand = _entManager.SpawnEntity(DefaultHandPrototype, _entManager.GetComponent<TransformComponent>(entity).Coordinates);
+                        break;
                     }
-                    else
+                case 2:
                     {
-                        if (player == null)
+                        if (!NetEntity.TryParse(args[0], out var netEnt) || !_entManager.TryGetEntity(netEnt, out var uid))
                         {
-                            shell.WriteLine("You must specify an entity to add a hand to when using this command from the server terminal.");
+                            shell.WriteLine($"{args[0]} is not a valid entity uid.");
                             return;
                         }
 
-                        if (player.AttachedEntity == null)
+                        if (!_entManager.EntityExists(uid))
                         {
-                            shell.WriteLine("You don't have an entity to add a hand to.");
+                            shell.WriteLine($"No entity exists with uid {uid}.");
                             return;
                         }
 
-                        entity = player.AttachedEntity.Value;
-                        hand = _entManager.SpawnEntity(args[0], _entManager.GetComponent<TransformComponent>(entity).Coordinates);
-                    }
-
-                    break;
-                }
-                case 2:
-                {
-                    if (!NetEntity.TryParse(args[0], out var netEnt) || !_entManager.TryGetEntity(netEnt, out var uid))
-                    {
-                        shell.WriteLine($"{args[0]} is not a valid entity uid.");
-                        return;
-                    }
+                        entity = uid.Value;
 
-                    if (!_entManager.EntityExists(uid))
-                    {
-                        shell.WriteLine($"No entity exists with uid {uid}.");
-                        return;
-                    }
+                        if (!_protoManager.HasIndex<EntityPrototype>(args[1]))
+                        {
+                            shell.WriteLine($"No hand entity exists with id {args[1]}.");
+                            return;
+                        }
 
-                    entity = uid.Value;
+                        hand = _entManager.SpawnEntity(args[1], _entManager.GetComponent<TransformComponent>(entity).Coordinates);
 
-                    if (!_protoManager.HasIndex<EntityPrototype>(args[1]))
-                    {
-                        shell.WriteLine($"No hand entity exists with id {args[1]}.");
-                        return;
+                        break;
                     }
-
-                    hand = _entManager.SpawnEntity(args[1], _entManager.GetComponent<TransformComponent>(entity).Coordinates);
-
-                    break;
-                }
                 default:
-                {
                     shell.WriteLine(Help);
                     return;
-                }
             }
 
             if (!_entManager.TryGetComponent(entity, out BodyComponent? body) || body.RootContainer.ContainedEntity == null)
@@ -139,7 +135,7 @@ namespace Content.Server.Body.Commands
 
             var slotId = part.GetHashCode().ToString();
 
-            if (!bodySystem.TryCreatePartSlotAndAttach(attachAt.Id, slotId, hand, BodyPartType.Hand,attachAt.Component, part))
+            if (!bodySystem.TryCreatePartSlotAndAttach(attachAt.Id, slotId, hand, BodyPartType.Hand, attachAt.Component, part))
             {
                 shell.WriteError($"Couldn't create a slot with id {slotId} on entity {_entManager.ToPrettyString(entity)}");
                 return;
index 24604b88b7a9599231f286eadbb2f456cf4ccb7d..82f71619370aae36066d963eba345e4d5f563756 100644 (file)
@@ -103,11 +103,11 @@ namespace Content.Server.Body.Commands
             // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
             if (body.RootContainer.ContainedEntity != null)
             {
-                bodySystem.AttachPartToRoot(bodyId,partUid.Value, body ,part);
+                bodySystem.AttachPartToRoot(bodyId, partUid.Value, body, part);
             }
             else
             {
-                var (rootPartId,rootPart) = bodySystem.GetRootPartOrNull(bodyId, body)!.Value;
+                var (rootPartId, rootPart) = bodySystem.GetRootPartOrNull(bodyId, body)!.Value;
                 if (!bodySystem.TryCreatePartSlotAndAttach(rootPartId, slotId, partUid.Value, part.PartType, rootPart, part))
                 {
                     shell.WriteError($"Could not create slot {slotId} on entity {_entManager.ToPrettyString(bodyId)}");
index 66b52af47bdd827d2d9c9b8306b0a50eb67afa39..a010855f784f13d7dfd0b17aab129bd13d4f9132 100644 (file)
@@ -1,11 +1,7 @@
 namespace Content.Server.Body.Components;
 
-public sealed class BeingGibbedEvent : EntityEventArgs
-{
-    public readonly HashSet<EntityUid> GibbedParts;
-
-    public BeingGibbedEvent(HashSet<EntityUid> gibbedParts)
-    {
-        GibbedParts = gibbedParts;
-    }
-}
+/// <summary>
+/// Raised when a body gets gibbed, before it is deleted.
+/// </summary>
+[ByRefEvent]
+public readonly record struct BeingGibbedEvent(HashSet<EntityUid> GibbedParts);
index 7041df444818c3195e45192606c3fceafddfe11f..d448c4aab21b691dc8aa559f2188cd247d751f28 100644 (file)
@@ -1,11 +1,13 @@
 using Content.Server.Body.Systems;
 using Content.Server.Chemistry.EntitySystems;
 using Content.Shared.Chemistry.Components;
+using Content.Shared.Chemistry.Reagent;
 using Content.Shared.Damage;
 using Content.Shared.Damage.Prototypes;
 using Content.Shared.FixedPoint;
 using Robust.Shared.Audio;
-using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
+using Robust.Shared.Prototypes;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
 
 namespace Content.Server.Body.Components
 {
@@ -16,7 +18,17 @@ namespace Content.Server.Body.Components
         public static string DefaultBloodSolutionName = "bloodstream";
         public static string DefaultBloodTemporarySolutionName = "bloodstreamTemporary";
 
-        public float AccumulatedFrametime = 0.0f;
+        /// <summary>
+        /// The next time that blood level will be updated and bloodloss damage dealt.
+        /// </summary>
+        [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
+        public TimeSpan NextUpdate;
+
+        /// <summary>
+        /// The interval at which this component updates.
+        /// </summary>
+        [DataField]
+        public TimeSpan UpdateInterval = TimeSpan.FromSeconds(3);
 
         /// <summary>
         ///     How much is this entity currently bleeding?
@@ -32,7 +44,7 @@ namespace Content.Server.Body.Components
         public float BleedAmount;
 
         /// <summary>
-        ///     How much should bleeding should be reduced every update interval?
+        ///     How much should bleeding be reduced every update interval?
         /// </summary>
         [DataField]
         public float BleedReductionAmount = 0.33f;
@@ -63,18 +75,12 @@ namespace Content.Server.Body.Components
         [DataField(required: true)]
         public DamageSpecifier BloodlossHealDamage = new();
 
-        /// <summary>
-        ///     How frequently should this bloodstream update, in seconds?
-        /// </summary>
-        [DataField]
-        public float UpdateInterval = 3.0f;
-
         // TODO shouldn't be hardcoded, should just use some organ simulation like bone marrow or smth.
         /// <summary>
         ///     How much reagent of blood should be restored each update interval?
         /// </summary>
         [DataField]
-        public float BloodRefreshAmount = 1.0f;
+        public FixedPoint2 BloodRefreshAmount = 1.0f;
 
         /// <summary>
         ///     How much blood needs to be in the temporary solution in order to create a puddle?
@@ -89,8 +95,8 @@ namespace Content.Server.Body.Components
         /// <remarks>
         ///     For example, piercing damage is increased while poison damage is nullified entirely.
         /// </remarks>
-        [DataField(customTypeSerializer:typeof(PrototypeIdSerializer<DamageModifierSetPrototype>))]
-        public string DamageBleedModifiers = "BloodlossHuman";
+        [DataField]
+        public ProtoId<DamageModifierSetPrototype> DamageBleedModifiers = "BloodlossHuman";
 
         /// <summary>
         ///     The sound to be played when a weapon instantly deals blood loss damage.
@@ -126,7 +132,7 @@ namespace Content.Server.Body.Components
         ///     Slime-people might use slime as their blood or something like that.
         /// </remarks>
         [DataField]
-        public string BloodReagent = "Blood";
+        public ProtoId<ReagentPrototype> BloodReagent = "Blood";
 
         /// <summary>Name/Key that <see cref="BloodSolution"/> is indexed by.</summary>
         [DataField]
@@ -164,6 +170,6 @@ namespace Content.Server.Body.Components
         /// Variable that stores the amount of status time added by having a low blood level.
         /// </summary>
         [ViewVariables(VVAccess.ReadWrite)]
-        public float StatusTime;
+        public TimeSpan StatusTime;
     }
 }
index 4eda008b0f9f5b059023db6dcb2e09a4c00aac7d..18caab8dcf041a8c2587469b0b14842ddff6f669 100644 (file)
@@ -1,4 +1,3 @@
-using System.Threading;
 namespace Content.Server.Body.Components
 {
     /// <summary>
@@ -7,14 +6,17 @@ namespace Content.Server.Body.Components
     [RegisterComponent]
     public sealed partial class InternalsComponent : Component
     {
-        [ViewVariables] public EntityUid? GasTankEntity { get; set; }
-        [ViewVariables] public EntityUid? BreathToolEntity { get; set; }
+        [ViewVariables]
+        public EntityUid? GasTankEntity;
+
+        [ViewVariables]
+        public EntityUid? BreathToolEntity;
 
         /// <summary>
-        /// Toggle Internals delay (seconds) when the target is not you.
+        /// Toggle Internals delay when the target is not you.
         /// </summary>
         [ViewVariables(VVAccess.ReadWrite)]
-        [DataField("delay")]
-        public float Delay = 3;
+        [DataField]
+        public TimeSpan Delay = TimeSpan.FromSeconds(3);
     }
 }
index 0656ef8fad37a13febc590ca0d59e86f92b8b5c1..46600b3020738532fa2ec1cedcd75e37c1889ed1 100644 (file)
@@ -1,4 +1,4 @@
-using Content.Server.Atmos;
+using Content.Server.Atmos;
 using Content.Server.Body.Systems;
 using Content.Shared.Alert;
 using Content.Shared.Atmos;
@@ -11,7 +11,7 @@ public sealed partial class LungComponent : Component
 {
     [DataField]
     [Access(typeof(LungSystem), Other = AccessPermissions.ReadExecute)] // FIXME Friends
-    public GasMixture Air { get; set; } = new()
+    public GasMixture Air = new()
     {
         Volume = 6,
         Temperature = Atmospherics.NormalBodyTemperature
index a8c82f3d369cd43a2bd98b185ff381493100d201..90c99df7db2c616e9613afe53887d0a87146b7f6 100644 (file)
@@ -1,8 +1,8 @@
-using Content.Server.Body.Systems;
+using Content.Server.Body.Systems;
 using Content.Shared.Body.Prototypes;
 using Content.Shared.FixedPoint;
-using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
-using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set;
+using Robust.Shared.Prototypes;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
 
 namespace Content.Server.Body.Components
 {
@@ -12,20 +12,24 @@ namespace Content.Server.Body.Components
     [RegisterComponent, Access(typeof(MetabolizerSystem))]
     public sealed partial class MetabolizerComponent : Component
     {
-        public float AccumulatedFrametime = 0.0f;
+        /// <summary>
+        ///     The next time that reagents will be metabolized.
+        /// </summary>
+        [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
+        public TimeSpan NextUpdate;
 
         /// <summary>
-        ///     How often to metabolize reagents, in seconds.
+        ///     How often to metabolize reagents.
         /// </summary>
         /// <returns></returns>
         [DataField]
-        public float UpdateFrequency = 1.0f;
+        public TimeSpan UpdateInterval = TimeSpan.FromSeconds(1);
 
         /// <summary>
         ///     From which solution will this metabolizer attempt to metabolize chemicals
         /// </summary>
         [DataField("solution")]
-        public string SolutionName { get; set; } = BloodstreamComponent.DefaultChemicalsSolutionName;
+        public string SolutionName = BloodstreamComponent.DefaultChemicalsSolutionName;
 
         /// <summary>
         ///     Does this component use a solution on it's parent entity (the body) or itself
@@ -39,9 +43,9 @@ namespace Content.Server.Body.Components
         /// <summary>
         ///     List of metabolizer types that this organ is. ex. Human, Slime, Felinid, w/e.
         /// </summary>
-        [DataField(customTypeSerializer:typeof(PrototypeIdHashSetSerializer<MetabolizerTypePrototype>))]
+        [DataField]
         [Access(typeof(MetabolizerSystem), Other = AccessPermissions.ReadExecute)] // FIXME Friends
-        public HashSet<string>? MetabolizerTypes = null;
+        public HashSet<ProtoId<MetabolizerTypePrototype>>? MetabolizerTypes = null;
 
         /// <summary>
         ///     Should this metabolizer remove chemicals that have no metabolisms defined?
@@ -72,8 +76,8 @@ namespace Content.Server.Body.Components
     [DataDefinition]
     public sealed partial class MetabolismGroupEntry
     {
-        [DataField(required: true, customTypeSerializer:typeof(PrototypeIdSerializer<MetabolismGroupPrototype>))]
-        public string Id = default!;
+        [DataField(required: true)]
+        public ProtoId<MetabolismGroupPrototype> Id = default!;
 
         [DataField("rateModifier")]
         public FixedPoint2 MetabolismRateModifier = 1.0;
index 9f080a3dd9dc38d36a42f1eff331e9cb84a3b8b7..4045e21e26a72a682b5cd3fd566474a767d2971e 100644 (file)
@@ -1,5 +1,6 @@
 using Content.Server.Body.Systems;
 using Content.Shared.Damage;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
 
 namespace Content.Server.Body.Components
 {
@@ -7,36 +8,49 @@ namespace Content.Server.Body.Components
     public sealed partial class RespiratorComponent : Component
     {
         /// <summary>
-        ///     Saturation level. Reduced by CycleDelay each tick.
+        ///     The next time that this body will inhale or exhale.
+        /// </summary>
+        [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
+        public TimeSpan NextUpdate;
+
+        /// <summary>
+        ///     The interval between updates. Each update is either inhale or exhale,
+        ///     so a full cycle takes twice as long.
+        /// </summary>
+        [DataField]
+        public TimeSpan UpdateInterval = TimeSpan.FromSeconds(2);
+
+        /// <summary>
+        ///     Saturation level. Reduced by UpdateInterval each tick.
         ///     Can be thought of as 'how many seconds you have until you start suffocating' in this configuration.
         /// </summary>
-        [DataField("saturation")]
+        [DataField]
         public float Saturation = 5.0f;
 
         /// <summary>
         ///     At what level of saturation will you begin to suffocate?
         /// </summary>
-        [DataField("suffocationThreshold")]
+        [DataField]
         public float SuffocationThreshold;
 
-        [DataField("maxSaturation")]
+        [DataField]
         public float MaxSaturation = 5.0f;
 
-        [DataField("minSaturation")]
+        [DataField]
         public float MinSaturation = -2.0f;
 
         // TODO HYPEROXIA?
 
-        [DataField("damage", required: true)]
+        [DataField(required: true)]
         [ViewVariables(VVAccess.ReadWrite)]
         public DamageSpecifier Damage = default!;
 
-        [DataField("damageRecovery", required: true)]
+        [DataField(required: true)]
         [ViewVariables(VVAccess.ReadWrite)]
         public DamageSpecifier DamageRecovery = default!;
 
-        [DataField("gaspPopupCooldown")]
-        public TimeSpan GaspPopupCooldown { get; private set; } = TimeSpan.FromSeconds(8);
+        [DataField]
+        public TimeSpan GaspPopupCooldown = TimeSpan.FromSeconds(8);
 
         [ViewVariables]
         public TimeSpan LastGaspPopupTime;
@@ -55,11 +69,6 @@ namespace Content.Server.Body.Components
 
         [ViewVariables]
         public RespiratorStatus Status = RespiratorStatus.Inhaling;
-
-        [DataField("cycleDelay")]
-        public float CycleDelay = 2.0f;
-
-        public float AccumulatedFrametime;
     }
 }
 
index fe93468f74eed9a5c73a0fb04a27721798cc3ce8..d541ca4d7c453641cd1eb446800305822578d2bf 100644 (file)
@@ -1,21 +1,26 @@
-using Content.Server.Body.Systems;
+using Content.Server.Body.Systems;
 using Content.Server.Nutrition.EntitySystems;
 using Content.Shared.Chemistry.Components;
 using Content.Shared.Chemistry.Reagent;
 using Content.Shared.Whitelist;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
 
 namespace Content.Server.Body.Components
 {
     [RegisterComponent, Access(typeof(StomachSystem), typeof(FoodSystem))]
     public sealed partial class StomachComponent : Component
     {
-        public float AccumulatedFrameTime;
+        /// <summary>
+        ///     The next time that the stomach will try to digest its contents.
+        /// </summary>
+        [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
+        public TimeSpan NextUpdate;
 
         /// <summary>
-        ///     How fast should this component update, in seconds?
+        ///     The interval at which this stomach digests its contents.
         /// </summary>
         [DataField]
-        public float UpdateInterval = 1.0f;
+        public TimeSpan UpdateInterval = TimeSpan.FromSeconds(1);
 
         /// <summary>
         ///     The solution inside of this stomach this transfers reagents to the body.
@@ -30,11 +35,11 @@ namespace Content.Server.Body.Components
         public string BodySolutionName = BloodstreamComponent.DefaultChemicalsSolutionName;
 
         /// <summary>
-        ///     Time in seconds between reagents being ingested and them being
+        ///     Time between reagents being ingested and them being
         ///     transferred to <see cref="BloodstreamComponent"/>
         /// </summary>
         [DataField]
-        public float DigestionDelay = 20;
+        public TimeSpan DigestionDelay = TimeSpan.FromSeconds(20);
 
         /// <summary>
         ///     A whitelist for what special-digestible-required foods this stomach is capable of eating.
@@ -54,15 +59,15 @@ namespace Content.Server.Body.Components
         public sealed class ReagentDelta
         {
             public readonly ReagentQuantity ReagentQuantity;
-            public float Lifetime { get; private set; }
+            public TimeSpan Lifetime { get; private set; }
 
             public ReagentDelta(ReagentQuantity reagentQuantity)
             {
                 ReagentQuantity = reagentQuantity;
-                Lifetime = 0.0f;
+                Lifetime = TimeSpan.Zero;
             }
 
-            public void Increment(float delta) => Lifetime += delta;
+            public void Increment(TimeSpan delta) => Lifetime += delta;
         }
     }
 }
index 4acdccf1ba7527b56c8363598e93181da12dcd38..19b76189e095fc5cdfc985f6823232f61ea9f5ae 100644 (file)
@@ -1,4 +1,5 @@
 using Content.Server.Body.Systems;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
 
 namespace Content.Server.Body.Components;
 
@@ -6,48 +7,58 @@ namespace Content.Server.Body.Components;
 [Access(typeof(ThermalRegulatorSystem))]
 public sealed partial class ThermalRegulatorComponent : Component
 {
+    /// <summary>
+    /// The next time that the body will regulate its heat.
+    /// </summary>
+    [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
+    public TimeSpan NextUpdate;
+
+    /// <summary>
+    /// The interval at which thermal regulation is processed.
+    /// </summary>
+    [DataField]
+    public TimeSpan UpdateInterval = TimeSpan.FromSeconds(1);
+
     /// <summary>
     /// Heat generated due to metabolism. It's generated via metabolism
     /// </summary>
-    [DataField("metabolismHeat")]
-    public float MetabolismHeat { get; private set; }
+    [DataField]
+    public float MetabolismHeat;
 
     /// <summary>
     /// Heat output via radiation.
     /// </summary>
-    [DataField("radiatedHeat")]
-    public float RadiatedHeat { get; private set; }
+    [DataField]
+    public float RadiatedHeat;
 
     /// <summary>
     /// Maximum heat regulated via sweat
     /// </summary>
-    [DataField("sweatHeatRegulation")]
-    public float SweatHeatRegulation { get; private set; }
+    [DataField]
+    public float SweatHeatRegulation;
 
     /// <summary>
     /// Maximum heat regulated via shivering
     /// </summary>
-    [DataField("shiveringHeatRegulation")]
-    public float ShiveringHeatRegulation { get; private set; }
+    [DataField]
+    public float ShiveringHeatRegulation;
 
     /// <summary>
     /// Amount of heat regulation that represents thermal regulation processes not
     /// explicitly coded.
     /// </summary>
-    [DataField("implicitHeatRegulation")]
-    public float ImplicitHeatRegulation { get; private set; }
+    [DataField]
+    public float ImplicitHeatRegulation;
 
     /// <summary>
     /// Normal body temperature
     /// </summary>
-    [DataField("normalBodyTemperature")]
-    public float NormalBodyTemperature { get; private set; }
+    [DataField]
+    public float NormalBodyTemperature;
 
     /// <summary>
     /// Deviation from normal temperature for body to start thermal regulation
     /// </summary>
-    [DataField("thermalRegulationTemperatureThreshold")]
-    public float ThermalRegulationTemperatureThreshold { get; private set; }
-
-    public float AccumulatedFrametime;
+    [DataField]
+    public float ThermalRegulationTemperatureThreshold;
 }
index f6fdcfedff49f0c67475b17f4ed0112db3b09bdc..9e29fdf75680a8f4bdaf1170383881bae321d5d1 100644 (file)
@@ -13,7 +13,6 @@ using Content.Shared.Damage;
 using Content.Shared.Damage.Prototypes;
 using Content.Shared.Drunk;
 using Content.Shared.FixedPoint;
-using Content.Shared.IdentityManagement;
 using Content.Shared.Mobs.Systems;
 using Content.Shared.Popups;
 using Content.Shared.Rejuvenate;
@@ -21,11 +20,13 @@ using Content.Shared.Speech.EntitySystems;
 using Robust.Server.Audio;
 using Robust.Shared.Prototypes;
 using Robust.Shared.Random;
+using Robust.Shared.Timing;
 
 namespace Content.Server.Body.Systems;
 
 public sealed class BloodstreamSystem : EntitySystem
 {
+    [Dependency] private readonly IGameTiming _gameTiming = default!;
     [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
     [Dependency] private readonly IRobustRandom _robustRandom = default!;
     [Dependency] private readonly AudioSystem _audio = default!;
@@ -44,6 +45,8 @@ public sealed class BloodstreamSystem : EntitySystem
         base.Initialize();
 
         SubscribeLocalEvent<BloodstreamComponent, ComponentInit>(OnComponentInit);
+        SubscribeLocalEvent<BloodstreamComponent, MapInitEvent>(OnMapInit);
+        SubscribeLocalEvent<BloodstreamComponent, EntityUnpausedEvent>(OnUnpaused);
         SubscribeLocalEvent<BloodstreamComponent, DamageChangedEvent>(OnDamageChanged);
         SubscribeLocalEvent<BloodstreamComponent, HealthBeingExaminedEvent>(OnHealthBeingExamined);
         SubscribeLocalEvent<BloodstreamComponent, BeingGibbedEvent>(OnBeingGibbed);
@@ -53,6 +56,16 @@ public sealed class BloodstreamSystem : EntitySystem
         SubscribeLocalEvent<BloodstreamComponent, RejuvenateEvent>(OnRejuvenate);
     }
 
+    private void OnMapInit(Entity<BloodstreamComponent> ent, ref MapInitEvent args)
+    {
+        ent.Comp.NextUpdate = _gameTiming.CurTime + ent.Comp.UpdateInterval;
+    }
+
+    private void OnUnpaused(Entity<BloodstreamComponent> ent, ref EntityUnpausedEvent args)
+    {
+        ent.Comp.NextUpdate += args.PausedTime;
+    }
+
     private void OnReactionAttempt(Entity<BloodstreamComponent> entity, ref ReactionAttemptEvent args)
     {
         if (args.Cancelled)
@@ -83,7 +96,9 @@ public sealed class BloodstreamSystem : EntitySystem
         if (args.Name != entity.Comp.BloodSolutionName
             && args.Name != entity.Comp.ChemicalSolutionName
             && args.Name != entity.Comp.BloodTemporarySolutionName)
+        {
             return;
+        }
 
         OnReactionAttempt(entity, ref args.Event);
     }
@@ -95,12 +110,10 @@ public sealed class BloodstreamSystem : EntitySystem
         var query = EntityQueryEnumerator<BloodstreamComponent>();
         while (query.MoveNext(out var uid, out var bloodstream))
         {
-            bloodstream.AccumulatedFrametime += frameTime;
-
-            if (bloodstream.AccumulatedFrametime < bloodstream.UpdateInterval)
+            if (_gameTiming.CurTime < bloodstream.NextUpdate)
                 continue;
 
-            bloodstream.AccumulatedFrametime -= bloodstream.UpdateInterval;
+            bloodstream.NextUpdate += bloodstream.UpdateInterval;
 
             if (!_solutionContainerSystem.ResolveSolution(uid, bloodstream.BloodSolutionName, ref bloodstream.BloodSolution, out var bloodSolution))
                 continue;
@@ -128,13 +141,17 @@ public sealed class BloodstreamSystem : EntitySystem
                 // bloodloss damage is based on the base value, and modified by how low your blood level is.
                 var amt = bloodstream.BloodlossDamage / (0.1f + bloodPercentage);
 
-                _damageableSystem.TryChangeDamage(uid, amt, false, false);
+                _damageableSystem.TryChangeDamage(uid, amt,
+                    ignoreResistances: false, interruptsDoAfters: false);
 
                 // Apply dizziness as a symptom of bloodloss.
                 // The effect is applied in a way that it will never be cleared without being healthy.
                 // Multiplying by 2 is arbitrary but works for this case, it just prevents the time from running out
-                _drunkSystem.TryApplyDrunkenness(uid, bloodstream.UpdateInterval*2, false);
-                _stutteringSystem.DoStutter(uid, TimeSpan.FromSeconds(bloodstream.UpdateInterval*2), false);
+                _drunkSystem.TryApplyDrunkenness(
+                    uid,
+                    (float) bloodstream.UpdateInterval.TotalSeconds * 2,
+                    applySlur: false);
+                _stutteringSystem.DoStutter(uid, bloodstream.UpdateInterval * 2, refresh: false);
 
                 // storing the drunk and stutter time so we can remove it independently from other effects additions
                 bloodstream.StatusTime += bloodstream.UpdateInterval * 2;
@@ -142,13 +159,16 @@ public sealed class BloodstreamSystem : EntitySystem
             else if (!_mobStateSystem.IsDead(uid))
             {
                 // If they're healthy, we'll try and heal some bloodloss instead.
-                _damageableSystem.TryChangeDamage(uid, bloodstream.BloodlossHealDamage * bloodPercentage, true, false);
+                _damageableSystem.TryChangeDamage(
+                    uid,
+                    bloodstream.BloodlossHealDamage * bloodPercentage,
+                    ignoreResistances: true, interruptsDoAfters: false);
 
                 // Remove the drunk effect when healthy. Should only remove the amount of drunk and stutter added by low blood level
-                _drunkSystem.TryRemoveDrunkenessTime(uid, bloodstream.StatusTime);
-                _stutteringSystem.DoRemoveStutterTime(uid, bloodstream.StatusTime);
+                _drunkSystem.TryRemoveDrunkenessTime(uid, bloodstream.StatusTime.TotalSeconds);
+                _stutteringSystem.DoRemoveStutterTime(uid, bloodstream.StatusTime.TotalSeconds);
                 // Reset the drunk and stutter time to zero
-                bloodstream.StatusTime = 0;
+                bloodstream.StatusTime = TimeSpan.Zero;
             }
         }
     }
@@ -167,17 +187,15 @@ public sealed class BloodstreamSystem : EntitySystem
         bloodSolution.AddReagent(entity.Comp.BloodReagent, entity.Comp.BloodMaxVolume - bloodSolution.Volume);
     }
 
-    private void OnDamageChanged(EntityUid uid, BloodstreamComponent component, DamageChangedEvent args)
+    private void OnDamageChanged(Entity<BloodstreamComponent> ent, ref DamageChangedEvent args)
     {
-        if (args.DamageDelta is null)
-            return;
-
-        // definitely don't make them bleed if they got healed
-        if (!args.DamageIncreased)
+        if (args.DamageDelta is null || !args.DamageIncreased)
+        {
             return;
+        }
 
         // TODO probably cache this or something. humans get hurt a lot
-        if (!_prototypeManager.TryIndex<DamageModifierSetPrototype>(component.DamageBleedModifiers, out var modifiers))
+        if (!_prototypeManager.TryIndex<DamageModifierSetPrototype>(ent.Comp.DamageBleedModifiers, out var modifiers))
             return;
 
         var bloodloss = DamageSpecifier.ApplyModifierSet(args.DamageDelta, modifiers);
@@ -186,10 +204,10 @@ public sealed class BloodstreamSystem : EntitySystem
             return;
 
         // Does the calculation of how much bleed rate should be added/removed, then applies it
-        var oldBleedAmount = component.BleedAmount;
+        var oldBleedAmount = ent.Comp.BleedAmount;
         var total = bloodloss.GetTotal();
         var totalFloat = total.Float();
-        TryModifyBleedAmount(uid, totalFloat, component);
+        TryModifyBleedAmount(ent, totalFloat, ent);
 
         /// <summary>
         ///     Critical hit. Causes target to lose blood, using the bleed rate modifier of the weapon, currently divided by 5
@@ -199,8 +217,8 @@ public sealed class BloodstreamSystem : EntitySystem
         var prob = Math.Clamp(totalFloat / 25, 0, 1);
         if (totalFloat > 0 && _robustRandom.Prob(prob))
         {
-            TryModifyBloodLevel(uid, (-total) / 5, component);
-            _audio.PlayPvs(component.InstantBloodSound, uid);
+            TryModifyBloodLevel(ent, (-total) / 5, ent);
+            _audio.PlayPvs(ent.Comp.InstantBloodSound, ent);
         }
 
         // Heat damage will cauterize, causing the bleed rate to be reduced.
@@ -210,53 +228,52 @@ public sealed class BloodstreamSystem : EntitySystem
             // because it's burn damage that cauterized their wounds.
 
             // We'll play a special sound and popup for feedback.
-            _audio.PlayPvs(component.BloodHealedSound, uid);
-            _popupSystem.PopupEntity(Loc.GetString("bloodstream-component-wounds-cauterized"), uid,
-                uid, PopupType.Medium);
+            _audio.PlayPvs(ent.Comp.BloodHealedSound, ent);
+            _popupSystem.PopupEntity(Loc.GetString("bloodstream-component-wounds-cauterized"), ent,
+                ent, PopupType.Medium);
         }
     }
     /// <summary>
     ///     Shows text on health examine, based on bleed rate and blood level.
     /// </summary>
-    private void OnHealthBeingExamined(EntityUid uid, BloodstreamComponent component, HealthBeingExaminedEvent args)
+    private void OnHealthBeingExamined(Entity<BloodstreamComponent> ent, ref HealthBeingExaminedEvent args)
     {
         // Shows profusely bleeding at half the max bleed rate.
-        if (component.BleedAmount > component.MaxBleedAmount / 2)
+        if (ent.Comp.BleedAmount > ent.Comp.MaxBleedAmount / 2)
         {
             args.Message.PushNewline();
-            args.Message.AddMarkup(Loc.GetString("bloodstream-component-profusely-bleeding", ("target", Identity.Entity(uid, EntityManager))));
+            args.Message.AddMarkup(Loc.GetString("bloodstream-component-profusely-bleeding", ("target", ent.Owner)));
         }
         // Shows bleeding message when bleeding, but less than profusely.
-        else if (component.BleedAmount > 0)
+        else if (ent.Comp.BleedAmount > 0)
         {
             args.Message.PushNewline();
-            args.Message.AddMarkup(Loc.GetString("bloodstream-component-bleeding", ("target", Identity.Entity(uid, EntityManager))));
+            args.Message.AddMarkup(Loc.GetString("bloodstream-component-bleeding", ("target", ent.Owner)));
         }
 
         // If the mob's blood level is below the damage threshhold, the pale message is added.
-        if (GetBloodLevelPercentage(uid, component) < component.BloodlossThreshold)
+        if (GetBloodLevelPercentage(ent, ent) < ent.Comp.BloodlossThreshold)
         {
             args.Message.PushNewline();
-            args.Message.AddMarkup(Loc.GetString("bloodstream-component-looks-pale", ("target", Identity.Entity(uid, EntityManager))));
+            args.Message.AddMarkup(Loc.GetString("bloodstream-component-looks-pale", ("target", ent.Owner)));
         }
     }
 
-    private void OnBeingGibbed(EntityUid uid, BloodstreamComponent component, BeingGibbedEvent args)
+    private void OnBeingGibbed(Entity<BloodstreamComponent> ent, ref BeingGibbedEvent args)
     {
-        SpillAllSolutions(uid, component);
+        SpillAllSolutions(ent, ent);
     }
 
-    private void OnApplyMetabolicMultiplier(EntityUid uid, BloodstreamComponent component, ApplyMetabolicMultiplierEvent args)
+    private void OnApplyMetabolicMultiplier(
+        Entity<BloodstreamComponent> ent,
+        ref ApplyMetabolicMultiplierEvent args)
     {
         if (args.Apply)
         {
-            component.UpdateInterval *= args.Multiplier;
+            ent.Comp.UpdateInterval *= args.Multiplier;
             return;
         }
-        component.UpdateInterval /= args.Multiplier;
-        // Reset the accumulator properly
-        if (component.AccumulatedFrametime >= component.UpdateInterval)
-            component.AccumulatedFrametime = component.UpdateInterval;
+        ent.Comp.UpdateInterval /= args.Multiplier;
     }
 
     private void OnRejuvenate(Entity<BloodstreamComponent> entity, ref RejuvenateEvent args)
@@ -275,21 +292,15 @@ public sealed class BloodstreamSystem : EntitySystem
     /// </summary>
     public bool TryAddToChemicals(EntityUid uid, Solution solution, BloodstreamComponent? component = null)
     {
-        if (!Resolve(uid, ref component, false))
-            return false;
-
-        if (!_solutionContainerSystem.ResolveSolution(uid, component.ChemicalSolutionName, ref component.ChemicalSolution))
-            return false;
-
-        return _solutionContainerSystem.TryAddSolution(component.ChemicalSolution.Value, solution);
+        return Resolve(uid, ref component, logMissing: false)
+            && _solutionContainerSystem.ResolveSolution(uid, component.ChemicalSolutionName, ref component.ChemicalSolution)
+            && _solutionContainerSystem.TryAddSolution(component.ChemicalSolution.Value, solution);
     }
 
     public bool FlushChemicals(EntityUid uid, string excludedReagentID, FixedPoint2 quantity, BloodstreamComponent? component = null)
     {
-        if (!Resolve(uid, ref component, false))
-            return false;
-
-        if (!_solutionContainerSystem.ResolveSolution(uid, component.ChemicalSolutionName, ref component.ChemicalSolution, out var chemSolution))
+        if (!Resolve(uid, ref component, logMissing: false)
+            || !_solutionContainerSystem.ResolveSolution(uid, component.ChemicalSolutionName, ref component.ChemicalSolution, out var chemSolution))
             return false;
 
         for (var i = chemSolution.Contents.Count - 1; i >= 0; i--)
@@ -306,11 +317,11 @@ public sealed class BloodstreamSystem : EntitySystem
 
     public float GetBloodLevelPercentage(EntityUid uid, BloodstreamComponent? component = null)
     {
-        if (!Resolve(uid, ref component))
-            return 0.0f;
-
-        if (!_solutionContainerSystem.ResolveSolution(uid, component.BloodSolutionName, ref component.BloodSolution, out var bloodSolution))
+        if (!Resolve(uid, ref component)
+            || !_solutionContainerSystem.ResolveSolution(uid, component.BloodSolutionName, ref component.BloodSolution, out var bloodSolution))
+        {
             return 0.0f;
+        }
 
         return bloodSolution.FillFraction;
     }
@@ -328,11 +339,11 @@ public sealed class BloodstreamSystem : EntitySystem
     /// </summary>
     public bool TryModifyBloodLevel(EntityUid uid, FixedPoint2 amount, BloodstreamComponent? component = null)
     {
-        if (!Resolve(uid, ref component, false))
-            return false;
-
-        if (!_solutionContainerSystem.ResolveSolution(uid, component.BloodSolutionName, ref component.BloodSolution))
+        if (!Resolve(uid, ref component, logMissing: false)
+            || !_solutionContainerSystem.ResolveSolution(uid, component.BloodSolutionName, ref component.BloodSolution))
+        {
             return false;
+        }
 
         if (amount >= 0)
             return _solutionContainerSystem.TryAddReagent(component.BloodSolution.Value, component.BloodReagent, amount, out _);
@@ -356,9 +367,9 @@ public sealed class BloodstreamSystem : EntitySystem
                 tempSolution.AddSolution(temp, _prototypeManager);
             }
 
-            if (_puddleSystem.TrySpillAt(uid, tempSolution, out var puddleUid, false))
+            if (_puddleSystem.TrySpillAt(uid, tempSolution, out var puddleUid, sound: false))
             {
-                _forensicsSystem.TransferDna(puddleUid, uid, false);
+                _forensicsSystem.TransferDna(puddleUid, uid, canDnaBeCleaned: false);
             }
 
             tempSolution.RemoveAllSolution();
@@ -374,7 +385,7 @@ public sealed class BloodstreamSystem : EntitySystem
     /// </summary>
     public bool TryModifyBleedAmount(EntityUid uid, float amount, BloodstreamComponent? component = null)
     {
-        if (!Resolve(uid, ref component, false))
+        if (!Resolve(uid, ref component, logMissing: false))
             return false;
 
         component.BleedAmount += amount;
@@ -424,7 +435,7 @@ public sealed class BloodstreamSystem : EntitySystem
 
         if (_puddleSystem.TrySpillAt(uid, tempSol, out var puddleUid))
         {
-            _forensicsSystem.TransferDna(puddleUid, uid, false);
+            _forensicsSystem.TransferDna(puddleUid, uid, canDnaBeCleaned: false);
         }
     }
 
@@ -433,11 +444,11 @@ public sealed class BloodstreamSystem : EntitySystem
     /// </summary>
     public void ChangeBloodReagent(EntityUid uid, string reagent, BloodstreamComponent? component = null)
     {
-        if (!Resolve(uid, ref component, false))
-            return;
-
-        if (reagent == component.BloodReagent)
+        if (!Resolve(uid, ref component, logMissing: false)
+            || reagent == component.BloodReagent)
+        {
             return;
+        }
 
         if (!_solutionContainerSystem.ResolveSolution(uid, component.BloodSolutionName, ref component.BloodSolution, out var bloodSolution))
         {
index 18119909abce0dda854354c5e7ac51b562fe51fa..92074d06ffb4eab64b1210386da87ee030117cb3 100644 (file)
@@ -1,23 +1,19 @@
 using Content.Server.Body.Components;
 using Content.Server.GameTicking;
 using Content.Server.Humanoid;
-using Content.Server.Kitchen.Components;
 using Content.Shared.Body.Components;
 using Content.Shared.Body.Part;
 using Content.Shared.Body.Systems;
 using Content.Shared.Humanoid;
-using Content.Shared.Kitchen.Components;
 using Content.Shared.Mind;
 using Content.Shared.Mobs.Systems;
 using Content.Shared.Movement.Events;
+using Content.Shared.Movement.Systems;
 using Robust.Shared.Audio;
-using Robust.Shared.Player;
+using Robust.Shared.Audio.Systems;
 using Robust.Shared.Random;
 using Robust.Shared.Timing;
 using System.Numerics;
-using Content.Shared.Gibbing.Components;
-using Content.Shared.Movement.Systems;
-using Robust.Shared.Audio.Systems;
 
 namespace Content.Server.Body.Systems;
 
@@ -28,7 +24,6 @@ public sealed class BodySystem : SharedBodySystem
     [Dependency] private readonly HumanoidAppearanceSystem _humanoidSystem = default!;
     [Dependency] private readonly MobStateSystem _mobState = default!;
     [Dependency] private readonly SharedAudioSystem _audio = default!;
-    [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
     [Dependency] private readonly SharedMindSystem _mindSystem = default!;
     [Dependency] private readonly IRobustRandom _random = default!;
 
@@ -40,7 +35,7 @@ public sealed class BodySystem : SharedBodySystem
         SubscribeLocalEvent<BodyComponent, ApplyMetabolicMultiplierEvent>(OnApplyMetabolicMultiplier);
     }
 
-    private void OnRelayMoveInput(EntityUid uid, BodyComponent component, ref MoveInputEvent args)
+    private void OnRelayMoveInput(Entity<BodyComponent> ent, ref MoveInputEvent args)
     {
         // If they haven't actually moved then ignore it.
         if ((args.Component.HeldMoveButtons &
@@ -49,68 +44,67 @@ public sealed class BodySystem : SharedBodySystem
             return;
         }
 
-        if (_mobState.IsDead(uid) && _mindSystem.TryGetMind(uid, out var mindId, out var mind))
+        if (_mobState.IsDead(ent) && _mindSystem.TryGetMind(ent, out var mindId, out var mind))
         {
             mind.TimeOfDeath ??= _gameTiming.RealTime;
-            _ticker.OnGhostAttempt(mindId, true, mind: mind);
+            _ticker.OnGhostAttempt(mindId, canReturnGlobal: true, mind: mind);
         }
     }
 
-    private void OnApplyMetabolicMultiplier(EntityUid uid, BodyComponent component,
-        ApplyMetabolicMultiplierEvent args)
+    private void OnApplyMetabolicMultiplier(
+        Entity<BodyComponent> ent,
+        ref ApplyMetabolicMultiplierEvent args)
     {
-        foreach (var organ in GetBodyOrgans(uid, component))
+        foreach (var organ in GetBodyOrgans(ent, ent))
         {
-            RaiseLocalEvent(organ.Id, args);
+            RaiseLocalEvent(organ.Id, ref args);
         }
     }
 
     protected override void AddPart(
-        EntityUid bodyUid,
-        EntityUid partUid,
-        string slotId,
-        BodyPartComponent component,
-        BodyComponent? bodyComp = null)
+        Entity<BodyComponent?> bodyEnt,
+        Entity<BodyPartComponent> partEnt,
+        string slotId)
     {
         // TODO: Predict this probably.
-        base.AddPart(bodyUid, partUid, slotId, component, bodyComp);
+        base.AddPart(bodyEnt, partEnt, slotId);
 
-        if (TryComp<HumanoidAppearanceComponent>(bodyUid, out var humanoid))
+        if (TryComp<HumanoidAppearanceComponent>(bodyEnt, out var humanoid))
         {
-            var layer = component.ToHumanoidLayers();
+            var layer = partEnt.Comp.ToHumanoidLayers();
             if (layer != null)
             {
                 var layers = HumanoidVisualLayersExtension.Sublayers(layer.Value);
-                _humanoidSystem.SetLayersVisibility(bodyUid, layers, true, true, humanoid);
+                _humanoidSystem.SetLayersVisibility(
+                    bodyEnt, layers, visible: true, permanent: true, humanoid);
             }
         }
     }
 
     protected override void RemovePart(
-        EntityUid bodyUid,
-        EntityUid partUid,
-        string slotId,
-        BodyPartComponent component,
-        BodyComponent? bodyComp = null)
+        Entity<BodyComponent?> bodyEnt,
+        Entity<BodyPartComponent> partEnt,
+        string slotId)
     {
-        base.RemovePart(bodyUid, partUid, slotId, component, bodyComp);
+        base.RemovePart(bodyEnt, partEnt, slotId);
 
-        if (!TryComp<HumanoidAppearanceComponent>(bodyUid, out var humanoid))
+        if (!TryComp<HumanoidAppearanceComponent>(bodyEnt, out var humanoid))
             return;
 
-        var layer = component.ToHumanoidLayers();
+        var layer = partEnt.Comp.ToHumanoidLayers();
 
-        if (layer == null)
+        if (layer is null)
             return;
 
         var layers = HumanoidVisualLayersExtension.Sublayers(layer.Value);
-        _humanoidSystem.SetLayersVisibility(bodyUid, layers, false, true, humanoid);
+        _humanoidSystem.SetLayersVisibility(
+            bodyEnt, layers, visible: false, permanent: true, humanoid);
     }
 
     public override HashSet<EntityUid> GibBody(
         EntityUid bodyId,
         bool gibOrgans = false,
-        BodyComponent? body = null ,
+        BodyComponent? body = null,
         bool launchGibs = true,
         Vector2? splatDirection = null,
         float splatModifier = 1,
@@ -118,19 +112,23 @@ public sealed class BodySystem : SharedBodySystem
         SoundSpecifier? gibSoundOverride = null
     )
     {
-        if (!Resolve(bodyId, ref body, false))
-            return new HashSet<EntityUid>();
-
-        if (TerminatingOrDeleted(bodyId) || EntityManager.IsQueuedForDeletion(bodyId))
+        if (!Resolve(bodyId, ref body, logMissing: false)
+            || TerminatingOrDeleted(bodyId)
+            || EntityManager.IsQueuedForDeletion(bodyId))
+        {
             return new HashSet<EntityUid>();
+        }
 
         var xform = Transform(bodyId);
-        if (xform.MapUid == null)
+        if (xform.MapUid is null)
             return new HashSet<EntityUid>();
 
         var gibs = base.GibBody(bodyId, gibOrgans, body, launchGibs: launchGibs,
             splatDirection: splatDirection, splatModifier: splatModifier, splatCone:splatCone);
-        RaiseLocalEvent(bodyId, new BeingGibbedEvent(gibs));
+
+        var ev = new BeingGibbedEvent(gibs);
+        RaiseLocalEvent(bodyId, ref ev);
+
         QueueDel(bodyId);
 
         return gibs;
index abb54971209229cc0dfa06f553fd2d9c598c8ed8..86d2cb61ffe931a50c98233ae89a903ee1c903a6 100644 (file)
@@ -16,8 +16,8 @@ namespace Content.Server.Body.Systems
         {
             base.Initialize();
 
-            SubscribeLocalEvent<BrainComponent, AddedToPartInBodyEvent>((uid, _, args) => HandleMind(args.Body, uid));
-            SubscribeLocalEvent<BrainComponent, RemovedFromPartInBodyEvent>((uid, _, args) => HandleMind(uid, args.OldBody));
+            SubscribeLocalEvent<BrainComponent, OrganAddedToBodyEvent>((uid, _, args) => HandleMind(args.Body, uid));
+            SubscribeLocalEvent<BrainComponent, OrganRemovedFromBodyEvent>((uid, _, args) => HandleMind(uid, args.OldBody));
             SubscribeLocalEvent<BrainComponent, PointAttemptEvent>(OnPointAttempt);
         }
 
@@ -39,7 +39,7 @@ namespace Content.Server.Body.Systems
             _mindSystem.TransferTo(mindId, newEntity, mind: mind);
         }
 
-        private void OnPointAttempt(EntityUid uid, BrainComponent component, PointAttemptEvent args)
+        private void OnPointAttempt(Entity<BrainComponent> ent, ref PointAttemptEvent args)
         {
             args.Cancel();
         }
index 004dae99b97cadb08a4decc98d5116abca0bd735..999aa40077b455b1e0eec79d8457ca18080fdcb6 100644 (file)
@@ -18,12 +18,10 @@ namespace Content.Server.Body.Systems;
 
 public sealed class InternalsSystem : EntitySystem
 {
-    [Dependency] private readonly IPrototypeManager _protoManager = default!;
     [Dependency] private readonly AlertsSystem _alerts = default!;
     [Dependency] private readonly AtmosphereSystem _atmos = default!;
     [Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
     [Dependency] private readonly GasTankSystem _gasTank = default!;
-    [Dependency] private readonly HandsSystem _hands = default!;
     [Dependency] private readonly InventorySystem _inventory = default!;
     [Dependency] private readonly PopupSystem _popupSystem = default!;
 
@@ -40,28 +38,36 @@ public sealed class InternalsSystem : EntitySystem
         SubscribeLocalEvent<InternalsComponent, InternalsDoAfterEvent>(OnDoAfter);
     }
 
-    private void OnGetInteractionVerbs(EntityUid uid, InternalsComponent component, GetVerbsEvent<InteractionVerb> args)
+    private void OnGetInteractionVerbs(
+        Entity<InternalsComponent> ent,
+        ref GetVerbsEvent<InteractionVerb> args)
     {
-        if (!args.CanAccess || !args.CanInteract || args.Hands == null)
+        if (!args.CanAccess || !args.CanInteract || args.Hands is null)
             return;
 
+        var user = args.User;
+
         InteractionVerb verb = new()
         {
             Act = () =>
             {
-                ToggleInternals(uid, args.User, false, component);
+                ToggleInternals(ent, user, force: false, ent);
             },
             Message = Loc.GetString("action-description-internals-toggle"),
-            Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/dot.svg.192dpi.png")),
+            Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/dot.svg.192dpi.png")),
             Text = Loc.GetString("action-name-internals-toggle"),
         };
 
         args.Verbs.Add(verb);
     }
 
-    public void ToggleInternals(EntityUid uid, EntityUid user, bool force, InternalsComponent? internals = null)
+    public void ToggleInternals(
+        EntityUid uid,
+        EntityUid user,
+        bool force,
+        InternalsComponent? internals = null)
     {
-        if (!Resolve(uid, ref internals, false))
+        if (!Resolve(uid, ref internals, logMissing: false))
             return;
 
         // Toggle off if they're on
@@ -73,12 +79,12 @@ public sealed class InternalsSystem : EntitySystem
                 return;
             }
 
-            StartToggleInternalsDoAfter(user, uid, internals);
+            StartToggleInternalsDoAfter(user, (uid, internals));
             return;
         }
 
         // If they're not on then check if we have a mask to use
-        if (internals.BreathToolEntity == null)
+        if (internals.BreathToolEntity is null)
         {
             _popupSystem.PopupEntity(Loc.GetString("internals-no-breath-tool"), uid, user);
             return;
@@ -86,7 +92,7 @@ public sealed class InternalsSystem : EntitySystem
 
         var tank = FindBestGasTank(uid);
 
-        if (tank == null)
+        if (tank is null)
         {
             _popupSystem.PopupEntity(Loc.GetString("internals-no-tank"), uid, user);
             return;
@@ -94,20 +100,20 @@ public sealed class InternalsSystem : EntitySystem
 
         if (!force)
         {
-            StartToggleInternalsDoAfter(user, uid, internals);
+            StartToggleInternalsDoAfter(user, (uid, internals));
             return;
         }
 
         _gasTank.ConnectToInternals(tank.Value);
     }
 
-    private void StartToggleInternalsDoAfter(EntityUid user, EntityUid target, InternalsComponent internals)
+    private void StartToggleInternalsDoAfter(EntityUid user, Entity<InternalsComponent> targetEnt)
     {
         // Is the target not you? If yes, use a do-after to give them time to respond.
-        var isUser = user == target;
-        var delay = !isUser ? internals.Delay : 0f;
+        var isUser = user == targetEnt.Owner;
+        var delay = !isUser ? targetEnt.Comp.Delay : TimeSpan.Zero;
 
-        _doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager, user, delay, new InternalsDoAfterEvent(), target, target: target)
+        _doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager, user, delay, new InternalsDoAfterEvent(), targetEnt, target: targetEnt)
         {
             BreakOnDamage = true,
             BreakOnMove =  true,
@@ -115,66 +121,64 @@ public sealed class InternalsSystem : EntitySystem
         });
     }
 
-    private void OnDoAfter(EntityUid uid, InternalsComponent component, InternalsDoAfterEvent args)
+    private void OnDoAfter(Entity<InternalsComponent> ent, ref InternalsDoAfterEvent args)
     {
         if (args.Cancelled || args.Handled)
             return;
 
-        ToggleInternals(uid, args.User, true, component);
+        ToggleInternals(ent, args.User, force: true, ent);
 
         args.Handled = true;
     }
 
-    private void OnInternalsStartup(EntityUid uid, InternalsComponent component, ComponentStartup args)
+    private void OnInternalsStartup(Entity<InternalsComponent> ent, ref ComponentStartup args)
     {
-        _alerts.ShowAlert(uid, AlertType.Internals, GetSeverity(component));
+        _alerts.ShowAlert(ent, AlertType.Internals, GetSeverity(ent));
     }
 
-    private void OnInternalsShutdown(EntityUid uid, InternalsComponent component, ComponentShutdown args)
+    private void OnInternalsShutdown(Entity<InternalsComponent> ent, ref ComponentShutdown args)
     {
-        _alerts.ClearAlert(uid, AlertType.Internals);
+        _alerts.ClearAlert(ent, AlertType.Internals);
     }
 
-    private void OnInhaleLocation(EntityUid uid, InternalsComponent component, InhaleLocationEvent args)
+    private void OnInhaleLocation(Entity<InternalsComponent> ent, ref InhaleLocationEvent args)
     {
-        if (AreInternalsWorking(component))
+        if (AreInternalsWorking(ent))
         {
-            var gasTank = Comp<GasTankComponent>(component.GasTankEntity!.Value);
-            args.Gas = _gasTank.RemoveAirVolume((component.GasTankEntity.Value, gasTank), Atmospherics.BreathVolume);
+            var gasTank = Comp<GasTankComponent>(ent.Comp.GasTankEntity!.Value);
+            args.Gas = _gasTank.RemoveAirVolume((ent.Comp.GasTankEntity.Value, gasTank), Atmospherics.BreathVolume);
             // TODO: Should listen to gas tank updates instead I guess?
-            _alerts.ShowAlert(uid, AlertType.Internals, GetSeverity(component));
+            _alerts.ShowAlert(ent, AlertType.Internals, GetSeverity(ent));
         }
     }
     public void DisconnectBreathTool(Entity<InternalsComponent> ent)
     {
-        var (owner, component) = ent;
-        var old = component.BreathToolEntity;
-        component.BreathToolEntity = null;
+        var old = ent.Comp.BreathToolEntity;
+        ent.Comp.BreathToolEntity = null;
 
-        if (TryComp(old, out BreathToolComponent? breathTool) )
+        if (TryComp(old, out BreathToolComponent? breathTool))
         {
             _atmos.DisconnectInternals(breathTool);
             DisconnectTank(ent);
         }
 
-        _alerts.ShowAlert(owner, AlertType.Internals, GetSeverity(component));
+        _alerts.ShowAlert(ent, AlertType.Internals, GetSeverity(ent));
     }
 
     public void ConnectBreathTool(Entity<InternalsComponent> ent, EntityUid toolEntity)
     {
-        var (owner, component) = ent;
-        if (TryComp(component.BreathToolEntity, out BreathToolComponent? tool))
+        if (TryComp(ent.Comp.BreathToolEntity, out BreathToolComponent? tool))
         {
             _atmos.DisconnectInternals(tool);
         }
 
-        component.BreathToolEntity = toolEntity;
-        _alerts.ShowAlert(owner, AlertType.Internals, GetSeverity(component));
+        ent.Comp.BreathToolEntity = toolEntity;
+        _alerts.ShowAlert(ent, AlertType.Internals, GetSeverity(ent));
     }
 
     public void DisconnectTank(InternalsComponent? component)
     {
-        if (component == null)
+        if (component is null)
             return;
 
         if (TryComp(component.GasTankEntity, out GasTankComponent? tank))
@@ -186,46 +190,47 @@ public sealed class InternalsSystem : EntitySystem
 
     public bool TryConnectTank(Entity<InternalsComponent> ent, EntityUid tankEntity)
     {
-        var component = ent.Comp;
-        if (component.BreathToolEntity == null)
+        if (ent.Comp.BreathToolEntity is null)
             return false;
 
-        if (TryComp(component.GasTankEntity, out GasTankComponent? tank))
-            _gasTank.DisconnectFromInternals((component.GasTankEntity.Value, tank));
+        if (TryComp(ent.Comp.GasTankEntity, out GasTankComponent? tank))
+            _gasTank.DisconnectFromInternals((ent.Comp.GasTankEntity.Value, tank));
 
-        component.GasTankEntity = tankEntity;
-        _alerts.ShowAlert(ent, AlertType.Internals, GetSeverity(component));
+        ent.Comp.GasTankEntity = tankEntity;
+        _alerts.ShowAlert(ent, AlertType.Internals, GetSeverity(ent));
         return true;
     }
 
     public bool AreInternalsWorking(EntityUid uid, InternalsComponent? component = null)
     {
-        if (!Resolve(uid, ref component, false))
-            return false;
-
-        return AreInternalsWorking(component);
+        return Resolve(uid, ref component, logMissing: false)
+            && AreInternalsWorking(component);
     }
 
     public bool AreInternalsWorking(InternalsComponent component)
     {
-        return TryComp(component.BreathToolEntity, out BreathToolComponent? breathTool) &&
-               breathTool.IsFunctional &&
-               TryComp(component.GasTankEntity, out GasTankComponent? _);
+        return TryComp(component.BreathToolEntity, out BreathToolComponent? breathTool)
+            && breathTool.IsFunctional
+            && HasComp<GasTankComponent>(component.GasTankEntity);
     }
 
     private short GetSeverity(InternalsComponent component)
     {
-        if (component.BreathToolEntity == null || !AreInternalsWorking(component))
+        if (component.BreathToolEntity is null || !AreInternalsWorking(component))
             return 2;
 
         // If pressure in the tank is below low pressure threshhold, flash warning on internals UI
-        if (TryComp<GasTankComponent>(component.GasTankEntity, out var gasTank) && gasTank.IsLowPressure)
+        if (TryComp<GasTankComponent>(component.GasTankEntity, out var gasTank)
+            && gasTank.IsLowPressure)
+        {
             return 0;
+        }
 
         return 1;
     }
 
-    public Entity<GasTankComponent>? FindBestGasTank(Entity<HandsComponent?, InventoryComponent?, ContainerManagerComponent?> user)
+    public Entity<GasTankComponent>? FindBestGasTank(
+        Entity<HandsComponent?, InventoryComponent?, ContainerManagerComponent?> user)
     {
         // Prioritise
         // 1. back equipped tanks
@@ -233,17 +238,17 @@ public sealed class InternalsSystem : EntitySystem
         // 3. in-hand tanks
         // 4. pocket/belt tanks
 
-        if (!Resolve(user.Owner, ref user.Comp1, ref user.Comp2, ref user.Comp3))
+        if (!Resolve(user, ref user.Comp1, ref user.Comp2, ref user.Comp3))
             return null;
 
-        if (_inventory.TryGetSlotEntity(user.Owner, "back", out var backEntity, user.Comp2, user.Comp3) &&
+        if (_inventory.TryGetSlotEntity(user, "back", out var backEntity, user.Comp2, user.Comp3) &&
             TryComp<GasTankComponent>(backEntity, out var backGasTank) &&
             _gasTank.CanConnectToInternals(backGasTank))
         {
             return (backEntity.Value, backGasTank);
         }
 
-        if (_inventory.TryGetSlotEntity(user.Owner, "suitstorage", out var entity, user.Comp2, user.Comp3) &&
+        if (_inventory.TryGetSlotEntity(user, "suitstorage", out var entity, user.Comp2, user.Comp3) &&
             TryComp<GasTankComponent>(entity, out var gasTank) &&
             _gasTank.CanConnectToInternals(gasTank))
         {
index 4b60f8814b5335d020298084099293643dfeb0cb..e83d3c32a25fb3c597615deeef096dc657336cd0 100644 (file)
@@ -1,4 +1,4 @@
-using Content.Server.Atmos.Components;
+using Content.Server.Atmos.Components;
 using Content.Server.Atmos.EntitySystems;
 using Content.Server.Body.Components;
 using Content.Server.Chemistry.Containers.EntitySystems;
@@ -26,21 +26,24 @@ public sealed class LungSystem : EntitySystem
         SubscribeLocalEvent<BreathToolComponent, ItemMaskToggledEvent>(OnMaskToggled);
     }
 
-    private void OnGotUnequipped(EntityUid uid, BreathToolComponent component, GotUnequippedEvent args)
+    private void OnGotUnequipped(Entity<BreathToolComponent> ent, ref GotUnequippedEvent args)
     {
-        _atmosphereSystem.DisconnectInternals(component);
+        _atmosphereSystem.DisconnectInternals(ent);
     }
 
-    private void OnGotEquipped(EntityUid uid, BreathToolComponent component, GotEquippedEvent args)
+    private void OnGotEquipped(Entity<BreathToolComponent> ent, ref GotEquippedEvent args)
     {
+        if ((args.SlotFlags & ent.Comp.AllowedSlots) == 0)
+        {
+            return;
+        }
 
-        if ((args.SlotFlags & component.AllowedSlots) == 0) return;
-        component.IsFunctional = true;
+        ent.Comp.IsFunctional = true;
 
         if (TryComp(args.Equipee, out InternalsComponent? internals))
         {
-            component.ConnectedInternalsEntity = args.Equipee;
-            _internals.ConnectBreathTool((args.Equipee, internals), uid);
+            ent.Comp.ConnectedInternalsEntity = args.Equipee;
+            _internals.ConnectBreathTool((args.Equipee, internals), ent);
         }
     }
 
@@ -81,7 +84,7 @@ public sealed class LungSystem : EntitySystem
             if (moles <= 0)
                 continue;
             var reagent = _atmosphereSystem.GasReagents[i];
-            if (reagent == null) continue;
+            if (reagent is null) continue;
 
             var amount = moles * Atmospherics.BreathMolesToReagentMultiplier;
             solution.AddReagent(reagent, amount);
index e5f604f70dfb4ae6d7a44910e6f6c51fac9bbe7a..45cba5a195f234768e0cba36fef96a2aeb073e8a 100644 (file)
@@ -12,11 +12,13 @@ using Content.Shared.Mobs.Systems;
 using Robust.Shared.Collections;
 using Robust.Shared.Prototypes;
 using Robust.Shared.Random;
+using Robust.Shared.Timing;
 
 namespace Content.Server.Body.Systems
 {
     public sealed class MetabolizerSystem : EntitySystem
     {
+        [Dependency] private readonly IGameTiming _gameTiming = default!;
         [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
         [Dependency] private readonly IRobustRandom _random = default!;
         [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
@@ -34,9 +36,21 @@ namespace Content.Server.Body.Systems
             _solutionQuery = GetEntityQuery<SolutionContainerManagerComponent>();
 
             SubscribeLocalEvent<MetabolizerComponent, ComponentInit>(OnMetabolizerInit);
+            SubscribeLocalEvent<MetabolizerComponent, MapInitEvent>(OnMapInit);
+            SubscribeLocalEvent<MetabolizerComponent, EntityUnpausedEvent>(OnUnpaused);
             SubscribeLocalEvent<MetabolizerComponent, ApplyMetabolicMultiplierEvent>(OnApplyMetabolicMultiplier);
         }
 
+        private void OnMapInit(Entity<MetabolizerComponent> ent, ref MapInitEvent args)
+        {
+            ent.Comp.NextUpdate = _gameTiming.CurTime + ent.Comp.UpdateInterval;
+        }
+
+        private void OnUnpaused(Entity<MetabolizerComponent> ent, ref EntityUnpausedEvent args)
+        {
+            ent.Comp.NextUpdate += args.PausedTime;
+        }
+
         private void OnMetabolizerInit(Entity<MetabolizerComponent> entity, ref ComponentInit args)
         {
             if (!entity.Comp.SolutionOnBody)
@@ -49,19 +63,17 @@ namespace Content.Server.Body.Systems
             }
         }
 
-        private void OnApplyMetabolicMultiplier(EntityUid uid, MetabolizerComponent component,
-            ApplyMetabolicMultiplierEvent args)
+        private void OnApplyMetabolicMultiplier(
+            Entity<MetabolizerComponent> ent,
+            ref ApplyMetabolicMultiplierEvent args)
         {
             if (args.Apply)
             {
-                component.UpdateFrequency *= args.Multiplier;
+                ent.Comp.UpdateInterval *= args.Multiplier;
                 return;
             }
 
-            component.UpdateFrequency /= args.Multiplier;
-            // Reset the accumulator properly
-            if (component.AccumulatedFrametime >= component.UpdateFrequency)
-                component.AccumulatedFrametime = component.UpdateFrequency;
+            ent.Comp.UpdateInterval /= args.Multiplier;
         }
 
         public override void Update(float frameTime)
@@ -78,50 +90,52 @@ namespace Content.Server.Body.Systems
 
             foreach (var (uid, metab) in metabolizers)
             {
-                metab.AccumulatedFrametime += frameTime;
-
                 // Only update as frequently as it should
-                if (metab.AccumulatedFrametime < metab.UpdateFrequency)
+                if (_gameTiming.CurTime < metab.NextUpdate)
                     continue;
 
-                metab.AccumulatedFrametime -= metab.UpdateFrequency;
-                TryMetabolize(uid, metab);
+                metab.NextUpdate += metab.UpdateInterval;
+                TryMetabolize((uid, metab));
             }
         }
 
-        private void TryMetabolize(EntityUid uid, MetabolizerComponent meta, OrganComponent? organ = null)
+        private void TryMetabolize(Entity<MetabolizerComponent, OrganComponent?, SolutionContainerManagerComponent?> ent)
         {
-            _organQuery.Resolve(uid, ref organ, false);
+            _organQuery.Resolve(ent, ref ent.Comp2, logMissing: false);
 
             // First step is get the solution we actually care about
+            var solutionName = ent.Comp1.SolutionName;
             Solution? solution = null;
             Entity<SolutionComponent>? soln = default!;
             EntityUid? solutionEntityUid = null;
 
-            SolutionContainerManagerComponent? manager = null;
-
-            if (meta.SolutionOnBody)
+            if (ent.Comp1.SolutionOnBody)
             {
-                if (organ?.Body is { } body)
+                if (ent.Comp2?.Body is { } body)
                 {
-                    if (!_solutionQuery.Resolve(body, ref manager, false))
+                    if (!_solutionQuery.Resolve(body, ref ent.Comp3, logMissing: false))
                         return;
 
-                    _solutionContainerSystem.TryGetSolution((body, manager), meta.SolutionName, out soln, out solution);
+                    _solutionContainerSystem.TryGetSolution((body, ent.Comp3), solutionName, out soln, out solution);
                     solutionEntityUid = body;
                 }
             }
             else
             {
-                if (!_solutionQuery.Resolve(uid, ref manager, false))
+                if (!_solutionQuery.Resolve(ent, ref ent.Comp3, logMissing: false))
                     return;
 
-                _solutionContainerSystem.TryGetSolution((uid, manager), meta.SolutionName, out soln, out solution);
-                solutionEntityUid = uid;
+                _solutionContainerSystem.TryGetSolution((ent, ent), solutionName, out soln, out solution);
+                solutionEntityUid = ent;
             }
 
-            if (solutionEntityUid == null || soln is null || solution is null || solution.Contents.Count == 0)
+            if (solutionEntityUid is null
+                || soln is null
+                || solution is null
+                || solution.Contents.Count == 0)
+            {
                 return;
+            }
 
             // randomize the reagent list so we don't have any weird quirks
             // like alphabetical order or insertion order mattering for processing
@@ -135,9 +149,9 @@ namespace Content.Server.Body.Systems
                     continue;
 
                 var mostToRemove = FixedPoint2.Zero;
-                if (proto.Metabolisms == null)
+                if (proto.Metabolisms is null)
                 {
-                    if (meta.RemoveEmpty)
+                    if (ent.Comp1.RemoveEmpty)
                     {
                         solution.RemoveReagent(reagent, FixedPoint2.New(1));
                     }
@@ -146,15 +160,15 @@ namespace Content.Server.Body.Systems
                 }
 
                 // we're done here entirely if this is true
-                if (reagents >= meta.MaxReagentsProcessable)
+                if (reagents >= ent.Comp1.MaxReagentsProcessable)
                     return;
 
 
                 // loop over all our groups and see which ones apply
-                if (meta.MetabolismGroups == null)
+                if (ent.Comp1.MetabolismGroups is null)
                     continue;
 
-                foreach (var group in meta.MetabolismGroups)
+                foreach (var group in ent.Comp1.MetabolismGroups)
                 {
                     if (!proto.Metabolisms.TryGetValue(group.Id, out var entry))
                         continue;
@@ -169,14 +183,14 @@ namespace Content.Server.Body.Systems
                     // if it's possible for them to be dead, and they are,
                     // then we shouldn't process any effects, but should probably
                     // still remove reagents
-                    if (EntityManager.TryGetComponent<MobStateComponent>(solutionEntityUid.Value, out var state))
+                    if (TryComp<MobStateComponent>(solutionEntityUid.Value, out var state))
                     {
                         if (!proto.WorksOnTheDead && _mobStateSystem.IsDead(solutionEntityUid.Value, state))
                             continue;
                     }
 
-                    var actualEntity = organ?.Body ?? solutionEntityUid.Value;
-                    var args = new ReagentEffectArgs(actualEntity, uid, solution, proto, mostToRemove,
+                    var actualEntity = ent.Comp2?.Body ?? solutionEntityUid.Value;
+                    var args = new ReagentEffectArgs(actualEntity, ent, solution, proto, mostToRemove,
                         EntityManager, null, scale);
 
                     // do all effects, if conditions apply
@@ -187,8 +201,14 @@ namespace Content.Server.Body.Systems
 
                         if (effect.ShouldLog)
                         {
-                            _adminLogger.Add(LogType.ReagentEffect, effect.LogImpact,
-                                $"Metabolism effect {effect.GetType().Name:effect} of reagent {proto.LocalizedName:reagent} applied on entity {actualEntity:entity} at {Transform(actualEntity).Coordinates:coordinates}");
+                            _adminLogger.Add(
+                                LogType.ReagentEffect,
+                                effect.LogImpact,
+                                $"Metabolism effect {effect.GetType().Name:effect}"
+                                + $" of reagent {proto.LocalizedName:reagent}"
+                                + $" applied on entity {actualEntity:entity}"
+                                + $" at {Transform(actualEntity).Coordinates:coordinates}"
+                            );
                         }
 
                         effect.Effect(args);
@@ -209,15 +229,25 @@ namespace Content.Server.Body.Systems
         }
     }
 
-    public sealed class ApplyMetabolicMultiplierEvent : EntityEventArgs
+    [ByRefEvent]
+    public readonly record struct ApplyMetabolicMultiplierEvent(
+        EntityUid Uid,
+        float Multiplier,
+        bool Apply)
     {
-        // The entity whose metabolism is being modified
-        public EntityUid Uid;
-
-        // What the metabolism's update rate will be multiplied by
-        public float Multiplier;
-
-        // Apply this multiplier or ignore / reset it?
-        public bool Apply;
+        /// <summary>
+        /// The entity whose metabolism is being modified.
+        /// </summary>
+        public readonly EntityUid Uid = Uid;
+
+        /// <summary>
+        /// What the metabolism's update rate will be multiplied by.
+        /// </summary>
+        public readonly float Multiplier = Multiplier;
+
+        /// <summary>
+        /// If true, apply the multiplier. If false, revert it.
+        /// </summary>
+        public readonly bool Apply = Apply;
     }
 }
index 0fd61a9cb7b2dd3c1f29c34325e78da0dad52e66..c7266e2c463e93d41b179334de5607b593f94bd6 100644 (file)
@@ -35,9 +35,21 @@ public sealed class RespiratorSystem : EntitySystem
 
         // We want to process lung reagents before we inhale new reagents.
         UpdatesAfter.Add(typeof(MetabolizerSystem));
+        SubscribeLocalEvent<RespiratorComponent, MapInitEvent>(OnMapInit);
+        SubscribeLocalEvent<RespiratorComponent, EntityUnpausedEvent>(OnUnpaused);
         SubscribeLocalEvent<RespiratorComponent, ApplyMetabolicMultiplierEvent>(OnApplyMetabolicMultiplier);
     }
 
+    private void OnMapInit(Entity<RespiratorComponent> ent, ref MapInitEvent args)
+    {
+        ent.Comp.NextUpdate = _gameTiming.CurTime + ent.Comp.UpdateInterval;
+    }
+
+    private void OnUnpaused(Entity<RespiratorComponent> ent, ref EntityUnpausedEvent args)
+    {
+        ent.Comp.NextUpdate += args.PausedTime;
+    }
+
     public override void Update(float frameTime)
     {
         base.Update(frameTime);
@@ -45,17 +57,15 @@ public sealed class RespiratorSystem : EntitySystem
         var query = EntityQueryEnumerator<RespiratorComponent, BodyComponent>();
         while (query.MoveNext(out var uid, out var respirator, out var body))
         {
-            if (_mobState.IsDead(uid))
-            {
+            if (_gameTiming.CurTime < respirator.NextUpdate)
                 continue;
-            }
 
-            respirator.AccumulatedFrametime += frameTime;
+            respirator.NextUpdate += respirator.UpdateInterval;
 
-            if (respirator.AccumulatedFrametime < respirator.CycleDelay)
+            if (_mobState.IsDead(uid))
                 continue;
-            respirator.AccumulatedFrametime -= respirator.CycleDelay;
-            UpdateSaturation(uid, -respirator.CycleDelay, respirator);
+
+            UpdateSaturation(uid, -(float) respirator.UpdateInterval.TotalSeconds, respirator);
 
             if (!_mobState.IsIncapacitated(uid)) // cannot breathe in crit.
             {
@@ -80,30 +90,30 @@ public sealed class RespiratorSystem : EntitySystem
                     _popupSystem.PopupEntity(Loc.GetString("lung-behavior-gasp"), uid);
                 }
 
-                TakeSuffocationDamage(uid, respirator);
+                TakeSuffocationDamage((uid, respirator));
                 respirator.SuffocationCycles += 1;
                 continue;
             }
 
-            StopSuffocation(uid, respirator);
+            StopSuffocation((uid, respirator));
             respirator.SuffocationCycles = 0;
         }
     }
 
     public void Inhale(EntityUid uid, BodyComponent? body = null)
     {
-        if (!Resolve(uid, ref body, false))
+        if (!Resolve(uid, ref body, logMissing: false))
             return;
 
         var organs = _bodySystem.GetBodyOrganComponents<LungComponent>(uid, body);
 
         // Inhale gas
         var ev = new InhaleLocationEvent();
-        RaiseLocalEvent(uid, ev);
+        RaiseLocalEvent(uid, ref ev, broadcast: false);
 
-        ev.Gas ??= _atmosSys.GetContainingMixture(uid, false, true);
+        ev.Gas ??= _atmosSys.GetContainingMixture(uid, excite: true);
 
-        if (ev.Gas == null)
+        if (ev.Gas is null)
         {
             return;
         }
@@ -122,7 +132,7 @@ public sealed class RespiratorSystem : EntitySystem
 
     public void Exhale(EntityUid uid, BodyComponent? body = null)
     {
-        if (!Resolve(uid, ref body, false))
+        if (!Resolve(uid, ref body, logMissing: false))
             return;
 
         var organs = _bodySystem.GetBodyOrganComponents<LungComponent>(uid, body);
@@ -130,11 +140,11 @@ public sealed class RespiratorSystem : EntitySystem
         // exhale gas
 
         var ev = new ExhaleLocationEvent();
-        RaiseLocalEvent(uid, ev, false);
+        RaiseLocalEvent(uid, ref ev, broadcast: false);
 
-        if (ev.Gas == null)
+        if (ev.Gas is null)
         {
-            ev.Gas = _atmosSys.GetContainingMixture(uid, false, true);
+            ev.Gas = _atmosSys.GetContainingMixture(uid, excite: true);
 
             // Walls and grids without atmos comp return null. I guess it makes sense to not be able to exhale in walls,
             // but this also means you cannot exhale on some grids.
@@ -154,37 +164,37 @@ public sealed class RespiratorSystem : EntitySystem
         _atmosSys.Merge(ev.Gas, outGas);
     }
 
-    private void TakeSuffocationDamage(EntityUid uid, RespiratorComponent respirator)
+    private void TakeSuffocationDamage(Entity<RespiratorComponent> ent)
     {
-        if (respirator.SuffocationCycles == 2)
-            _adminLogger.Add(LogType.Asphyxiation, $"{ToPrettyString(uid):entity} started suffocating");
+        if (ent.Comp.SuffocationCycles == 2)
+            _adminLogger.Add(LogType.Asphyxiation, $"{ToPrettyString(ent):entity} started suffocating");
 
-        if (respirator.SuffocationCycles >= respirator.SuffocationCycleThreshold)
+        if (ent.Comp.SuffocationCycles >= ent.Comp.SuffocationCycleThreshold)
         {
             // TODO: This is not going work with multiple different lungs, if that ever becomes a possibility
-            var organs = _bodySystem.GetBodyOrganComponents<LungComponent>(uid);
+            var organs = _bodySystem.GetBodyOrganComponents<LungComponent>(ent);
             foreach (var (comp, _) in organs)
             {
-                _alertsSystem.ShowAlert(uid, comp.Alert);
+                _alertsSystem.ShowAlert(ent, comp.Alert);
             }
         }
 
-        _damageableSys.TryChangeDamage(uid, respirator.Damage, false, false);
+        _damageableSys.TryChangeDamage(ent, ent.Comp.Damage, interruptsDoAfters: false);
     }
 
-    private void StopSuffocation(EntityUid uid, RespiratorComponent respirator)
+    private void StopSuffocation(Entity<RespiratorComponent> ent)
     {
-        if (respirator.SuffocationCycles >= 2)
-            _adminLogger.Add(LogType.Asphyxiation, $"{ToPrettyString(uid):entity} stopped suffocating");
+        if (ent.Comp.SuffocationCycles >= 2)
+            _adminLogger.Add(LogType.Asphyxiation, $"{ToPrettyString(ent):entity} stopped suffocating");
 
         // TODO: This is not going work with multiple different lungs, if that ever becomes a possibility
-        var organs = _bodySystem.GetBodyOrganComponents<LungComponent>(uid);
+        var organs = _bodySystem.GetBodyOrganComponents<LungComponent>(ent);
         foreach (var (comp, _) in organs)
         {
-            _alertsSystem.ClearAlert(uid, comp.Alert);
+            _alertsSystem.ClearAlert(ent, comp.Alert);
         }
 
-        _damageableSys.TryChangeDamage(uid, respirator.DamageRecovery);
+        _damageableSys.TryChangeDamage(ent, ent.Comp.DamageRecovery);
     }
 
     public void UpdateSaturation(EntityUid uid, float amount,
@@ -198,35 +208,29 @@ public sealed class RespiratorSystem : EntitySystem
             Math.Clamp(respirator.Saturation, respirator.MinSaturation, respirator.MaxSaturation);
     }
 
-    private void OnApplyMetabolicMultiplier(EntityUid uid, RespiratorComponent component,
-            ApplyMetabolicMultiplierEvent args)
+    private void OnApplyMetabolicMultiplier(
+        Entity<RespiratorComponent> ent,
+        ref ApplyMetabolicMultiplierEvent args)
     {
         if (args.Apply)
         {
-            component.CycleDelay *= args.Multiplier;
-            component.Saturation *= args.Multiplier;
-            component.MaxSaturation *= args.Multiplier;
-            component.MinSaturation *= args.Multiplier;
+            ent.Comp.UpdateInterval *= args.Multiplier;
+            ent.Comp.Saturation *= args.Multiplier;
+            ent.Comp.MaxSaturation *= args.Multiplier;
+            ent.Comp.MinSaturation *= args.Multiplier;
             return;
         }
 
         // This way we don't have to worry about it breaking if the stasis bed component is destroyed
-        component.CycleDelay /= args.Multiplier;
-        component.Saturation /= args.Multiplier;
-        component.MaxSaturation /= args.Multiplier;
-        component.MinSaturation /= args.Multiplier;
-        // Reset the accumulator properly
-        if (component.AccumulatedFrametime >= component.CycleDelay)
-            component.AccumulatedFrametime = component.CycleDelay;
+        ent.Comp.UpdateInterval /= args.Multiplier;
+        ent.Comp.Saturation /= args.Multiplier;
+        ent.Comp.MaxSaturation /= args.Multiplier;
+        ent.Comp.MinSaturation /= args.Multiplier;
     }
 }
 
-public sealed class InhaleLocationEvent : EntityEventArgs
-{
-    public GasMixture? Gas;
-}
+[ByRefEvent]
+public record struct InhaleLocationEvent(GasMixture? Gas);
 
-public sealed class ExhaleLocationEvent : EntityEventArgs
-{
-    public GasMixture? Gas;
-}
+[ByRefEvent]
+public record struct ExhaleLocationEvent(GasMixture? Gas);
index 4c11244c379ee195236a005da005301baf55c861..a4c2e8292dd50b5bb11eadb0cdf5693a9ed028dd 100644 (file)
@@ -3,32 +3,44 @@ using Content.Server.Chemistry.Containers.EntitySystems;
 using Content.Shared.Body.Organ;
 using Content.Shared.Chemistry.Components;
 using Content.Shared.Chemistry.Components.SolutionManager;
+using Robust.Shared.Timing;
 using Robust.Shared.Utility;
 
 namespace Content.Server.Body.Systems
 {
     public sealed class StomachSystem : EntitySystem
     {
+        [Dependency] private readonly IGameTiming _gameTiming = default!;
         [Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
 
         public const string DefaultSolutionName = "stomach";
 
         public override void Initialize()
         {
+            SubscribeLocalEvent<StomachComponent, MapInitEvent>(OnMapInit);
+            SubscribeLocalEvent<StomachComponent, EntityUnpausedEvent>(OnUnpaused);
             SubscribeLocalEvent<StomachComponent, ApplyMetabolicMultiplierEvent>(OnApplyMetabolicMultiplier);
         }
 
+        private void OnMapInit(Entity<StomachComponent> ent, ref MapInitEvent args)
+        {
+            ent.Comp.NextUpdate = _gameTiming.CurTime + ent.Comp.UpdateInterval;
+        }
+
+        private void OnUnpaused(Entity<StomachComponent> ent, ref EntityUnpausedEvent args)
+        {
+            ent.Comp.NextUpdate += args.PausedTime;
+        }
+
         public override void Update(float frameTime)
         {
             var query = EntityQueryEnumerator<StomachComponent, OrganComponent, SolutionContainerManagerComponent>();
             while (query.MoveNext(out var uid, out var stomach, out var organ, out var sol))
             {
-                stomach.AccumulatedFrameTime += frameTime;
-
-                if (stomach.AccumulatedFrameTime < stomach.UpdateInterval)
+                if (_gameTiming.CurTime < stomach.NextUpdate)
                     continue;
 
-                stomach.AccumulatedFrameTime -= stomach.UpdateInterval;
+                stomach.NextUpdate += stomach.UpdateInterval;
 
                 // Get our solutions
                 if (!_solutionContainerSystem.ResolveSolution((uid, sol), DefaultSolutionName, ref stomach.Solution, out var stomachSolution))
@@ -70,49 +82,44 @@ namespace Content.Server.Body.Systems
             }
         }
 
-        private void OnApplyMetabolicMultiplier(EntityUid uid, StomachComponent component,
-            ApplyMetabolicMultiplierEvent args)
+        private void OnApplyMetabolicMultiplier(
+            Entity<StomachComponent> ent,
+            ref ApplyMetabolicMultiplierEvent args)
         {
             if (args.Apply)
             {
-                component.UpdateInterval *= args.Multiplier;
+                ent.Comp.UpdateInterval *= args.Multiplier;
                 return;
             }
 
             // This way we don't have to worry about it breaking if the stasis bed component is destroyed
-            component.UpdateInterval /= args.Multiplier;
-            // Reset the accumulator properly
-            if (component.AccumulatedFrameTime >= component.UpdateInterval)
-                component.AccumulatedFrameTime = component.UpdateInterval;
+            ent.Comp.UpdateInterval /= args.Multiplier;
         }
 
-        public bool CanTransferSolution(EntityUid uid, Solution solution,
+        public bool CanTransferSolution(
+            EntityUid uid,
+            Solution solution,
             StomachComponent? stomach = null,
             SolutionContainerManagerComponent? solutions = null)
         {
-            if (!Resolve(uid, ref stomach, ref solutions, false))
-                return false;
-
-            if (!_solutionContainerSystem.ResolveSolution((uid, solutions), DefaultSolutionName, ref stomach.Solution, out var stomachSolution))
-                return false;
-
-            // TODO: For now no partial transfers. Potentially change by design
-            if (!stomachSolution.CanAddSolution(solution))
-                return false;
-
-            return true;
+            return Resolve(uid, ref stomach, ref solutions, logMissing: false)
+                && _solutionContainerSystem.ResolveSolution((uid, solutions), DefaultSolutionName, ref stomach.Solution, out var stomachSolution)
+                // TODO: For now no partial transfers. Potentially change by design
+                && stomachSolution.CanAddSolution(solution);
         }
 
-        public bool TryTransferSolution(EntityUid uid, Solution solution,
+        public bool TryTransferSolution(
+            EntityUid uid,
+            Solution solution,
             StomachComponent? stomach = null,
             SolutionContainerManagerComponent? solutions = null)
         {
-            if (!Resolve(uid, ref stomach, ref solutions, false))
-                return false;
-
-            if (!_solutionContainerSystem.ResolveSolution((uid, solutions), DefaultSolutionName, ref stomach.Solution)
+            if (!Resolve(uid, ref stomach, ref solutions, logMissing: false)
+                || !_solutionContainerSystem.ResolveSolution((uid, solutions), DefaultSolutionName, ref stomach.Solution)
                 || !CanTransferSolution(uid, solution, stomach, solutions))
+            {
                 return false;
+            }
 
             _solutionContainerSystem.TryAddSolution(stomach.Solution.Value, solution);
             // Add each reagent to ReagentDeltas. Used to track how long each reagent has been in the stomach
index a9556be7738ef968d09ba43df1ba71ef206f9d31..a8bf4184ac81deab3c9e66974464b1c8d6f1cf12 100644 (file)
@@ -1,73 +1,95 @@
-using Content.Server.Body.Components;
+using Content.Server.Body.Components;
 using Content.Server.Temperature.Components;
 using Content.Server.Temperature.Systems;
 using Content.Shared.ActionBlocker;
+using Robust.Shared.Timing;
 
 namespace Content.Server.Body.Systems;
 
 public sealed class ThermalRegulatorSystem : EntitySystem
 {
+    [Dependency] private readonly IGameTiming _gameTiming = default!;
     [Dependency] private readonly TemperatureSystem _tempSys = default!;
     [Dependency] private readonly ActionBlockerSystem _actionBlockerSys = default!;
 
+    public override void Initialize()
+    {
+        base.Initialize();
+
+        SubscribeLocalEvent<ThermalRegulatorComponent, MapInitEvent>(OnMapInit);
+        SubscribeLocalEvent<ThermalRegulatorComponent, EntityUnpausedEvent>(OnUnpaused);
+    }
+
+    private void OnMapInit(Entity<ThermalRegulatorComponent> ent, ref MapInitEvent args)
+    {
+        ent.Comp.NextUpdate = _gameTiming.CurTime + ent.Comp.UpdateInterval;
+    }
+
+    private void OnUnpaused(Entity<ThermalRegulatorComponent> ent, ref EntityUnpausedEvent args)
+    {
+        ent.Comp.NextUpdate += args.PausedTime;
+    }
+
     public override void Update(float frameTime)
     {
         var query = EntityQueryEnumerator<ThermalRegulatorComponent>();
         while (query.MoveNext(out var uid, out var regulator))
         {
-            regulator.AccumulatedFrametime += frameTime;
-            if (regulator.AccumulatedFrametime < 1)
+            if (_gameTiming.CurTime < regulator.NextUpdate)
                 continue;
 
-            regulator.AccumulatedFrametime -= 1;
-            ProcessThermalRegulation(uid, regulator);
+            regulator.NextUpdate += regulator.UpdateInterval;
+            ProcessThermalRegulation((uid, regulator));
         }
     }
 
     /// <summary>
     /// Processes thermal regulation for a mob
     /// </summary>
-    private void ProcessThermalRegulation(EntityUid uid, ThermalRegulatorComponent comp)
+    private void ProcessThermalRegulation(Entity<ThermalRegulatorComponent, TemperatureComponent?> ent)
     {
-        if (!EntityManager.TryGetComponent(uid, out TemperatureComponent? temperatureComponent)) return;
+        if (!Resolve(ent, ref ent.Comp2, logMissing: false))
+            return;
 
-        var totalMetabolismTempChange = comp.MetabolismHeat - comp.RadiatedHeat;
+        var totalMetabolismTempChange = ent.Comp1.MetabolismHeat - ent.Comp1.RadiatedHeat;
 
         // implicit heat regulation
-        var tempDiff = Math.Abs(temperatureComponent.CurrentTemperature - comp.NormalBodyTemperature);
-        var heatCapacity = _tempSys.GetHeatCapacity(uid, temperatureComponent);
+        var tempDiff = Math.Abs(ent.Comp2.CurrentTemperature - ent.Comp1.NormalBodyTemperature);
+        var heatCapacity = _tempSys.GetHeatCapacity(ent, ent);
         var targetHeat = tempDiff * heatCapacity;
-        if (temperatureComponent.CurrentTemperature > comp.NormalBodyTemperature)
+        if (ent.Comp2.CurrentTemperature > ent.Comp1.NormalBodyTemperature)
         {
-            totalMetabolismTempChange -= Math.Min(targetHeat, comp.ImplicitHeatRegulation);
+            totalMetabolismTempChange -= Math.Min(targetHeat, ent.Comp1.ImplicitHeatRegulation);
         }
         else
         {
-            totalMetabolismTempChange += Math.Min(targetHeat, comp.ImplicitHeatRegulation);
+            totalMetabolismTempChange += Math.Min(targetHeat, ent.Comp1.ImplicitHeatRegulation);
         }
 
-        _tempSys.ChangeHeat(uid, totalMetabolismTempChange, true, temperatureComponent);
+        _tempSys.ChangeHeat(ent, totalMetabolismTempChange, ignoreHeatResistance: true, ent);
 
         // recalc difference and target heat
-        tempDiff = Math.Abs(temperatureComponent.CurrentTemperature - comp.NormalBodyTemperature);
+        tempDiff = Math.Abs(ent.Comp2.CurrentTemperature - ent.Comp1.NormalBodyTemperature);
         targetHeat = tempDiff * heatCapacity;
 
         // if body temperature is not within comfortable, thermal regulation
         // processes starts
-        if (tempDiff > comp.ThermalRegulationTemperatureThreshold)
+        if (tempDiff > ent.Comp1.ThermalRegulationTemperatureThreshold)
             return;
 
-        if (temperatureComponent.CurrentTemperature > comp.NormalBodyTemperature)
+        if (ent.Comp2.CurrentTemperature > ent.Comp1.NormalBodyTemperature)
         {
-            if (!_actionBlockerSys.CanSweat(uid)) return;
-            _tempSys.ChangeHeat(uid, -Math.Min(targetHeat, comp.SweatHeatRegulation), true,
-                temperatureComponent);
+            if (!_actionBlockerSys.CanSweat(ent))
+                return;
+
+            _tempSys.ChangeHeat(ent, -Math.Min(targetHeat, ent.Comp1.SweatHeatRegulation), ignoreHeatResistance: true, ent);
         }
         else
         {
-            if (!_actionBlockerSys.CanShiver(uid)) return;
-            _tempSys.ChangeHeat(uid, Math.Min(targetHeat, comp.ShiveringHeatRegulation), true,
-                temperatureComponent);
+            if (!_actionBlockerSys.CanShiver(ent))
+                return;
+
+            _tempSys.ChangeHeat(ent, Math.Min(targetHeat, ent.Comp1.ShiveringHeatRegulation), ignoreHeatResistance: true, ent);
         }
     }
 }
index c783701003de37e983cca21f807a59a98de33c4d..06946cd05229852d8affa73fc11945be2e613a56 100644 (file)
@@ -101,17 +101,17 @@ namespace Content.Server.Hands.Systems
 
         private void HandleBodyPartAdded(EntityUid uid, HandsComponent component, ref BodyPartAddedEvent args)
         {
-            if (args.Part.PartType != BodyPartType.Hand)
+            if (args.Part.Comp.PartType != BodyPartType.Hand)
                 return;
 
             // If this annoys you, which it should.
             // Ping Smugleaf.
-            var location = args.Part.Symmetry switch
+            var location = args.Part.Comp.Symmetry switch
             {
                 BodyPartSymmetry.None => HandLocation.Middle,
                 BodyPartSymmetry.Left => HandLocation.Left,
                 BodyPartSymmetry.Right => HandLocation.Right,
-                _ => throw new ArgumentOutOfRangeException(nameof(args.Part.Symmetry))
+                _ => throw new ArgumentOutOfRangeException(nameof(args.Part.Comp.Symmetry))
             };
 
             AddHand(uid, args.Slot, location);
@@ -119,7 +119,7 @@ namespace Content.Server.Hands.Systems
 
         private void HandleBodyPartRemoved(EntityUid uid, HandsComponent component, ref BodyPartRemovedEvent args)
         {
-            if (args.Part.PartType != BodyPartType.Hand)
+            if (args.Part.Comp.PartType != BodyPartType.Hand)
                 return;
 
             RemoveHand(uid, args.Slot);
index b7751afbf18c7aa77b911903c2acb2c7458789b2..d491b957bfb3c0a7ef78cacf1243067d6e490dbc 100644 (file)
@@ -19,10 +19,10 @@ public sealed partial class NymphSystem : EntitySystem
     {
         base.Initialize();
 
-        SubscribeLocalEvent<NymphComponent, RemovedFromPartInBodyEvent>(OnRemovedFromPart);
+        SubscribeLocalEvent<NymphComponent, OrganRemovedFromBodyEvent>(OnRemovedFromPart);
     }
 
-    private void OnRemovedFromPart(EntityUid uid, NymphComponent comp, RemovedFromPartInBodyEvent args)
+    private void OnRemovedFromPart(EntityUid uid, NymphComponent comp, ref OrganRemovedFromBodyEvent args)
     {
         if (!_timing.IsFirstTimePredicted)
             return;
index a914a8f267d5e3fbad2c53e7c85d3f183d0c203b..f5ed2df227c491ac7277397fbd1e5281ab08c563 100644 (file)
@@ -202,7 +202,7 @@ namespace Content.Shared.ActionBlocker
         public bool CanShiver(EntityUid uid)
         {
             var ev = new ShiverAttemptEvent(uid);
-            RaiseLocalEvent(uid, ev);
+            RaiseLocalEvent(uid, ref ev);
 
             return !ev.Cancelled;
         }
@@ -210,7 +210,7 @@ namespace Content.Shared.ActionBlocker
         public bool CanSweat(EntityUid uid)
         {
             var ev = new SweatAttemptEvent(uid);
-            RaiseLocalEvent(uid, ev);
+            RaiseLocalEvent(uid, ref ev);
 
             return !ev.Cancelled;
         }
index b52a333613f5246f04dce06c0c53f1e3e03e5736..968b172aef5e99b1cca5dd438e7b345ea05bf73b 100644 (file)
@@ -1,61 +1,28 @@
-namespace Content.Shared.Body.Events
-{
-    // All of these events are raised on a mechanism entity when added/removed to a body in different
-    // ways.
-
-    /// <summary>
-    ///     Raised on a mechanism when it is added to a body part.
-    /// </summary>
-    public sealed class AddedToPartEvent : EntityEventArgs
-    {
-        public EntityUid Part;
-
-        public AddedToPartEvent(EntityUid part)
-        {
-            Part = part;
-        }
-    }
-
-    /// <summary>
-    ///     Raised on a mechanism when it is added to a body part within a body.
-    /// </summary>
-    public sealed class AddedToPartInBodyEvent : EntityEventArgs
-    {
-        public EntityUid Body;
-        public EntityUid Part;
-
-        public AddedToPartInBodyEvent(EntityUid body, EntityUid part)
-        {
-            Body = body;
-            Part = part;
-        }
-    }
-
-    /// <summary>
-    ///     Raised on a mechanism when it is removed from a body part.
-    /// </summary>
-    public sealed class RemovedFromPartEvent : EntityEventArgs
-    {
-        public EntityUid OldPart;
-
-        public RemovedFromPartEvent(EntityUid oldPart)
-        {
-            OldPart = oldPart;
-        }
-    }
-
-    /// <summary>
-    ///     Raised on a mechanism when it is removed from a body part within a body.
-    /// </summary>
-    public sealed class RemovedFromPartInBodyEvent : EntityEventArgs
-    {
-        public EntityUid OldBody;
-        public EntityUid OldPart;
-
-        public RemovedFromPartInBodyEvent(EntityUid oldBody, EntityUid oldPart)
-        {
-            OldBody = oldBody;
-            OldPart = oldPart;
-        }
-    }
-}
+namespace Content.Shared.Body.Events;
+
+// All of these events are raised on a mechanism entity when added/removed to a body in different
+// ways.
+
+/// <summary>
+/// Raised on a mechanism when it is added to a body part.
+/// </summary>
+[ByRefEvent]
+public readonly record struct OrganAddedEvent(EntityUid Part);
+
+/// <summary>
+/// Raised on a mechanism when it is added to a body part within a body.
+/// </summary>
+[ByRefEvent]
+public readonly record struct OrganAddedToBodyEvent(EntityUid Body, EntityUid Part);
+
+/// <summary>
+/// Raised on a mechanism when it is removed from a body part.
+/// </summary>
+[ByRefEvent]
+public readonly record struct OrganRemovedEvent(EntityUid OldPart);
+
+/// <summary>
+/// Raised on a mechanism when it is removed from a body part within a body.
+/// </summary>
+[ByRefEvent]
+public readonly record struct OrganRemovedFromBodyEvent(EntityUid OldBody, EntityUid OldPart);
index 8c2761f545d8d46c870e1a14cb4ea326b5cbacc1..e9400bc48d7bbf5bf92dfe69a895370cad534a83 100644 (file)
@@ -1,12 +1,8 @@
-namespace Content.Shared.Body.Events
-{
-    public sealed class ShiverAttemptEvent : CancellableEntityEventArgs
-    {
-        public ShiverAttemptEvent(EntityUid uid)
-        {
-            Uid = uid;
-        }
+namespace Content.Shared.Body.Events;
 
-        public EntityUid Uid { get; }
-    }
+[ByRefEvent]
+public record struct ShiverAttemptEvent(EntityUid Uid)
+{
+    public readonly EntityUid Uid = Uid;
+    public bool Cancelled = false;
 }
index 7f4b3fab15d8111e365dd8a37bdc31633bab6a5b..7506538c43976b10d227ba0dc5c28c9bd616df07 100644 (file)
@@ -1,12 +1,8 @@
-namespace Content.Shared.Body.Events
-{
-    public sealed class SweatAttemptEvent : CancellableEntityEventArgs
-    {
-        public SweatAttemptEvent(EntityUid uid)
-        {
-            Uid = uid;
-        }
+namespace Content.Shared.Body.Events;
 
-        public EntityUid Uid { get; }
-    }
+[ByRefEvent]
+public record struct SweatAttemptEvent(EntityUid Uid)
+{
+    public readonly EntityUid Uid = Uid;
+    public bool Cancelled = false;
 }
index 9e1de6b3559d7d3a39b51c430e56d6be75144e00..3048927b5fb719025946491b09f5ed045d27d2b8 100644 (file)
@@ -1,4 +1,4 @@
-using Content.Shared.Body.Systems;
+using Content.Shared.Body.Systems;
 using Robust.Shared.Containers;
 using Robust.Shared.GameStates;
 
@@ -11,6 +11,6 @@ public sealed partial class OrganComponent : Component
     /// <summary>
     /// Relevant body this organ is attached to.
     /// </summary>
-    [DataField("body"), AutoNetworkedField]
+    [DataField, AutoNetworkedField]
     public EntityUid? Body;
 }
index 4dbc543fc8e5ad6b6eef9841933aa82e8d21561a..0d8d2c8a268139a515ba65e297a08f9e6b7b5836 100644 (file)
@@ -1,7 +1,7 @@
-namespace Content.Shared.Body.Part;
+namespace Content.Shared.Body.Part;
 
 [ByRefEvent]
-public readonly record struct BodyPartAddedEvent(string Slot, BodyPartComponent Part);
+public readonly record struct BodyPartAddedEvent(string Slot, Entity<BodyPartComponent> Part);
 
 [ByRefEvent]
-public readonly record struct BodyPartRemovedEvent(string Slot, BodyPartComponent Part);
+public readonly record struct BodyPartRemovedEvent(string Slot, Entity<BodyPartComponent> Part);
index bc7cf63124c30689e7aaf6cbf375d45b3ae30225..1a35afdbe00385b944ec00bd55f12c4b8affa0ec 100644 (file)
@@ -9,7 +9,6 @@ using Content.Shared.Gibbing.Components;
 using Content.Shared.Gibbing.Events;
 using Content.Shared.Gibbing.Systems;
 using Content.Shared.Inventory;
-using Content.Shared.Inventory.Events;
 using Robust.Shared.Audio;
 using Robust.Shared.Audio.Systems;
 using Robust.Shared.Containers;
@@ -30,8 +29,10 @@ public partial class SharedBodySystem
     [Dependency] private readonly InventorySystem _inventory = default!;
     [Dependency] private readonly GibbingSystem _gibbingSystem = default!;
     [Dependency] private readonly SharedAudioSystem _audioSystem = default!;
+
     private const float GibletLaunchImpulse = 8;
     private const float GibletLaunchImpulseVariance = 3;
+
     private void InitializeBody()
     {
         // Body here to handle root body parts.
@@ -43,7 +44,7 @@ public partial class SharedBodySystem
         SubscribeLocalEvent<BodyComponent, CanDragEvent>(OnBodyCanDrag);
     }
 
-    private void OnBodyInserted(EntityUid uid, BodyComponent component, EntInsertedIntoContainerMessage args)
+    private void OnBodyInserted(Entity<BodyComponent> ent, ref EntInsertedIntoContainerMessage args)
     {
         // Root body part?
         var slotId = args.Container.ID;
@@ -51,21 +52,21 @@ public partial class SharedBodySystem
         if (slotId != BodyRootContainerId)
             return;
 
-        var entity = args.Entity;
+        var insertedUid = args.Entity;
 
-        if (TryComp(entity, out BodyPartComponent? childPart))
+        if (TryComp(insertedUid, out BodyPartComponent? part))
         {
-            AddPart(uid, entity, slotId, childPart);
-            RecursiveBodyUpdate(entity, uid, childPart);
+            AddPart((ent, ent), (insertedUid, part), slotId);
+            RecursiveBodyUpdate((insertedUid, part), ent);
         }
 
-        if (TryComp(entity, out OrganComponent? organ))
+        if (TryComp(insertedUid, out OrganComponent? organ))
         {
-            AddOrgan(entity, uid, uid, organ);
+            AddOrgan((insertedUid, organ), ent, ent);
         }
     }
 
-    private void OnBodyRemoved(EntityUid uid, BodyComponent component, EntRemovedFromContainerMessage args)
+    private void OnBodyRemoved(Entity<BodyComponent> ent, ref EntRemovedFromContainerMessage args)
     {
         // Root body part?
         var slotId = args.Container.ID;
@@ -73,55 +74,55 @@ public partial class SharedBodySystem
         if (slotId != BodyRootContainerId)
             return;
 
-        var entity = args.Entity;
-        DebugTools.Assert(!TryComp(entity, out BodyPartComponent? b) || b.Body == uid);
-        DebugTools.Assert(!TryComp(entity, out OrganComponent? o) || o.Body == uid);
+        var removedUid = args.Entity;
+        DebugTools.Assert(!TryComp(removedUid, out BodyPartComponent? b) || b.Body == ent);
+        DebugTools.Assert(!TryComp(removedUid, out OrganComponent? o) || o.Body == ent);
 
-        if (TryComp(entity, out BodyPartComponent? childPart))
+        if (TryComp(removedUid, out BodyPartComponent? part))
         {
-            RemovePart(uid, entity, slotId, childPart);
-            RecursiveBodyUpdate(entity, null, childPart);
+            RemovePart((ent, ent), (removedUid, part), slotId);
+            RecursiveBodyUpdate((removedUid, part), null);
         }
 
-        if (TryComp(entity, out OrganComponent? organ))
-            RemoveOrgan(entity, uid, organ);
+        if (TryComp(removedUid, out OrganComponent? organ))
+            RemoveOrgan((removedUid, organ), ent);
     }
 
-    private void OnBodyInit(EntityUid bodyId, BodyComponent body, ComponentInit args)
+    private void OnBodyInit(Entity<BodyComponent> ent, ref ComponentInit args)
     {
         // Setup the initial container.
-        body.RootContainer = Containers.EnsureContainer<ContainerSlot>(bodyId, BodyRootContainerId);
+        ent.Comp.RootContainer = Containers.EnsureContainer<ContainerSlot>(ent, BodyRootContainerId);
     }
 
-    private void OnBodyMapInit(EntityUid bodyId, BodyComponent body, MapInitEvent args)
+    private void OnBodyMapInit(Entity<BodyComponent> ent, ref MapInitEvent args)
     {
-        if (body.Prototype == null)
+        if (ent.Comp.Prototype is null)
             return;
 
         // One-time setup
         // Obviously can't run in Init to avoid double-spawns on save / load.
-        var prototype = Prototypes.Index(body.Prototype.Value);
-        MapInitBody(bodyId, prototype);
+        var prototype = Prototypes.Index(ent.Comp.Prototype.Value);
+        MapInitBody(ent, prototype);
     }
 
     private void MapInitBody(EntityUid bodyEntity, BodyPrototype prototype)
     {
         var protoRoot = prototype.Slots[prototype.Root];
-        if (protoRoot.Part == null)
+        if (protoRoot.Part is null)
             return;
 
         // This should already handle adding the entity to the root.
-        var rootPartEntity = SpawnInContainerOrDrop(protoRoot.Part, bodyEntity, BodyRootContainerId);
-        var rootPart = Comp<BodyPartComponent>(rootPartEntity);
+        var rootPartUid = SpawnInContainerOrDrop(protoRoot.Part, bodyEntity, BodyRootContainerId);
+        var rootPart = Comp<BodyPartComponent>(rootPartUid);
         rootPart.Body = bodyEntity;
-        Dirty(rootPartEntity, rootPart);
+        Dirty(rootPartUid, rootPart);
 
         // Setup the rest of the body entities.
-        SetupOrgans(rootPartEntity, rootPart, protoRoot.Organs);
-        MapInitParts(rootPartEntity, prototype);
+        SetupOrgans((rootPartUid, rootPart), protoRoot.Organs);
+        MapInitParts(rootPartUid, prototype);
     }
 
-    private void OnBodyCanDrag(EntityUid uid, BodyComponent component, ref CanDragEvent args)
+    private void OnBodyCanDrag(Entity<BodyComponent> ent, ref CanDragEvent args)
     {
         args.Handled = true;
     }
@@ -169,7 +170,7 @@ public partial class SharedBodySystem
                 var partSlot = CreatePartSlot(parentEntity, connection, childPartComponent.PartType, parentPartComponent);
                 var cont = Containers.GetContainer(parentEntity, GetPartSlotContainerId(connection));
 
-                if (partSlot == null || !Containers.Insert(childPart, cont))
+                if (partSlot is null || !Containers.Insert(childPart, cont))
                 {
                     Log.Error($"Could not create slot for connection {connection} in body {prototype.ID}");
                     QueueDel(childPart);
@@ -177,7 +178,7 @@ public partial class SharedBodySystem
                 }
 
                 // Add organs
-                SetupOrgans(childPart, childPartComponent, connectionSlot.Organs);
+                SetupOrgans((childPart, childPartComponent), connectionSlot.Organs);
 
                 // Enqueue it so we can also get its neighbors.
                 frontier.Enqueue(connection);
@@ -185,16 +186,16 @@ public partial class SharedBodySystem
         }
     }
 
-    private void SetupOrgans(EntityUid partId, BodyPartComponent partComponent, Dictionary<string, string> organs)
+    private void SetupOrgans(Entity<BodyPartComponent> ent, Dictionary<string, string> organs)
     {
         foreach (var (organSlotId, organProto) in organs)
         {
-            var slot = CreateOrganSlot(organSlotId, partId, partComponent);
-            SpawnInContainerOrDrop(organProto, partId, GetOrganContainerId(organSlotId));
+            var slot = CreateOrganSlot((ent, ent), organSlotId);
+            SpawnInContainerOrDrop(organProto, ent, GetOrganContainerId(organSlotId));
 
-            if (slot == null)
+            if (slot is null)
             {
-                Log.Error($"Could not create organ for slot {organSlotId} in {ToPrettyString(partId)}");
+                Log.Error($"Could not create organ for slot {organSlotId} in {ToPrettyString(ent)}");
             }
         }
     }
@@ -202,12 +203,14 @@ public partial class SharedBodySystem
     /// <summary>
     /// Gets all body containers on this entity including the root one.
     /// </summary>
-    public IEnumerable<BaseContainer> GetBodyContainers(EntityUid id, BodyComponent? body = null,
+    public IEnumerable<BaseContainer> GetBodyContainers(
+        EntityUid id,
+        BodyComponent? body = null,
         BodyPartComponent? rootPart = null)
     {
-        if (!Resolve(id, ref body, false) ||
-            body.RootContainer.ContainedEntity == null ||
-            !Resolve(body.RootContainer.ContainedEntity.Value, ref rootPart))
+        if (!Resolve(id, ref body, logMissing: false)
+            || body.RootContainer.ContainedEntity is null
+            || !Resolve(body.RootContainer.ContainedEntity.Value, ref rootPart))
         {
             yield break;
         }
@@ -223,13 +226,15 @@ public partial class SharedBodySystem
     /// <summary>
     /// Gets all child body parts of this entity, including the root entity.
     /// </summary>
-    public IEnumerable<(EntityUid Id, BodyPartComponent Component)> GetBodyChildren(EntityUid? id, BodyComponent? body = null,
+    public IEnumerable<(EntityUid Id, BodyPartComponent Component)> GetBodyChildren(
+        EntityUid? id,
+        BodyComponent? body = null,
         BodyPartComponent? rootPart = null)
     {
-        if (id == null ||
-            !Resolve(id.Value, ref body, false) ||
-            body.RootContainer.ContainedEntity == null ||
-            !Resolve(body.RootContainer.ContainedEntity.Value, ref rootPart))
+        if (id is null
+            || !Resolve(id.Value, ref body, logMissing: false)
+            || body.RootContainer.ContainedEntity is null
+            || !Resolve(body.RootContainer.ContainedEntity.Value, ref rootPart))
         {
             yield break;
         }
@@ -240,9 +245,11 @@ public partial class SharedBodySystem
         }
     }
 
-    public IEnumerable<(EntityUid Id, OrganComponent Component)> GetBodyOrgans(EntityUid? bodyId, BodyComponent? body = null)
+    public IEnumerable<(EntityUid Id, OrganComponent Component)> GetBodyOrgans(
+        EntityUid? bodyId,
+        BodyComponent? body = null)
     {
-        if (bodyId == null || !Resolve(bodyId.Value, ref body, false))
+        if (bodyId is null || !Resolve(bodyId.Value, ref body, logMissing: false))
             yield break;
 
         foreach (var part in GetBodyChildren(bodyId, body))
@@ -260,10 +267,15 @@ public partial class SharedBodySystem
     /// <param name="bodyId"></param>
     /// <param name="body"></param>
     /// <returns></returns>
-    public IEnumerable<BodyPartSlot> GetBodyAllSlots(EntityUid bodyId, BodyComponent? body = null)
+    public IEnumerable<BodyPartSlot> GetBodyAllSlots(
+        EntityUid bodyId,
+        BodyComponent? body = null)
     {
-        if (!Resolve(bodyId, ref body, false) || body.RootContainer.ContainedEntity == null)
+        if (!Resolve(bodyId, ref body, logMissing: false)
+            || body.RootContainer.ContainedEntity is null)
+        {
             yield break;
+        }
 
         foreach (var slot in GetAllBodyPartSlots(body.RootContainer.ContainedEntity.Value))
         {
@@ -279,12 +291,11 @@ public partial class SharedBodySystem
         Vector2? splatDirection = null,
         float splatModifier = 1,
         Angle splatCone = default,
-        SoundSpecifier? gibSoundOverride = null
-        )
+        SoundSpecifier? gibSoundOverride = null)
     {
         var gibs = new HashSet<EntityUid>();
 
-        if (!Resolve(bodyId, ref body, false))
+        if (!Resolve(bodyId, ref body, logMissing: false))
             return gibs;
 
         var root = GetRootPartOrNull(bodyId, body);
@@ -311,7 +322,7 @@ public partial class SharedBodySystem
                     launchImpulseVariance:GibletLaunchImpulseVariance, launchCone: splatCone);
             }
         }
-        if(TryComp<InventoryComponent>(bodyId, out var inventory))
+        if (TryComp<InventoryComponent>(bodyId, out var inventory))
         {
             foreach (var item in _inventory.GetHandOrInventoryEntities(bodyId))
             {
index fa113907058e2d0e256f1969072f3f4295c1c03e..efabebfc858bfe5896bcede8156a2d5fc98009eb 100644 (file)
@@ -1,4 +1,4 @@
-using System.Diagnostics.CodeAnalysis;
+using System.Diagnostics.CodeAnalysis;
 using Content.Shared.Body.Components;
 using Content.Shared.Body.Events;
 using Content.Shared.Body.Organ;
@@ -9,41 +9,50 @@ namespace Content.Shared.Body.Systems;
 
 public partial class SharedBodySystem
 {
-    private void AddOrgan(EntityUid uid, EntityUid bodyUid, EntityUid parentPartUid, OrganComponent component)
+    private void AddOrgan(
+        Entity<OrganComponent> organEnt,
+        EntityUid bodyUid,
+        EntityUid parentPartUid)
     {
-        component.Body = bodyUid;
-        RaiseLocalEvent(uid, new AddedToPartEvent(parentPartUid));
+        organEnt.Comp.Body = bodyUid;
+        var addedEv = new OrganAddedEvent(parentPartUid);
+        RaiseLocalEvent(organEnt, ref addedEv);
 
-        if (component.Body != null)
-            RaiseLocalEvent(uid, new AddedToPartInBodyEvent(component.Body.Value, parentPartUid));
+        if (organEnt.Comp.Body is not null)
+        {
+            var addedInBodyEv = new OrganAddedToBodyEvent(bodyUid, parentPartUid);
+            RaiseLocalEvent(organEnt, ref addedInBodyEv);
+        }
 
-        Dirty(uid, component);
+        Dirty(organEnt, organEnt.Comp);
     }
 
-    private void RemoveOrgan(EntityUid uid, EntityUid parentPartUid, OrganComponent component)
+    private void RemoveOrgan(Entity<OrganComponent> organEnt, EntityUid parentPartUid)
     {
-        RaiseLocalEvent(uid, new RemovedFromPartEvent(parentPartUid));
+        var removedEv = new OrganRemovedEvent(parentPartUid);
+        RaiseLocalEvent(organEnt, ref removedEv);
 
-        if (component.Body != null)
+        if (organEnt.Comp.Body is { Valid: true } bodyUid)
         {
-            RaiseLocalEvent(uid, new RemovedFromPartInBodyEvent(component.Body.Value, parentPartUid));
+            var removedInBodyEv = new OrganRemovedFromBodyEvent(bodyUid, parentPartUid);
+            RaiseLocalEvent(organEnt, ref removedInBodyEv);
         }
 
-        component.Body = null;
-        Dirty(uid, component);
+        organEnt.Comp.Body = null;
+        Dirty(organEnt, organEnt.Comp);
     }
 
     /// <summary>
     /// Creates the specified organ slot on the parent entity.
     /// </summary>
-    private OrganSlot? CreateOrganSlot(string slotId, EntityUid parent, BodyPartComponent? part = null)
+    private OrganSlot? CreateOrganSlot(Entity<BodyPartComponent?> parentEnt, string slotId)
     {
-        if (!Resolve(parent, ref part, false))
+        if (!Resolve(parentEnt, ref parentEnt.Comp, logMissing: false))
             return null;
 
-        Containers.EnsureContainer<ContainerSlot>(parent, GetOrganContainerId(slotId));
+        Containers.EnsureContainer<ContainerSlot>(parentEnt, GetOrganContainerId(slotId));
         var slot = new OrganSlot(slotId);
-        part.Organs.Add(slotId, slot);
+        parentEnt.Comp.Organs.Add(slotId, slot);
         return slot;
     }
 
@@ -58,20 +67,23 @@ public partial class SharedBodySystem
     {
         slot = null;
 
-        if (parent == null || !Resolve(parent.Value, ref part, false))
+        if (parent is null || !Resolve(parent.Value, ref part, logMissing: false))
         {
             return false;
         }
 
         Containers.EnsureContainer<ContainerSlot>(parent.Value, GetOrganContainerId(slotId));
         slot = new OrganSlot(slotId);
-        return part.Organs.TryAdd(slotId,slot.Value);
+        return part.Organs.TryAdd(slotId, slot.Value);
     }
 
     /// <summary>
     /// Returns whether the slotId exists on the partId.
     /// </summary>
-    public bool CanInsertOrgan(EntityUid partId, string slotId, BodyPartComponent? part = null)
+    public bool CanInsertOrgan(
+        EntityUid partId,
+        string slotId,
+        BodyPartComponent? part = null)
     {
         return Resolve(partId, ref part) && part.Organs.ContainsKey(slotId);
     }
@@ -79,26 +91,32 @@ public partial class SharedBodySystem
     /// <summary>
     /// Returns whether the specified organ slot exists on the partId.
     /// </summary>
-    public bool CanInsertOrgan(EntityUid partId, OrganSlot slot, BodyPartComponent? part = null)
+    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)
+    public bool InsertOrgan(
+        EntityUid partId,
+        EntityUid organId,
+        string slotId,
+        BodyPartComponent? part = null,
+        OrganComponent? organ = null)
     {
-        if (!Resolve(organId, ref organ, false) ||
-            !Resolve(partId, ref part, false) ||
-            !CanInsertOrgan(partId, slotId, part))
+        if (!Resolve(organId, ref organ, logMissing: false)
+            || !Resolve(partId, ref part, logMissing: false)
+            || !CanInsertOrgan(partId, slotId, part))
         {
             return false;
         }
 
         var containerId = GetOrganContainerId(slotId);
 
-        if (!Containers.TryGetContainer(partId, containerId, out var container))
-            return false;
-
-        return Containers.Insert(organId, container);
+        return Containers.TryGetContainer(partId, containerId, out var container)
+            && Containers.Insert(organId, container);
     }
 
     /// <summary>
@@ -111,10 +129,8 @@ public partial class SharedBodySystem
 
         var parent = container.Owner;
 
-        if (!HasComp<BodyPartComponent>(parent))
-            return false;
-
-        return Containers.Remove(organId, container);
+        return HasComp<BodyPartComponent>(parent)
+            && Containers.Remove(organId, container);
     }
 
     /// <summary>
@@ -126,8 +142,8 @@ public partial class SharedBodySystem
         BodyPartComponent? part = null,
         OrganComponent? organ = null)
     {
-        if (!Resolve(partId, ref part, false) ||
-            !Resolve(organId, ref organ, false))
+        if (!Resolve(partId, ref part, logMissing: false)
+            || !Resolve(organId, ref organ, logMissing: false))
         {
             return false;
         }
index e07aac06226e99278aaf73a89231df9d998f2e82..ee79faa0b8e7ab31e349f73c8f764c5a288f4efc 100644 (file)
@@ -1,4 +1,4 @@
-using System.Diagnostics.CodeAnalysis;
+using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using Content.Shared.Body.Components;
 using Content.Shared.Body.Events;
@@ -23,52 +23,52 @@ public partial class SharedBodySystem
         SubscribeLocalEvent<BodyPartComponent, EntRemovedFromContainerMessage>(OnBodyPartRemoved);
     }
 
-    private void OnBodyPartInserted(EntityUid uid, BodyPartComponent component, EntInsertedIntoContainerMessage args)
+    private void OnBodyPartInserted(Entity<BodyPartComponent> ent, ref EntInsertedIntoContainerMessage args)
     {
         // Body part inserted into another body part.
-        var entity = args.Entity;
+        var insertedUid = args.Entity;
         var slotId = args.Container.ID;
 
-        if (component.Body == null)
+        if (ent.Comp.Body is null)
             return;
 
-        if (TryComp(entity, out BodyPartComponent? childPart))
+        if (TryComp(insertedUid, out BodyPartComponent? part))
         {
-            AddPart(component.Body.Value, entity, slotId, childPart);
-            RecursiveBodyUpdate(entity, component.Body.Value, childPart);
+            AddPart(ent.Comp.Body.Value, (insertedUid, part), slotId);
+            RecursiveBodyUpdate((insertedUid, part), ent.Comp.Body.Value);
         }
 
-        if (TryComp(entity, out OrganComponent? organ))
-            AddOrgan(entity, component.Body.Value, uid, organ);
+        if (TryComp(insertedUid, out OrganComponent? organ))
+            AddOrgan((insertedUid, organ), ent.Comp.Body.Value, ent);
     }
 
-    private void OnBodyPartRemoved(EntityUid uid, BodyPartComponent component, EntRemovedFromContainerMessage args)
+    private void OnBodyPartRemoved(Entity<BodyPartComponent> ent, ref EntRemovedFromContainerMessage args)
     {
         // Body part removed from another body part.
-        var entity = args.Entity;
+        var removedUid = args.Entity;
         var slotId = args.Container.ID;
 
-        DebugTools.Assert(!TryComp(entity, out BodyPartComponent? b) || b.Body == component.Body);
-        DebugTools.Assert(!TryComp(entity, out OrganComponent? o) || o.Body == component.Body);
+        DebugTools.Assert(!TryComp(removedUid, out BodyPartComponent? b) || b.Body == ent.Comp.Body);
+        DebugTools.Assert(!TryComp(removedUid, out OrganComponent? o) || o.Body == ent.Comp.Body);
 
-        if (TryComp(entity, out BodyPartComponent? childPart) && childPart.Body != null)
+        if (TryComp(removedUid, out BodyPartComponent? part) && part.Body is not null)
         {
-            RemovePart(childPart.Body.Value, entity, slotId, childPart);
-            RecursiveBodyUpdate(entity, null, childPart);
+            RemovePart(part.Body.Value, (removedUid, part), slotId);
+            RecursiveBodyUpdate((removedUid, part), null);
         }
 
-        if (TryComp(entity, out OrganComponent? organ))
-            RemoveOrgan(entity, uid, organ);
+        if (TryComp(removedUid, out OrganComponent? organ))
+            RemoveOrgan((removedUid, organ), ent);
     }
 
-    private void RecursiveBodyUpdate(EntityUid uid, EntityUid? bodyUid, BodyPartComponent component)
+    private void RecursiveBodyUpdate(Entity<BodyPartComponent> ent, EntityUid? bodyUid)
     {
-        component.Body = bodyUid;
-        Dirty(uid, component);
+        ent.Comp.Body = bodyUid;
+        Dirty(ent, ent.Comp);
 
-        foreach (var slotId in component.Organs.Keys)
+        foreach (var slotId in ent.Comp.Organs.Keys)
         {
-            if (!Containers.TryGetContainer(uid, GetOrganContainerId(slotId), out var container))
+            if (!Containers.TryGetContainer(ent, GetOrganContainerId(slotId), out var container))
                 continue;
 
             foreach (var organ in container.ContainedEntities)
@@ -78,105 +78,108 @@ public partial class SharedBodySystem
 
                 Dirty(organ, organComp);
 
-                if (organComp.Body != null)
-                    RaiseLocalEvent(organ, new RemovedFromPartInBodyEvent(organComp.Body.Value, uid));
+                if (organComp.Body is { Valid: true } oldBodyUid)
+                {
+                    var removedEv = new OrganRemovedFromBodyEvent(oldBodyUid, ent);
+                    RaiseLocalEvent(organ, ref removedEv);
+                }
 
                 organComp.Body = bodyUid;
-                if (bodyUid != null)
-                    RaiseLocalEvent(organ, new AddedToPartInBodyEvent(bodyUid.Value, uid));
+                if (bodyUid is not null)
+                {
+                    var addedEv = new OrganAddedToBodyEvent(bodyUid.Value, ent);
+                    RaiseLocalEvent(organ, ref addedEv);
+                }
             }
         }
 
-        foreach (var slotId in component.Children.Keys)
+        foreach (var slotId in ent.Comp.Children.Keys)
         {
-            if (!Containers.TryGetContainer(uid, GetPartSlotContainerId(slotId), out var container))
+            if (!Containers.TryGetContainer(ent, GetPartSlotContainerId(slotId), out var container))
                 continue;
 
-            foreach (var containedEnt in container.ContainedEntities)
+            foreach (var containedUid in container.ContainedEntities)
             {
-                if (TryComp(containedEnt, out BodyPartComponent? childPart))
-                    RecursiveBodyUpdate(containedEnt, bodyUid, childPart);
+                if (TryComp(containedUid, out BodyPartComponent? childPart))
+                    RecursiveBodyUpdate((containedUid, childPart), bodyUid);
             }
         }
     }
 
     protected virtual void AddPart(
-        EntityUid bodyUid,
-        EntityUid partUid,
-        string slotId,
-        BodyPartComponent component,
-        BodyComponent? bodyComp = null)
+        Entity<BodyComponent?> bodyEnt,
+        Entity<BodyPartComponent> partEnt,
+        string slotId)
     {
-        DebugTools.AssertOwner(partUid, component);
-        Dirty(partUid, component);
-        component.Body = bodyUid;
+        Dirty(partEnt, partEnt.Comp);
+        partEnt.Comp.Body = bodyEnt;
 
-        var ev = new BodyPartAddedEvent(slotId, component);
-        RaiseLocalEvent(bodyUid, ref ev);
+        var ev = new BodyPartAddedEvent(slotId, partEnt);
+        RaiseLocalEvent(bodyEnt, ref ev);
 
-        AddLeg(partUid, bodyUid, component, bodyComp);
+        AddLeg(partEnt, bodyEnt);
     }
 
     protected virtual void RemovePart(
-        EntityUid bodyUid,
-        EntityUid partUid,
-        string slotId,
-        BodyPartComponent component,
-        BodyComponent? bodyComp = null)
+        Entity<BodyComponent?> bodyEnt,
+        Entity<BodyPartComponent> partEnt,
+        string slotId)
     {
-        DebugTools.AssertOwner(partUid, component);
-        Resolve(bodyUid, ref bodyComp, false);
-        Dirty(partUid, component);
-        component.Body = null;
+        Resolve(bodyEnt, ref bodyEnt.Comp, logMissing: false);
+        Dirty(partEnt, partEnt.Comp);
+        partEnt.Comp.Body = null;
 
-        var ev = new BodyPartRemovedEvent(slotId, component);
-        RaiseLocalEvent(bodyUid, ref ev);
+        var ev = new BodyPartRemovedEvent(slotId, partEnt);
+        RaiseLocalEvent(bodyEnt, ref ev);
 
-        RemoveLeg(partUid, bodyUid, component);
-        PartRemoveDamage(bodyUid, component, bodyComp);
+        RemoveLeg(partEnt, bodyEnt);
+        PartRemoveDamage(bodyEnt, partEnt);
     }
 
-    private void AddLeg(EntityUid uid, EntityUid bodyUid, BodyPartComponent component, BodyComponent? bodyComp = null)
+    private void AddLeg(Entity<BodyPartComponent> legEnt, Entity<BodyComponent?> bodyEnt)
     {
-        if (!Resolve(bodyUid, ref bodyComp, false))
+        if (!Resolve(bodyEnt, ref bodyEnt.Comp, logMissing: false))
             return;
 
-        if (component.PartType == BodyPartType.Leg)
+        if (legEnt.Comp.PartType == BodyPartType.Leg)
         {
-            bodyComp.LegEntities.Add(uid);
-            UpdateMovementSpeed(bodyUid);
-            Dirty(bodyUid, bodyComp);
+            bodyEnt.Comp.LegEntities.Add(legEnt);
+            UpdateMovementSpeed(bodyEnt);
+            Dirty(bodyEnt, bodyEnt.Comp);
         }
     }
 
-    private void RemoveLeg(EntityUid uid, EntityUid bodyUid, BodyPartComponent component, BodyComponent? bodyComp = null)
+    private void RemoveLeg(Entity<BodyPartComponent> legEnt, Entity<BodyComponent?> bodyEnt)
     {
-        if (!Resolve(bodyUid, ref bodyComp, false))
+        if (!Resolve(bodyEnt, ref bodyEnt.Comp, logMissing: false))
             return;
 
-        if (component.PartType == BodyPartType.Leg)
+        if (legEnt.Comp.PartType == BodyPartType.Leg)
         {
-            bodyComp.LegEntities.Remove(uid);
-            UpdateMovementSpeed(bodyUid);
-            Dirty(bodyUid, bodyComp);
+            bodyEnt.Comp.LegEntities.Remove(legEnt);
+            UpdateMovementSpeed(bodyEnt);
+            Dirty(bodyEnt, bodyEnt.Comp);
 
-            if (!bodyComp.LegEntities.Any())
+            if (!bodyEnt.Comp.LegEntities.Any())
             {
-                Standing.Down(bodyUid);
+                Standing.Down(bodyEnt);
             }
         }
     }
 
-    private void PartRemoveDamage(EntityUid parent, BodyPartComponent component, BodyComponent? bodyComp = null)
+    private void PartRemoveDamage(Entity<BodyComponent?> bodyEnt, Entity<BodyPartComponent> partEnt)
     {
-        if (!Resolve(parent, ref bodyComp, false))
+        if (!Resolve(bodyEnt, ref bodyEnt.Comp, logMissing: false))
             return;
 
-        if (!_timing.ApplyingState && component.IsVital && !GetBodyChildrenOfType(parent, component.PartType, bodyComp).Any())
+        if (!_timing.ApplyingState
+            && partEnt.Comp.IsVital
+            && !GetBodyChildrenOfType(bodyEnt, partEnt.Comp.PartType, bodyEnt.Comp).Any()
+        )
         {
             // TODO BODY SYSTEM KILL : remove this when wounding and required parts are implemented properly
             var damage = new DamageSpecifier(Prototypes.Index<DamageTypePrototype>("Bloodloss"), 300);
-            Damageable.TryChangeDamage(parent, damage);
+            Damageable.TryChangeDamage(bodyEnt, damage);
         }
     }
 
@@ -212,7 +215,8 @@ public partial class SharedBodySystem
 
         var parent = container.Owner;
 
-        if (!TryComp<BodyPartComponent>(parent, out var parentBody) || !parentBody.Children.ContainsKey(slotId))
+        if (!TryComp<BodyPartComponent>(parent, out var parentBody)
+            || !parentBody.Children.ContainsKey(slotId))
             return null;
 
         return (parent, slotId);
@@ -252,7 +256,7 @@ public partial class SharedBodySystem
         BodyPartType partType,
         BodyPartComponent? part = null)
     {
-        if (!Resolve(partUid, ref part, false))
+        if (!Resolve(partUid, ref part, logMissing: false))
             return null;
 
         Containers.EnsureContainer<ContainerSlot>(partUid, GetPartSlotContainerId(slotId));
@@ -275,8 +279,8 @@ public partial class SharedBodySystem
     {
         slot = null;
 
-        if (partId == null ||
-            !Resolve(partId.Value, ref part, false))
+        if (partId is null
+            || !Resolve(partId.Value, ref part, logMissing: false))
         {
             return false;
         }
@@ -310,24 +314,31 @@ public partial class SharedBodySystem
     /// <summary>
     /// Returns true if the partId is the root body container for the specified bodyId.
     /// </summary>
-    public bool IsPartRoot(EntityUid bodyId, EntityUid partId, BodyComponent? body = null, BodyPartComponent? part = null)
+    public bool IsPartRoot(
+        EntityUid bodyId,
+        EntityUid partId,
+        BodyComponent? body = null,
+        BodyPartComponent? part = null)
     {
-        if (!Resolve(partId, ref part)|| !Resolve(bodyId, ref body))
-            return false;
-
-        return Containers.TryGetContainingContainer(bodyId, partId, out var container) && container.ID == BodyRootContainerId;
+        return Resolve(partId, ref part)
+            && Resolve(bodyId, ref body)
+            && Containers.TryGetContainingContainer(bodyId, partId, out var container)
+            && container.ID == BodyRootContainerId;
     }
 
     /// <summary>
     /// Returns true if we can attach the partId to the bodyId as the root entity.
     /// </summary>
-    public bool CanAttachToRoot(EntityUid bodyId, EntityUid partId, BodyComponent? body = null,
+    public bool CanAttachToRoot(
+        EntityUid bodyId,
+        EntityUid partId,
+        BodyComponent? body = null,
         BodyPartComponent? part = null)
     {
-        return Resolve(bodyId, ref body) &&
-               Resolve(partId, ref part) &&
-               body.RootContainer.ContainedEntity == null &&
-               bodyId != part.Body;
+        return Resolve(bodyId, ref body)
+            && Resolve(partId, ref part)
+            && body.RootContainer.ContainedEntity is null
+            && bodyId != part.Body;
     }
 
     /// <summary>
@@ -335,8 +346,11 @@ public partial class SharedBodySystem
     /// </summary>
     public (EntityUid Entity, BodyPartComponent BodyPart)? GetRootPartOrNull(EntityUid bodyId, BodyComponent? body = null)
     {
-        if (!Resolve(bodyId, ref body) || body.RootContainer.ContainedEntity == null)
+        if (!Resolve(bodyId, ref body)
+            || body.RootContainer.ContainedEntity is null)
+        {
             return null;
+        }
 
         return (body.RootContainer.ContainedEntity.Value,
             Comp<BodyPartComponent>(body.RootContainer.ContainedEntity.Value));
@@ -352,13 +366,9 @@ public partial class SharedBodySystem
         BodyPartComponent? parentPart = null,
         BodyPartComponent? part = null)
     {
-        if (!Resolve(partId, ref part, false) ||
-            !Resolve(parentId, ref parentPart, false))
-        {
-            return false;
-        }
-
-        return CanAttachPart(parentId, slot.Id, partId, parentPart, part);
+        return Resolve(partId, ref part, logMissing: false)
+            && Resolve(parentId, ref parentPart, logMissing: false)
+            && CanAttachPart(parentId, slot.Id, partId, parentPart, part);
     }
 
     /// <summary>
@@ -371,16 +381,12 @@ public partial class SharedBodySystem
         BodyPartComponent? parentPart = null,
         BodyPartComponent? part = null)
     {
-        if (!Resolve(partId, ref part, false) ||
-            !Resolve(parentId, ref parentPart, false) ||
-            !parentPart.Children.TryGetValue(slotId, out var parentSlotData))
-        {
-            return false;
-        }
-
-        return part.PartType == parentSlotData.Type &&
-               Containers.TryGetContainer(parentId, GetPartSlotContainerId(slotId), out var container) &&
-               Containers.CanInsert(partId, container);
+        return Resolve(partId, ref part, logMissing: false)
+            && Resolve(parentId, ref parentPart, logMissing: false)
+            && parentPart.Children.TryGetValue(slotId, out var parentSlotData)
+            && part.PartType == parentSlotData.Type
+            && Containers.TryGetContainer(parentId, GetPartSlotContainerId(slotId), out var container)
+            && Containers.CanInsert(partId, container);
     }
 
     public bool AttachPartToRoot(
@@ -389,14 +395,10 @@ public partial class SharedBodySystem
         BodyComponent? body = null,
         BodyPartComponent? part = null)
     {
-        if (!Resolve(bodyId, ref body) ||
-            !Resolve(partId, ref part) ||
-            !CanAttachToRoot(bodyId, partId, body, part))
-        {
-            return false;
-        }
-
-        return Containers.Insert(partId, body.RootContainer);
+        return Resolve(bodyId, ref body)
+            && Resolve(partId, ref part)
+            && CanAttachToRoot(bodyId, partId, body, part)
+            && Containers.Insert(partId, body.RootContainer);
     }
 
     #endregion
@@ -406,20 +408,16 @@ public partial class SharedBodySystem
     /// <summary>
     /// Attaches a body part to the specified body part parent.
     /// </summary>
-     public bool AttachPart(
-         EntityUid parentPartId,
-         string slotId,
-         EntityUid partId,
-         BodyPartComponent? parentPart = null,
-         BodyPartComponent? part = null)
-    {
-        if (!Resolve(parentPartId, ref parentPart, false) ||
-            !parentPart.Children.TryGetValue(slotId, out var slot))
-        {
-            return false;
-        }
-
-        return AttachPart(parentPartId, slot, partId, parentPart, part);
+    public bool AttachPart(
+        EntityUid parentPartId,
+        string slotId,
+        EntityUid partId,
+        BodyPartComponent? parentPart = null,
+        BodyPartComponent? part = null)
+    {
+        return Resolve(parentPartId, ref parentPart, logMissing: false)
+            && parentPart.Children.TryGetValue(slotId, out var slot)
+            && AttachPart(parentPartId, slot, partId, parentPart, part);
     }
 
     /// <summary>
@@ -432,10 +430,10 @@ public partial class SharedBodySystem
         BodyPartComponent? parentPart = null,
         BodyPartComponent? part = null)
     {
-        if (!Resolve(parentPartId, ref parentPart, false) ||
-            !Resolve(partId, ref part, false) ||
-            !CanAttachPart(parentPartId, slot.Id, partId, parentPart, part) ||
-            !parentPart.Children.ContainsKey(slot.Id))
+        if (!Resolve(parentPartId, ref parentPart, logMissing: false)
+            || !Resolve(partId, ref part, logMissing: false)
+            || !CanAttachPart(parentPartId, slot.Id, partId, parentPart, part)
+            || !parentPart.Children.ContainsKey(slot.Id))
         {
             return false;
         }
@@ -453,13 +451,16 @@ public partial class SharedBodySystem
 
     #region Misc
 
-    public void UpdateMovementSpeed(EntityUid bodyId, BodyComponent? body = null, MovementSpeedModifierComponent? movement = null)
+    public void UpdateMovementSpeed(
+        EntityUid bodyId,
+        BodyComponent? body = null,
+        MovementSpeedModifierComponent? movement = null)
     {
-        if (!Resolve(bodyId, ref body, ref movement, false))
-            return;
-
-        if (body.RequiredLegs <= 0)
+        if (!Resolve(bodyId, ref body, ref movement, logMissing: false)
+            || body.RequiredLegs <= 0)
+        {
             return;
+        }
 
         var walkSpeed = 0f;
         var sprintSpeed = 0f;
@@ -488,7 +489,7 @@ public partial class SharedBodySystem
     /// </summary>
     public IEnumerable<(EntityUid Id, OrganComponent Component)> GetPartOrgans(EntityUid partId, BodyPartComponent? part = null)
     {
-        if (!Resolve(partId, ref part, false))
+        if (!Resolve(partId, ref part, logMissing: false))
             yield break;
 
         foreach (var slotId in part.Organs.Keys)
@@ -513,7 +514,7 @@ public partial class SharedBodySystem
     /// </summary>
     public IEnumerable<BaseContainer> GetPartContainers(EntityUid id, BodyPartComponent? part = null)
     {
-        if (!Resolve(id, ref part, false) ||
+        if (!Resolve(id, ref part, logMissing: false) ||
             part.Children.Count == 0)
         {
             yield break;
@@ -541,9 +542,11 @@ public partial class SharedBodySystem
     /// <summary>
     /// Returns all body part components for this entity including itself.
     /// </summary>
-    public IEnumerable<(EntityUid Id, BodyPartComponent Component)> GetBodyPartChildren(EntityUid partId, BodyPartComponent? part = null)
+    public IEnumerable<(EntityUid Id, BodyPartComponent Component)> GetBodyPartChildren(
+        EntityUid partId,
+        BodyPartComponent? part = null)
     {
-        if (!Resolve(partId, ref part, false))
+        if (!Resolve(partId, ref part, logMissing: false))
             yield break;
 
         yield return (partId, part);
@@ -571,9 +574,11 @@ public partial class SharedBodySystem
     /// <summary>
     /// Returns all body part slots for this entity.
     /// </summary>
-    public IEnumerable<BodyPartSlot> GetAllBodyPartSlots(EntityUid partId, BodyPartComponent? part = null)
+    public IEnumerable<BodyPartSlot> GetAllBodyPartSlots(
+        EntityUid partId,
+        BodyPartComponent? part = null)
     {
-        if (!Resolve(partId, ref part, false))
+        if (!Resolve(partId, ref part, logMissing: false))
             yield break;
 
         foreach (var (slotId, slot) in part.Children)
@@ -601,7 +606,10 @@ public partial class SharedBodySystem
     /// <summary>
     /// Returns true if the bodyId has any parts of this type.
     /// </summary>
-    public bool BodyHasPartType(EntityUid bodyId, BodyPartType type, BodyComponent? body = null)
+    public bool BodyHasPartType(
+        EntityUid bodyId,
+        BodyPartType type,
+        BodyComponent? body = null)
     {
         return GetBodyChildrenOfType(bodyId, type, body).Any();
     }
@@ -615,8 +623,8 @@ public partial class SharedBodySystem
         BodyPartComponent? parent,
         BodyPartComponent? child)
     {
-        if (!Resolve(parentId, ref parent, false) ||
-            !Resolve(childId, ref child, false))
+        if (!Resolve(parentId, ref parent, logMissing: false)
+            || !Resolve(childId, ref child, logMissing: false))
         {
             return false;
         }
@@ -638,15 +646,11 @@ public partial class SharedBodySystem
         BodyComponent? body = null,
         BodyPartComponent? part = null)
     {
-        if (!Resolve(bodyId, ref body, false) ||
-            body.RootContainer.ContainedEntity == null ||
-            !Resolve(partId, ref part, false) ||
-            !TryComp(body.RootContainer.ContainedEntity, out BodyPartComponent? rootPart))
-        {
-            return false;
-        }
-
-        return PartHasChild(body.RootContainer.ContainedEntity.Value, partId, rootPart, part);
+        return Resolve(bodyId, ref body, logMissing: false)
+            && body.RootContainer.ContainedEntity is not null
+            && Resolve(partId, ref part, logMissing: false)
+            && TryComp(body.RootContainer.ContainedEntity, out BodyPartComponent? rootPart)
+            && PartHasChild(body.RootContainer.ContainedEntity.Value, partId, rootPart, part);
     }
 
     public IEnumerable<(EntityUid Id, BodyPartComponent Component)> GetBodyChildrenOfType(
@@ -721,9 +725,11 @@ public partial class SharedBodySystem
     /// <summary>
     /// Gets the parent body part and all immediate child body parts for the partId.
     /// </summary>
-    public IEnumerable<EntityUid> GetBodyPartAdjacentParts(EntityUid partId, BodyPartComponent? part = null)
+    public IEnumerable<EntityUid> GetBodyPartAdjacentParts(
+        EntityUid partId,
+        BodyPartComponent? part = null)
     {
-        if (!Resolve(partId, ref part, false))
+        if (!Resolve(partId, ref part, logMissing: false))
             yield break;
 
         if (TryGetParentBodyPart(partId, out var parentUid, out _))
@@ -745,7 +751,7 @@ public partial class SharedBodySystem
         BodyPartComponent? part = null)
         where T : IComponent
     {
-        if (!Resolve(partId, ref part, false))
+        if (!Resolve(partId, ref part, logMissing: false))
             yield break;
 
         var query = GetEntityQuery<T>();
@@ -762,7 +768,7 @@ public partial class SharedBodySystem
         BodyPartComponent? part = null)
         where T : IComponent
     {
-        if (!Resolve(partId, ref part, false))
+        if (!Resolve(partId, ref part, logMissing: false))
         {
             comps = null;
             return false;