diff --git a/Content.Client/Body/Components/BodyPartComponent.cs b/Content.Client/Body/Components/BodyPartComponent.cs
index aad192f355..b2927372de 100644
--- a/Content.Client/Body/Components/BodyPartComponent.cs
+++ b/Content.Client/Body/Components/BodyPartComponent.cs
@@ -1,4 +1,5 @@
-using Content.Shared.Body.Part;
+using Content.Shared.Body.Components;
+using Content.Shared.Body.Part;
using Robust.Shared.GameObjects;
namespace Content.Client.Body.Components
diff --git a/Content.Client/Body/Components/MechanismComponent.cs b/Content.Client/Body/Components/MechanismComponent.cs
index d7a1880ec9..2ff51766be 100644
--- a/Content.Client/Body/Components/MechanismComponent.cs
+++ b/Content.Client/Body/Components/MechanismComponent.cs
@@ -1,4 +1,4 @@
-using Content.Shared.Body.Mechanism;
+using Content.Shared.Body.Components;
using Robust.Shared.GameObjects;
namespace Content.Client.Body.Components
diff --git a/Content.Client/Body/UI/BodyScannerBoundUserInterface.cs b/Content.Client/Body/UI/BodyScannerBoundUserInterface.cs
index ba85e6691c..448f070ce3 100644
--- a/Content.Client/Body/UI/BodyScannerBoundUserInterface.cs
+++ b/Content.Client/Body/UI/BodyScannerBoundUserInterface.cs
@@ -1,5 +1,5 @@
using System;
-using Content.Shared.Body.Scanner;
+using Content.Shared.Body.Components;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Shared.GameObjects;
diff --git a/Content.Client/Body/UI/BodyScannerDisplay.cs b/Content.Client/Body/UI/BodyScannerDisplay.cs
index c0b98c1c82..497e00708b 100644
--- a/Content.Client/Body/UI/BodyScannerDisplay.cs
+++ b/Content.Client/Body/UI/BodyScannerDisplay.cs
@@ -1,6 +1,5 @@
using System.Linq;
using Content.Shared.Body.Components;
-using Content.Shared.Body.Mechanism;
using Content.Shared.Body.Part;
using Content.Shared.Damage;
using Robust.Client.UserInterface.Controls;
diff --git a/Content.Client/Commands/HideMechanismsCommand.cs b/Content.Client/Commands/HideMechanismsCommand.cs
index 6ee7eef082..282fedeff5 100644
--- a/Content.Client/Commands/HideMechanismsCommand.cs
+++ b/Content.Client/Commands/HideMechanismsCommand.cs
@@ -1,4 +1,4 @@
-using Content.Shared.Body.Mechanism;
+using Content.Shared.Body.Components;
using Robust.Client.Console;
using Robust.Client.GameObjects;
using Robust.Shared.Console;
diff --git a/Content.Client/Commands/OpenAHelpCommand.cs b/Content.Client/Commands/OpenAHelpCommand.cs
index 2ce05c7db2..dee8b2f4ea 100644
--- a/Content.Client/Commands/OpenAHelpCommand.cs
+++ b/Content.Client/Commands/OpenAHelpCommand.cs
@@ -1,6 +1,5 @@
using System;
-using Content.Client.Administration;
-using Content.Shared.Body.Mechanism;
+ using Content.Client.Administration;
using Robust.Client.Console;
using Robust.Client.GameObjects;
using Robust.Shared.Console;
diff --git a/Content.Client/Commands/ShowMechanismsCommand.cs b/Content.Client/Commands/ShowMechanismsCommand.cs
index 07a7dd5785..b61912a854 100644
--- a/Content.Client/Commands/ShowMechanismsCommand.cs
+++ b/Content.Client/Commands/ShowMechanismsCommand.cs
@@ -1,4 +1,4 @@
-using Content.Shared.Body.Mechanism;
+using Content.Shared.Body.Components;
using Robust.Client.Console;
using Robust.Client.GameObjects;
using Robust.Shared.Console;
diff --git a/Content.Client/Entry/IgnoredComponents.cs b/Content.Client/Entry/IgnoredComponents.cs
index 8b938dbe07..2ec4c14932 100644
--- a/Content.Client/Entry/IgnoredComponents.cs
+++ b/Content.Client/Entry/IgnoredComponents.cs
@@ -73,6 +73,7 @@ namespace Content.Client.Entry
"Bucket",
"CableVis",
"Puddle",
+ "Stomach",
"CanSpill",
"SpeedLoader",
"Hitscan",
diff --git a/Content.IntegrationTests/Tests/Body/LegTest.cs b/Content.IntegrationTests/Tests/Body/LegTest.cs
index e06b2a314d..1c4dd56790 100644
--- a/Content.IntegrationTests/Tests/Body/LegTest.cs
+++ b/Content.IntegrationTests/Tests/Body/LegTest.cs
@@ -1,5 +1,6 @@
using System.Threading.Tasks;
using Content.Server.Body;
+using Content.Server.Body.Components;
using Content.Shared.Body.Components;
using Content.Shared.Body.Part;
using Content.Shared.Rotation;
diff --git a/Content.IntegrationTests/Tests/Body/LungTest.cs b/Content.IntegrationTests/Tests/Body/LungTest.cs
index 90aab55410..f97e8533ee 100644
--- a/Content.IntegrationTests/Tests/Body/LungTest.cs
+++ b/Content.IntegrationTests/Tests/Body/LungTest.cs
@@ -4,8 +4,7 @@ using System.Linq;
using System.Threading.Tasks;
using Content.Server.Atmos;
using Content.Server.Body.Behavior;
-using Content.Server.Body.Circulatory;
-using Content.Server.Body.Respiratory;
+using Content.Server.Body.Components;
using Content.Shared.Atmos;
using Content.Shared.Body.Components;
using NUnit.Framework;
diff --git a/Content.IntegrationTests/Tests/Body/MechanismBehaviorEventsTest.cs b/Content.IntegrationTests/Tests/Body/MechanismBehaviorEventsTest.cs
index 9b175edcd5..ef47ff4dc8 100644
--- a/Content.IntegrationTests/Tests/Body/MechanismBehaviorEventsTest.cs
+++ b/Content.IntegrationTests/Tests/Body/MechanismBehaviorEventsTest.cs
@@ -3,7 +3,6 @@ using System.Linq;
using System.Threading.Tasks;
using Content.Server.Body.Behavior;
using Content.Shared.Body.Components;
-using Content.Shared.Body.Mechanism;
using Content.Shared.Body.Part;
using NUnit.Framework;
using Robust.Shared.GameObjects;
diff --git a/Content.Server/Administration/Commands/AddBodyPartCommand.cs b/Content.Server/Administration/Commands/AddBodyPartCommand.cs
index ecf4a41594..912b0d44e5 100644
--- a/Content.Server/Administration/Commands/AddBodyPartCommand.cs
+++ b/Content.Server/Administration/Commands/AddBodyPartCommand.cs
@@ -1,5 +1,5 @@
using Content.Server.Body;
-using Content.Server.Body.Mechanism;
+using Content.Server.Body.Components;
using Content.Server.Body.Part;
using Content.Server.Storage.Components;
using Content.Shared.Administration;
diff --git a/Content.Server/Administration/Commands/AddEntityStorageCommand.cs b/Content.Server/Administration/Commands/AddEntityStorageCommand.cs
index 8a4cd999eb..6e602c8e00 100644
--- a/Content.Server/Administration/Commands/AddEntityStorageCommand.cs
+++ b/Content.Server/Administration/Commands/AddEntityStorageCommand.cs
@@ -1,4 +1,3 @@
-using Content.Server.Body.Mechanism;
using Content.Server.Body.Part;
using Content.Server.Storage.Components;
using Content.Shared.Administration;
diff --git a/Content.Server/Administration/Commands/AddMechanismCommand.cs b/Content.Server/Administration/Commands/AddMechanismCommand.cs
index de2154da0f..05bff1498b 100644
--- a/Content.Server/Administration/Commands/AddMechanismCommand.cs
+++ b/Content.Server/Administration/Commands/AddMechanismCommand.cs
@@ -1,5 +1,5 @@
using Content.Server.Body;
-using Content.Server.Body.Mechanism;
+using Content.Server.Body.Components;
using Content.Server.Body.Part;
using Content.Server.Storage.Components;
using Content.Shared.Administration;
diff --git a/Content.Server/Administration/Commands/RemoveBodyPartCommand.cs b/Content.Server/Administration/Commands/RemoveBodyPartCommand.cs
index 81473aeb70..3aaed66b97 100644
--- a/Content.Server/Administration/Commands/RemoveBodyPartCommand.cs
+++ b/Content.Server/Administration/Commands/RemoveBodyPartCommand.cs
@@ -1,4 +1,5 @@
using Content.Server.Body;
+using Content.Server.Body.Components;
using Content.Server.Body.Part;
using Content.Shared.Administration;
using Robust.Shared.Console;
diff --git a/Content.Server/Administration/Commands/RemoveEntityStorageCommand.cs b/Content.Server/Administration/Commands/RemoveEntityStorageCommand.cs
index 3a3d7114aa..e296c5d338 100644
--- a/Content.Server/Administration/Commands/RemoveEntityStorageCommand.cs
+++ b/Content.Server/Administration/Commands/RemoveEntityStorageCommand.cs
@@ -1,4 +1,3 @@
-using Content.Server.Body.Mechanism;
using Content.Server.Body.Part;
using Content.Server.Storage.Components;
using Content.Shared.Administration;
diff --git a/Content.Server/Administration/Commands/RemoveMechanismCommand.cs b/Content.Server/Administration/Commands/RemoveMechanismCommand.cs
index 5284ecc759..a8eecd9961 100644
--- a/Content.Server/Administration/Commands/RemoveMechanismCommand.cs
+++ b/Content.Server/Administration/Commands/RemoveMechanismCommand.cs
@@ -1,5 +1,5 @@
using Content.Server.Body;
-using Content.Server.Body.Mechanism;
+using Content.Server.Body.Components;
using Content.Server.Body.Part;
using Content.Shared.Administration;
using Robust.Shared.Console;
diff --git a/Content.Server/Atmos/Components/BreathToolComponent.cs b/Content.Server/Atmos/Components/BreathToolComponent.cs
index 6b4ca06792..d1ebbc483c 100644
--- a/Content.Server/Atmos/Components/BreathToolComponent.cs
+++ b/Content.Server/Atmos/Components/BreathToolComponent.cs
@@ -1,4 +1,4 @@
-using Content.Server.Body.Respiratory;
+using Content.Server.Body.Components;
using Content.Shared.Inventory;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes;
diff --git a/Content.Server/Atmos/Components/GasTankComponent.cs b/Content.Server/Atmos/Components/GasTankComponent.cs
index 3434635cea..e9e0f63306 100644
--- a/Content.Server/Atmos/Components/GasTankComponent.cs
+++ b/Content.Server/Atmos/Components/GasTankComponent.cs
@@ -1,6 +1,6 @@
using System;
using Content.Server.Atmos.EntitySystems;
-using Content.Server.Body.Respiratory;
+using Content.Server.Body.Components;
using Content.Server.Explosion.EntitySystems;
using Content.Server.UserInterface;
using Content.Shared.ActionBlocker;
diff --git a/Content.Server/Body/Behavior/LungBehavior.cs b/Content.Server/Body/Behavior/LungBehavior.cs
index 572778c27a..9d05881698 100644
--- a/Content.Server/Body/Behavior/LungBehavior.cs
+++ b/Content.Server/Body/Behavior/LungBehavior.cs
@@ -2,8 +2,7 @@ using System;
using Content.Server.Atmos;
using Content.Server.Atmos.Components;
using Content.Server.Atmos.EntitySystems;
-using Content.Server.Body.Circulatory;
-using Content.Server.Body.Respiratory;
+using Content.Server.Body.Components;
using Content.Server.Popups;
using Content.Shared.Atmos;
using Content.Shared.Body.Components;
diff --git a/Content.Server/Body/Behavior/MechanismBehavior.cs b/Content.Server/Body/Behavior/MechanismBehavior.cs
index ff5c468126..40ace4a985 100644
--- a/Content.Server/Body/Behavior/MechanismBehavior.cs
+++ b/Content.Server/Body/Behavior/MechanismBehavior.cs
@@ -1,6 +1,5 @@
using Content.Shared.Body.Behavior;
using Content.Shared.Body.Components;
-using Content.Shared.Body.Mechanism;
using Content.Shared.Body.Part;
using Robust.Shared.GameObjects;
using Robust.Shared.Utility;
diff --git a/Content.Server/Body/Behavior/StomachBehavior.cs b/Content.Server/Body/Behavior/StomachBehavior.cs
deleted file mode 100644
index 160477a674..0000000000
--- a/Content.Server/Body/Behavior/StomachBehavior.cs
+++ /dev/null
@@ -1,198 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-using Content.Server.Body.Circulatory;
-using Content.Server.Chemistry.EntitySystems;
-using Content.Shared.Body.Networks;
-using Content.Shared.Chemistry.Components;
-using Content.Shared.Chemistry.Reagent;
-using Content.Shared.FixedPoint;
-using Robust.Shared.GameObjects;
-using Robust.Shared.Serialization.Manager.Attributes;
-using Robust.Shared.ViewVariables;
-
-namespace Content.Server.Body.Behavior
-{
- ///
- /// Where reagents go when ingested. Tracks ingested reagents over time, and
- /// eventually transfers them to once digested.
- ///
- public class StomachBehavior : MechanismBehavior
- {
- private const string DefaultSolutionName = "stomach";
- private float _accumulatedFrameTime;
-
- ///
- /// Updates digestion status of ingested reagents.
- /// Once reagents surpass _digestionDelay they are moved to the
- /// bloodstream, where they are then metabolized.
- ///
- ///
- /// The time since the last update in seconds.
- ///
- public override void Update(float frameTime)
- {
- // Do not metabolise if the organ does not have a body.
- if (Body == null)
- {
- return;
- }
-
- _accumulatedFrameTime += frameTime;
-
- // Update at most once per second
- if (_accumulatedFrameTime < 1)
- {
- return;
- }
-
- _accumulatedFrameTime -= 1;
-
- if (!Body.Owner.TryGetComponent(out BloodstreamComponent? bloodstream) ||
- StomachSolution == null) // Something has gone wrong here.
- {
- return;
- }
-
- // Reagents ready to transfer into the bloodstream are added to this solution
- var transferSolution = new Solution();
-
- // Use ToList here to remove entries while iterating
- foreach (var delta in _reagentDeltas.ToList())
- {
- //Increment lifetime of reagents
- delta.Increment(1);
- if (delta.Lifetime > _digestionDelay)
- {
- // This reagent has been in the stomach long enough, TRY to transfer it.
- // But first, check if the reagent still exists, and how much is left.
- // Some poor spessman may have washed down a potassium snack with some water.
- if (StomachSolution.ContainsReagent(delta.ReagentId, out FixedPoint2 quantity))
- {
- if (quantity > delta.Quantity)
- {
- quantity = delta.Quantity;
- }
-
- EntitySystem.Get()
- .TryRemoveReagent(Owner.Uid, StomachSolution, delta.ReagentId, quantity);
- transferSolution.AddReagent(delta.ReagentId, quantity);
- }
-
- _reagentDeltas.Remove(delta);
- }
- }
-
- // Transfer digested reagents to bloodstream
- bloodstream.TryTransferSolution(transferSolution);
- }
-
- public Solution? StomachSolution
- {
- get
- {
- EntitySystem.Get().TryGetSolution(Owner.Uid, DefaultSolutionName, out var solution);
- return solution;
- }
- }
-
- ///
- /// Max volume of internal solution storage
- ///
- public FixedPoint2 MaxVolume
- {
- get =>
- StomachSolution?.MaxVolume ?? FixedPoint2.Zero;
-
- set
- {
- if (StomachSolution != null)
- {
- StomachSolution.MaxVolume = value;
- }
- }
- }
-
- ///
- /// Initial internal solution storage volume
- ///
- [DataField("maxVolume")]
- [ViewVariables]
- protected FixedPoint2 InitialMaxVolume { get; private set; } = FixedPoint2.New(100);
-
- ///
- /// Time in seconds between reagents being ingested and them being
- /// transferred to
- ///
- [DataField("digestionDelay")] [ViewVariables]
- private float _digestionDelay = 20;
-
- ///
- /// Used to track how long each reagent has been in the stomach
- ///
- [ViewVariables] private readonly List _reagentDeltas = new();
-
- public override void Startup()
- {
- base.Startup();
-
- var solution = EntitySystem.Get().EnsureSolution(Owner.Uid, DefaultSolutionName);
- solution.MaxVolume = InitialMaxVolume;
- }
-
- public bool CanTransferSolution(Solution solution)
- {
- if (StomachSolution == null)
- {
- return false;
- }
-
- // TODO: For now no partial transfers. Potentially change by design
- if (!StomachSolution.CanAddSolution(solution))
- {
- return false;
- }
-
- return true;
- }
-
- public bool TryTransferSolution(Solution solution)
- {
- if (Owner == null || !CanTransferSolution(solution))
- return false;
-
- if (StomachSolution == null)
- {
- return false;
- }
-
- // Add solution to _stomachContents
- EntitySystem.Get().TryAddSolution(Owner.Uid, StomachSolution, solution);
- // Add each reagent to _reagentDeltas. Used to track how long each reagent has been in the stomach
- foreach (var reagent in solution.Contents)
- {
- _reagentDeltas.Add(new ReagentDelta(reagent.ReagentId, reagent.Quantity));
- }
-
- return true;
- }
-
- ///
- /// Used to track quantity changes when ingesting & digesting reagents
- ///
- protected class ReagentDelta
- {
- public readonly string ReagentId;
- public readonly FixedPoint2 Quantity;
- public float Lifetime { get; private set; }
-
- public ReagentDelta(string reagentId, FixedPoint2 quantity)
- {
- ReagentId = reagentId;
- Quantity = quantity;
- Lifetime = 0.0f;
- }
-
- public void Increment(float delta) => Lifetime += delta;
- }
- }
-}
diff --git a/Content.Server/Body/Circulatory/BloodstreamComponent.cs b/Content.Server/Body/Components/BloodstreamComponent.cs
similarity index 95%
rename from Content.Server/Body/Circulatory/BloodstreamComponent.cs
rename to Content.Server/Body/Components/BloodstreamComponent.cs
index 0e7b6d04df..9852f969e1 100644
--- a/Content.Server/Body/Circulatory/BloodstreamComponent.cs
+++ b/Content.Server/Body/Components/BloodstreamComponent.cs
@@ -1,18 +1,16 @@
using System;
using Content.Server.Atmos;
using Content.Server.Atmos.EntitySystems;
-using Content.Server.Body.Respiratory;
using Content.Server.Chemistry.EntitySystems;
using Content.Shared.Atmos;
-using Content.Shared.Body.Networks;
+using Content.Shared.Body.Components;
using Content.Shared.Chemistry.Components;
-using Content.Shared.Chemistry.Reagent;
using Content.Shared.FixedPoint;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
-namespace Content.Server.Body.Circulatory
+namespace Content.Server.Body.Components
{
[RegisterComponent]
[ComponentReference(typeof(SharedBloodstreamComponent))]
diff --git a/Content.Server/Body/BodyComponent.cs b/Content.Server/Body/Components/BodyComponent.cs
similarity index 98%
rename from Content.Server/Body/BodyComponent.cs
rename to Content.Server/Body/Components/BodyComponent.cs
index 916943f667..b325eea9f1 100644
--- a/Content.Server/Body/BodyComponent.cs
+++ b/Content.Server/Body/Components/BodyComponent.cs
@@ -1,8 +1,8 @@
using Content.Server.Ghost;
using Content.Shared.Audio;
+using Content.Shared.Body;
using Content.Shared.Body.Components;
using Content.Shared.Body.Part;
-using Content.Shared.Body.Slot;
using Content.Shared.Random.Helpers;
using Content.Shared.Sound;
using Robust.Shared.Audio;
@@ -12,7 +12,7 @@ using Robust.Shared.Log;
using Robust.Shared.Player;
using Robust.Shared.Serialization.Manager.Attributes;
-namespace Content.Server.Body
+namespace Content.Server.Body.Components
{
[RegisterComponent]
[ComponentReference(typeof(SharedBodyComponent))]
diff --git a/Content.Server/Body/Respiratory/InternalsComponent.cs b/Content.Server/Body/Components/InternalsComponent.cs
similarity index 98%
rename from Content.Server/Body/Respiratory/InternalsComponent.cs
rename to Content.Server/Body/Components/InternalsComponent.cs
index 87ec4d7b6d..35a027a175 100644
--- a/Content.Server/Body/Respiratory/InternalsComponent.cs
+++ b/Content.Server/Body/Components/InternalsComponent.cs
@@ -2,7 +2,7 @@
using Robust.Shared.GameObjects;
using Robust.Shared.ViewVariables;
-namespace Content.Server.Body.Respiratory
+namespace Content.Server.Body.Components
{
[RegisterComponent]
public class InternalsComponent : Component
diff --git a/Content.Server/Body/Mechanism/MechanismComponent.cs b/Content.Server/Body/Components/MechanismComponent.cs
similarity index 98%
rename from Content.Server/Body/Mechanism/MechanismComponent.cs
rename to Content.Server/Body/Components/MechanismComponent.cs
index 52c5cb56ca..d95593fe50 100644
--- a/Content.Server/Body/Mechanism/MechanismComponent.cs
+++ b/Content.Server/Body/Components/MechanismComponent.cs
@@ -2,7 +2,6 @@ using System.Collections.Generic;
using System.Threading.Tasks;
using Content.Server.UserInterface;
using Content.Shared.Body.Components;
-using Content.Shared.Body.Mechanism;
using Content.Shared.Body.Part;
using Content.Shared.Body.Surgery;
using Content.Shared.Interaction;
@@ -14,7 +13,7 @@ using Robust.Shared.Localization;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
-namespace Content.Server.Body.Mechanism
+namespace Content.Server.Body.Components
{
[RegisterComponent]
[ComponentReference(typeof(SharedMechanismComponent))]
diff --git a/Content.Server/Body/Metabolism/MetabolizerComponent.cs b/Content.Server/Body/Components/MetabolizerComponent.cs
similarity index 89%
rename from Content.Server/Body/Metabolism/MetabolizerComponent.cs
rename to Content.Server/Body/Components/MetabolizerComponent.cs
index 56d666cb4a..28f93d6079 100644
--- a/Content.Server/Body/Metabolism/MetabolizerComponent.cs
+++ b/Content.Server/Body/Components/MetabolizerComponent.cs
@@ -1,18 +1,15 @@
using System.Collections.Generic;
-using System.ComponentModel.DataAnnotations;
-using Content.Shared.Body.Metabolism;
-using Content.Shared.Body.Networks;
-using Content.Shared.Chemistry.Reagent;
+using Content.Server.Body.Systems;
+using Content.Shared.Body.Components;
+using Content.Shared.Body.Prototypes;
using Content.Shared.FixedPoint;
using Robust.Shared.Analyzers;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
-using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;
-using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set;
-namespace Content.Server.Body.Metabolism
+namespace Content.Server.Body.Components
{
///
/// Handles metabolizing various reagents with given effects.
diff --git a/Content.Server/Body/Respiratory/RespiratorComponent.cs b/Content.Server/Body/Components/RespiratorComponent.cs
similarity index 99%
rename from Content.Server/Body/Respiratory/RespiratorComponent.cs
rename to Content.Server/Body/Components/RespiratorComponent.cs
index 4e95ce9002..2047af0cc3 100644
--- a/Content.Server/Body/Respiratory/RespiratorComponent.cs
+++ b/Content.Server/Body/Components/RespiratorComponent.cs
@@ -5,7 +5,6 @@ using Content.Server.Alert;
using Content.Server.Atmos;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Body.Behavior;
-using Content.Server.Body.Circulatory;
using Content.Server.Temperature.Components;
using Content.Server.Temperature.Systems;
using Content.Shared.ActionBlocker;
@@ -20,7 +19,7 @@ using Robust.Shared.Localization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
-namespace Content.Server.Body.Respiratory
+namespace Content.Server.Body.Components
{
[RegisterComponent]
public class RespiratorComponent : Component
diff --git a/Content.Server/Body/Respiratory/RespiratorSystem.cs b/Content.Server/Body/Components/RespiratorSystem.cs
similarity index 91%
rename from Content.Server/Body/Respiratory/RespiratorSystem.cs
rename to Content.Server/Body/Components/RespiratorSystem.cs
index 7fd911d9d9..10bd67837a 100644
--- a/Content.Server/Body/Respiratory/RespiratorSystem.cs
+++ b/Content.Server/Body/Components/RespiratorSystem.cs
@@ -1,7 +1,7 @@
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
-namespace Content.Server.Body.Respiratory
+namespace Content.Server.Body.Components
{
[UsedImplicitly]
public class RespiratorSystem : EntitySystem
diff --git a/Content.Server/Body/Components/StomachComponent.cs b/Content.Server/Body/Components/StomachComponent.cs
new file mode 100644
index 0000000000..c73de7a773
--- /dev/null
+++ b/Content.Server/Body/Components/StomachComponent.cs
@@ -0,0 +1,69 @@
+using System.Collections.Generic;
+using Content.Server.Body.Systems;
+using Content.Shared.Body.Components;
+using Content.Shared.FixedPoint;
+using Robust.Shared.Analyzers;
+using Robust.Shared.GameObjects;
+using Robust.Shared.Serialization.Manager.Attributes;
+using Robust.Shared.ViewVariables;
+
+namespace Content.Server.Body.Components
+{
+ [RegisterComponent, Friend(typeof(StomachSystem))]
+ public class StomachComponent : Component
+ {
+ public override string Name => "Stomach";
+
+ public float AccumulatedFrameTime;
+
+ ///
+ /// How fast should this component update, in seconds?
+ ///
+ [DataField("updateInterval")]
+ public float UpdateInterval = 1.0f;
+
+ ///
+ /// What solution should this stomach push reagents into, on the body?
+ ///
+ [DataField("bodySolutionName")]
+ public string BodySolutionName = SharedBloodstreamComponent.DefaultSolutionName;
+
+ ///
+ /// Initial internal solution storage volume
+ ///
+ [DataField("maxVolume")]
+ public FixedPoint2 InitialMaxVolume { get; private set; } = FixedPoint2.New(100);
+
+ ///
+ /// Time in seconds between reagents being ingested and them being
+ /// transferred to
+ ///
+ [DataField("digestionDelay")]
+ public float DigestionDelay = 20;
+
+ ///
+ /// Used to track how long each reagent has been in the stomach
+ ///
+ [ViewVariables]
+ public readonly List ReagentDeltas = new();
+
+ ///
+ /// Used to track quantity changes when ingesting & digesting reagents
+ ///
+ public class ReagentDelta
+ {
+ public readonly string ReagentId;
+ public readonly FixedPoint2 Quantity;
+ public float Lifetime { get; private set; }
+
+ public ReagentDelta(string reagentId, FixedPoint2 quantity)
+ {
+ ReagentId = reagentId;
+ Quantity = quantity;
+ Lifetime = 0.0f;
+ }
+
+ public void Increment(float delta) => Lifetime += delta;
+ }
+ }
+}
diff --git a/Content.Server/Body/Part/BodyPartComponent.cs b/Content.Server/Body/Part/BodyPartComponent.cs
index 942bcc70e9..8c47adb572 100644
--- a/Content.Server/Body/Part/BodyPartComponent.cs
+++ b/Content.Server/Body/Part/BodyPartComponent.cs
@@ -2,7 +2,6 @@ using System.Collections.Generic;
using System.Threading.Tasks;
using Content.Server.UserInterface;
using Content.Shared.Body.Components;
-using Content.Shared.Body.Mechanism;
using Content.Shared.Body.Part;
using Content.Shared.Body.Surgery;
using Content.Shared.Interaction;
diff --git a/Content.Server/Body/Scanner/BodyScannerComponent.cs b/Content.Server/Body/Scanner/BodyScannerComponent.cs
index c0363699e2..9c178bfd59 100644
--- a/Content.Server/Body/Scanner/BodyScannerComponent.cs
+++ b/Content.Server/Body/Scanner/BodyScannerComponent.cs
@@ -1,6 +1,5 @@
using Content.Server.UserInterface;
using Content.Shared.Body.Components;
-using Content.Shared.Body.Scanner;
using Content.Shared.Interaction;
using Robust.Server.GameObjects;
using Robust.Shared.GameObjects;
diff --git a/Content.Server/Body/Surgery/BiologicalSurgeryDataComponent.cs b/Content.Server/Body/Surgery/BiologicalSurgeryDataComponent.cs
index 4485859f8c..bece574f9f 100644
--- a/Content.Server/Body/Surgery/BiologicalSurgeryDataComponent.cs
+++ b/Content.Server/Body/Surgery/BiologicalSurgeryDataComponent.cs
@@ -4,7 +4,6 @@ using System.Text;
using System.Threading.Tasks;
using Content.Server.DoAfter;
using Content.Shared.Body.Components;
-using Content.Shared.Body.Mechanism;
using Content.Shared.Body.Part;
using Content.Shared.Body.Surgery;
using Content.Shared.Popups;
diff --git a/Content.Server/Body/Surgery/Components/SurgeryToolComponent.cs b/Content.Server/Body/Surgery/Components/SurgeryToolComponent.cs
index 02690a615d..3af071f842 100644
--- a/Content.Server/Body/Surgery/Components/SurgeryToolComponent.cs
+++ b/Content.Server/Body/Surgery/Components/SurgeryToolComponent.cs
@@ -1,11 +1,10 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
-using Content.Server.Body.Mechanism;
+using Content.Server.Body.Components;
using Content.Server.Body.Surgery.Messages;
using Content.Server.UserInterface;
using Content.Shared.Body.Components;
-using Content.Shared.Body.Mechanism;
using Content.Shared.Body.Part;
using Content.Shared.Body.Surgery;
using Content.Shared.Interaction;
diff --git a/Content.Server/Body/BodySystem.cs b/Content.Server/Body/Systems/BodySystem.cs
similarity index 50%
rename from Content.Server/Body/BodySystem.cs
rename to Content.Server/Body/Systems/BodySystem.cs
index be7d62b46c..b93005fb9b 100644
--- a/Content.Server/Body/BodySystem.cs
+++ b/Content.Server/Body/Systems/BodySystem.cs
@@ -1,12 +1,17 @@
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using Content.Server.Body.Components;
using Content.Server.GameTicking;
using Content.Server.Mind.Components;
+using Content.Shared.Body.Components;
using Content.Shared.MobState.Components;
using Content.Shared.Movement.EntitySystems;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Timing;
-namespace Content.Server.Body
+namespace Content.Server.Body.Systems
{
public sealed class BodySystem : EntitySystem
{
@@ -34,5 +39,40 @@ namespace Content.Server.Body
_ticker.OnGhostAttempt(mind.Mind!, true);
}
}
+
+ public IEnumerable GetComponentsOnMechanisms(EntityUid uid,
+ SharedBodyComponent? body) where T : Component
+ {
+ if (!Resolve(uid, ref body))
+ yield break;
+
+ foreach (var (part, _) in body.Parts)
+ foreach (var mechanism in part.Mechanisms)
+ {
+ if (EntityManager.TryGetComponent(mechanism.OwnerUid, out var comp))
+ yield return comp;
+ }
+ }
+
+ public bool TryGetComponentsOnMechanisms(EntityUid uid,
+ [NotNullWhen(true)] out IEnumerable? comps,
+ SharedBodyComponent? body) where T: Component
+ {
+ if (!Resolve(uid, ref body))
+ {
+ comps = null;
+ return false;
+ }
+
+ comps = GetComponentsOnMechanisms(uid, body).ToArray();
+
+ if (!comps.Any())
+ {
+ comps = null;
+ return false;
+ }
+
+ return true;
+ }
}
}
diff --git a/Content.Server/Body/Metabolism/MetabolizerSystem.cs b/Content.Server/Body/Systems/MetabolizerSystem.cs
similarity index 96%
rename from Content.Server/Body/Metabolism/MetabolizerSystem.cs
rename to Content.Server/Body/Systems/MetabolizerSystem.cs
index a767222515..7ca3fc170e 100644
--- a/Content.Server/Body/Metabolism/MetabolizerSystem.cs
+++ b/Content.Server/Body/Systems/MetabolizerSystem.cs
@@ -1,11 +1,7 @@
-using System.Collections.Generic;
using System.Linq;
-using Content.Server.Body.Circulatory;
-using Content.Server.Body.Mechanism;
+using Content.Server.Body.Components;
using Content.Server.Chemistry.Components.SolutionManager;
using Content.Server.Chemistry.EntitySystems;
-using Content.Shared.Body.Components;
-using Content.Shared.Body.Mechanism;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.FixedPoint;
@@ -16,7 +12,7 @@ using Robust.Shared.IoC;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
-namespace Content.Server.Body.Metabolism
+namespace Content.Server.Body.Systems
{
// TODO mirror in the future working on mechanisms move updating here to BodySystem so it can be ordered?
[UsedImplicitly]
diff --git a/Content.Server/Body/Systems/StomachSystem.cs b/Content.Server/Body/Systems/StomachSystem.cs
new file mode 100644
index 0000000000..dd35f61122
--- /dev/null
+++ b/Content.Server/Body/Systems/StomachSystem.cs
@@ -0,0 +1,121 @@
+using Content.Server.Body.Components;
+using Content.Server.Chemistry.Components.SolutionManager;
+using Content.Server.Chemistry.EntitySystems;
+using Content.Shared.Chemistry.Components;
+using Robust.Shared.GameObjects;
+using Robust.Shared.IoC;
+using Robust.Shared.Utility;
+
+namespace Content.Server.Body.Systems
+{
+ public class StomachSystem : EntitySystem
+ {
+ [Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
+
+ public const string DefaultSolutionName = "stomach";
+
+ public override void Initialize()
+ {
+ SubscribeLocalEvent(OnComponentInit);
+ }
+
+ public override void Update(float frameTime)
+ {
+ foreach (var (stomach, mech, sol)
+ in EntityManager.EntityQuery(false))
+ {
+ if (mech.Body == null)
+ continue;
+
+ stomach.AccumulatedFrameTime += frameTime;
+
+ if (stomach.AccumulatedFrameTime < stomach.UpdateInterval)
+ continue;
+
+ stomach.AccumulatedFrameTime -= stomach.UpdateInterval;
+
+ // Get our solutions
+ if (!_solutionContainerSystem.TryGetSolution(stomach.OwnerUid, DefaultSolutionName,
+ out var stomachSolution, sol))
+ continue;
+
+ if (!_solutionContainerSystem.TryGetSolution(mech.Body.OwnerUid, stomach.BodySolutionName,
+ out var bodySolution))
+ continue;
+
+ var transferSolution = new Solution();
+
+ var queue = new RemQueue();
+ foreach (var delta in stomach.ReagentDeltas)
+ {
+ delta.Increment(stomach.UpdateInterval);
+ if (delta.Lifetime > stomach.DigestionDelay)
+ {
+ if (stomachSolution.ContainsReagent(delta.ReagentId, out var quant))
+ {
+ if (quant > delta.Quantity)
+ quant = delta.Quantity;
+
+ _solutionContainerSystem.TryRemoveReagent(stomach.OwnerUid, stomachSolution,
+ delta.ReagentId, quant);
+ transferSolution.AddReagent(delta.ReagentId, quant);
+ }
+
+ queue.Add(delta);
+ }
+ }
+
+ foreach (var item in queue)
+ {
+ stomach.ReagentDeltas.Remove(item);
+ }
+
+ // Transfer everything to the body solution!
+ _solutionContainerSystem.TryAddSolution(mech.Body.OwnerUid, bodySolution, transferSolution);
+ }
+ }
+
+ private void OnComponentInit(EntityUid uid, StomachComponent component, ComponentInit args)
+ {
+ var solution = _solutionContainerSystem.EnsureSolution(uid, DefaultSolutionName);
+ solution.MaxVolume = component.InitialMaxVolume;
+ }
+
+ public bool CanTransferSolution(EntityUid uid, Solution solution,
+ SolutionContainerManagerComponent? solutions=null)
+ {
+ if (!Resolve(uid, ref solutions, false))
+ return false;
+
+ if (!_solutionContainerSystem.TryGetSolution(uid, DefaultSolutionName, out var stomachSolution, solutions))
+ return false;
+
+ // TODO: For now no partial transfers. Potentially change by design
+ if (!stomachSolution.CanAddSolution(solution))
+ return false;
+
+ return true;
+ }
+
+ 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.TryGetSolution(uid, DefaultSolutionName, out var stomachSolution, solutions)
+ || !CanTransferSolution(uid, solution, solutions))
+ return false;
+
+ _solutionContainerSystem.TryAddSolution(uid, stomachSolution, solution);
+ // Add each reagent to ReagentDeltas. Used to track how long each reagent has been in the stomach
+ foreach (var reagent in solution.Contents)
+ {
+ stomach.ReagentDeltas.Add(new StomachComponent.ReagentDelta(reagent.ReagentId, reagent.Quantity));
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/Content.Server/Chemistry/Components/FoamSolutionAreaEffectComponent.cs b/Content.Server/Chemistry/Components/FoamSolutionAreaEffectComponent.cs
index 28d6b32aff..4d3ba16a44 100644
--- a/Content.Server/Chemistry/Components/FoamSolutionAreaEffectComponent.cs
+++ b/Content.Server/Chemistry/Components/FoamSolutionAreaEffectComponent.cs
@@ -1,4 +1,4 @@
-using Content.Server.Body.Circulatory;
+using Content.Server.Body.Components;
using Content.Server.Chemistry.EntitySystems;
using Content.Server.Inventory.Components;
using Content.Server.Items;
diff --git a/Content.Server/Chemistry/Components/InjectorComponent.cs b/Content.Server/Chemistry/Components/InjectorComponent.cs
index b8ae14ae6e..7372574847 100644
--- a/Content.Server/Chemistry/Components/InjectorComponent.cs
+++ b/Content.Server/Chemistry/Components/InjectorComponent.cs
@@ -1,9 +1,9 @@
using System;
using System.Threading.Tasks;
-using Content.Server.Body.Circulatory;
+using Content.Server.Body.Components;
using Content.Server.Chemistry.Components.SolutionManager;
using Content.Server.Chemistry.EntitySystems;
-using Content.Shared.Body.Networks;
+using Content.Shared.Body.Components;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.FixedPoint;
diff --git a/Content.Server/Chemistry/Components/SmokeSolutionAreaEffectComponent.cs b/Content.Server/Chemistry/Components/SmokeSolutionAreaEffectComponent.cs
index e57190369c..110828ef78 100644
--- a/Content.Server/Chemistry/Components/SmokeSolutionAreaEffectComponent.cs
+++ b/Content.Server/Chemistry/Components/SmokeSolutionAreaEffectComponent.cs
@@ -1,5 +1,4 @@
-using Content.Server.Body.Circulatory;
-using Content.Server.Body.Respiratory;
+using Content.Server.Body.Components;
using Content.Server.Chemistry.EntitySystems;
using Content.Shared.Chemistry;
using Content.Shared.Chemistry.Reagent;
diff --git a/Content.Server/Chemistry/EntitySystems/SolutionContainerSystem.cs b/Content.Server/Chemistry/EntitySystems/SolutionContainerSystem.cs
index e1835481da..3dac2e5285 100644
--- a/Content.Server/Chemistry/EntitySystems/SolutionContainerSystem.cs
+++ b/Content.Server/Chemistry/EntitySystems/SolutionContainerSystem.cs
@@ -215,7 +215,7 @@ namespace Content.Server.Chemistry.EntitySystems
[NotNullWhen(true)] out Solution? solution,
SolutionContainerManagerComponent? solutionsMgr = null)
{
- if (!Resolve(uid, ref solutionsMgr))
+ if (!Resolve(uid, ref solutionsMgr, false))
{
solution = null;
return false;
diff --git a/Content.Server/Chemistry/EntitySystems/SolutionInjectOnCollideSystem.cs b/Content.Server/Chemistry/EntitySystems/SolutionInjectOnCollideSystem.cs
index 7de40d5224..23a4419357 100644
--- a/Content.Server/Chemistry/EntitySystems/SolutionInjectOnCollideSystem.cs
+++ b/Content.Server/Chemistry/EntitySystems/SolutionInjectOnCollideSystem.cs
@@ -1,4 +1,4 @@
-using Content.Server.Body.Circulatory;
+using Content.Server.Body.Components;
using Content.Server.Chemistry.Components;
using Content.Server.Chemistry.Components.SolutionManager;
using JetBrains.Annotations;
diff --git a/Content.Server/Chemistry/ReagentEffectConditions/OrganType.cs b/Content.Server/Chemistry/ReagentEffectConditions/OrganType.cs
index ea327ab490..6bcf9cf191 100644
--- a/Content.Server/Chemistry/ReagentEffectConditions/OrganType.cs
+++ b/Content.Server/Chemistry/ReagentEffectConditions/OrganType.cs
@@ -1,5 +1,5 @@
-using Content.Server.Body.Metabolism;
-using Content.Shared.Body.Metabolism;
+using Content.Server.Body.Components;
+using Content.Shared.Body.Prototypes;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Reagent;
using Robust.Shared.GameObjects;
diff --git a/Content.Server/Nutrition/Components/FoodComponent.cs b/Content.Server/Nutrition/Components/FoodComponent.cs
index c12beb98f2..8327a55edd 100644
--- a/Content.Server/Nutrition/Components/FoodComponent.cs
+++ b/Content.Server/Nutrition/Components/FoodComponent.cs
@@ -3,6 +3,8 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Content.Server.Body.Behavior;
+using Content.Server.Body.Components;
+using Content.Server.Body.Systems;
using Content.Server.Chemistry.EntitySystems;
using Content.Server.Hands.Components;
using Content.Server.Items;
@@ -102,6 +104,9 @@ namespace Content.Server.Nutrition.Components
public bool TryUseFood(IEntity? user, IEntity? target, UtensilComponent? utensilUsed = null)
{
var solutionContainerSys = EntitySystem.Get();
+ var bodySys = EntitySystem.Get();
+ var stomachSys = EntitySystem.Get();
+
if (!solutionContainerSys.TryGetSolution(Owner.Uid, SolutionName, out var solution))
{
return false;
@@ -122,7 +127,7 @@ namespace Content.Server.Nutrition.Components
var trueTarget = target ?? user;
if (!trueTarget.TryGetComponent(out SharedBodyComponent? body) ||
- !body.TryGetMechanismBehaviors(out var stomachs))
+ !bodySys.TryGetComponentsOnMechanisms(body.OwnerUid, out var stomachs, body))
{
return false;
}
@@ -165,7 +170,7 @@ namespace Content.Server.Nutrition.Components
var transferAmount = TransferAmount != null ? FixedPoint2.Min((FixedPoint2)TransferAmount, solution.CurrentVolume) : solution.CurrentVolume;
var split = solutionContainerSys.SplitSolution(Owner.Uid, solution, transferAmount);
- var firstStomach = stomachs.FirstOrDefault(stomach => stomach.CanTransferSolution(split));
+ var firstStomach = stomachs.FirstOrDefault(stomach => stomachSys.CanTransferSolution(stomach.OwnerUid, split));
if (firstStomach == null)
{
@@ -175,13 +180,9 @@ namespace Content.Server.Nutrition.Components
}
// TODO: Account for partial transfer.
-
split.DoEntityReaction(trueTarget.Uid, ReactionMethod.Ingestion);
-
- firstStomach.TryTransferSolution(split);
-
+ stomachSys.TryTransferSolution(firstStomach.OwnerUid, split, firstStomach);
SoundSystem.Play(Filter.Pvs(trueTarget), UseSound.GetSound(), trueTarget, AudioParams.Default.WithVolume(-1f));
-
trueTarget.PopupMessage(user, Loc.GetString(_eatMessage, ("food", Owner)));
// If utensils were used
diff --git a/Content.Server/Nutrition/EntitySystems/DrinkSystem.cs b/Content.Server/Nutrition/EntitySystems/DrinkSystem.cs
index 85df2a1640..f732b2b007 100644
--- a/Content.Server/Nutrition/EntitySystems/DrinkSystem.cs
+++ b/Content.Server/Nutrition/EntitySystems/DrinkSystem.cs
@@ -1,5 +1,7 @@
using System.Linq;
using Content.Server.Body.Behavior;
+using Content.Server.Body.Components;
+using Content.Server.Body.Systems;
using Content.Server.Chemistry.Components.SolutionManager;
using Content.Server.Chemistry.EntitySystems;
using Content.Server.Fluids.Components;
@@ -31,6 +33,8 @@ namespace Content.Server.Nutrition.EntitySystems
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
+ [Dependency] private readonly BodySystem _bodySystem = default!;
+ [Dependency] private readonly StomachSystem _stomachSystem = default!;
public override void Initialize()
{
@@ -211,7 +215,7 @@ namespace Content.Server.Nutrition.EntitySystems
}
if (!EntityManager.TryGetComponent(targetUid, out SharedBodyComponent? body) ||
- !body.TryGetMechanismBehaviors(out var stomachs))
+ !_bodySystem.TryGetComponentsOnMechanisms(targetUid, out var stomachs, body))
{
_popupSystem.PopupEntity(Loc.GetString("drink-component-try-use-drink-cannot-drink", ("owner", owner)), targetUid, Filter.Entities(targetUid));
return false;
@@ -222,7 +226,7 @@ namespace Content.Server.Nutrition.EntitySystems
var transferAmount = FixedPoint2.Min(component.TransferAmount, interactions.DrainAvailable);
var drain = _solutionContainerSystem.Drain(owner.Uid, interactions, transferAmount);
- var firstStomach = stomachs.FirstOrDefault(stomach => stomach.CanTransferSolution(drain));
+ var firstStomach = stomachs.FirstOrDefault(stomach => _stomachSystem.CanTransferSolution(stomach.OwnerUid, drain));
// All stomach are full or can't handle whatever solution we have.
if (firstStomach == null)
@@ -244,10 +248,8 @@ namespace Content.Server.Nutrition.EntitySystems
_popupSystem.PopupEntity(Loc.GetString("drink-component-try-use-drink-success-slurp"), targetUid, Filter.Pvs(targetUid));
// TODO: Account for partial transfer.
-
drain.DoEntityReaction(targetUid, ReactionMethod.Ingestion);
-
- firstStomach.TryTransferSolution(drain);
+ _stomachSystem.TryTransferSolution(firstStomach.OwnerUid, drain, firstStomach);
return true;
}
diff --git a/Content.Server/Nutrition/EntitySystems/SmokingSystem.cs b/Content.Server/Nutrition/EntitySystems/SmokingSystem.cs
index 26563ed29a..36b177c49c 100644
--- a/Content.Server/Nutrition/EntitySystems/SmokingSystem.cs
+++ b/Content.Server/Nutrition/EntitySystems/SmokingSystem.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
using System.Linq;
-using Content.Server.Body.Circulatory;
+using Content.Server.Body.Components;
using Content.Server.Chemistry.EntitySystems;
using Content.Server.Nutrition.Components;
using Content.Shared.Chemistry;
diff --git a/Content.Server/Weapon/Melee/MeleeWeaponSystem.cs b/Content.Server/Weapon/Melee/MeleeWeaponSystem.cs
index 74c58859b9..2ef7da23fe 100644
--- a/Content.Server/Weapon/Melee/MeleeWeaponSystem.cs
+++ b/Content.Server/Weapon/Melee/MeleeWeaponSystem.cs
@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using Content.Server.Body.Circulatory;
+using Content.Server.Body.Components;
using Content.Server.Chemistry.Components;
using Content.Server.Chemistry.EntitySystems;
using Content.Server.Cooldown;
diff --git a/Content.Shared/ActionBlocker/ActionBlockerSystem.cs b/Content.Shared/ActionBlocker/ActionBlockerSystem.cs
index 31ad5bc183..761780a0a0 100644
--- a/Content.Shared/ActionBlocker/ActionBlockerSystem.cs
+++ b/Content.Shared/ActionBlocker/ActionBlockerSystem.cs
@@ -1,9 +1,9 @@
-using Content.Shared.DragDrop;
+using Content.Shared.Body.Events;
+using Content.Shared.DragDrop;
using Content.Shared.Emoting;
using Content.Shared.Interaction.Events;
using Content.Shared.Inventory.Events;
using Content.Shared.Item;
-using Content.Shared.Body.Metabolism;
using Content.Shared.Movement;
using Content.Shared.Speech;
using Content.Shared.Throwing;
diff --git a/Content.Shared/Body/Behavior/SharedMechanismBehavior.cs b/Content.Shared/Body/Behavior/SharedMechanismBehavior.cs
index 4f2f7dad96..286c290140 100644
--- a/Content.Shared/Body/Behavior/SharedMechanismBehavior.cs
+++ b/Content.Shared/Body/Behavior/SharedMechanismBehavior.cs
@@ -1,5 +1,4 @@
using Content.Shared.Body.Components;
-using Content.Shared.Body.Mechanism;
using Content.Shared.Body.Part;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes;
diff --git a/Content.Shared/Body/Slot/BodyPartSlot.cs b/Content.Shared/Body/BodyPartSlot.cs
similarity index 97%
rename from Content.Shared/Body/Slot/BodyPartSlot.cs
rename to Content.Shared/Body/BodyPartSlot.cs
index 3971c1b0bf..072bc1773d 100644
--- a/Content.Shared/Body/Slot/BodyPartSlot.cs
+++ b/Content.Shared/Body/BodyPartSlot.cs
@@ -1,9 +1,10 @@
using System;
using System.Collections.Generic;
+using Content.Shared.Body.Components;
using Content.Shared.Body.Part;
using Robust.Shared.ViewVariables;
-namespace Content.Shared.Body.Slot
+namespace Content.Shared.Body
{
public class BodyPartSlot
{
diff --git a/Content.Shared/Body/Networks/SharedBloodstreamComponent.cs b/Content.Shared/Body/Components/SharedBloodstreamComponent.cs
similarity index 93%
rename from Content.Shared/Body/Networks/SharedBloodstreamComponent.cs
rename to Content.Shared/Body/Components/SharedBloodstreamComponent.cs
index 1ad502b386..972c592fae 100644
--- a/Content.Shared/Body/Networks/SharedBloodstreamComponent.cs
+++ b/Content.Shared/Body/Components/SharedBloodstreamComponent.cs
@@ -1,7 +1,7 @@
using Content.Shared.Chemistry.Components;
using Robust.Shared.GameObjects;
-namespace Content.Shared.Body.Networks
+namespace Content.Shared.Body.Components
{
public abstract class SharedBloodstreamComponent : Component
{
diff --git a/Content.Shared/Body/Components/SharedBodyComponent.cs b/Content.Shared/Body/Components/SharedBodyComponent.cs
index 2322217d51..0a756c7478 100644
--- a/Content.Shared/Body/Components/SharedBodyComponent.cs
+++ b/Content.Shared/Body/Components/SharedBodyComponent.cs
@@ -5,9 +5,7 @@ using System.Linq;
using Content.Shared.Body.Behavior;
using Content.Shared.Body.Part;
using Content.Shared.Body.Part.Property;
-using Content.Shared.Body.Preset;
-using Content.Shared.Body.Slot;
-using Content.Shared.Body.Template;
+using Content.Shared.Body.Prototypes;
using Content.Shared.CharacterAppearance.Systems;
using Content.Shared.Damage;
using Content.Shared.Damage.Prototypes;
diff --git a/Content.Shared/Body/Part/SharedBodyPartComponent.cs b/Content.Shared/Body/Components/SharedBodyPartComponent.cs
similarity index 99%
rename from Content.Shared/Body/Part/SharedBodyPartComponent.cs
rename to Content.Shared/Body/Components/SharedBodyPartComponent.cs
index 76d2a2997b..9e6d2509ab 100644
--- a/Content.Shared/Body/Part/SharedBodyPartComponent.cs
+++ b/Content.Shared/Body/Components/SharedBodyPartComponent.cs
@@ -3,8 +3,7 @@ using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Content.Shared.Body.Behavior;
-using Content.Shared.Body.Components;
-using Content.Shared.Body.Mechanism;
+using Content.Shared.Body.Part;
using Content.Shared.Body.Part.Property;
using Content.Shared.Body.Surgery;
using Robust.Shared.GameObjects;
@@ -17,7 +16,7 @@ using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
-namespace Content.Shared.Body.Part
+namespace Content.Shared.Body.Components
{
[NetworkedComponent()]
public abstract class SharedBodyPartComponent : Component, IBodyPartContainer
diff --git a/Content.Shared/Body/Scanner/SharedBodyScannerComponent.cs b/Content.Shared/Body/Components/SharedBodyScannerComponent.cs
similarity index 93%
rename from Content.Shared/Body/Scanner/SharedBodyScannerComponent.cs
rename to Content.Shared/Body/Components/SharedBodyScannerComponent.cs
index 0de5b61c09..b440f69033 100644
--- a/Content.Shared/Body/Scanner/SharedBodyScannerComponent.cs
+++ b/Content.Shared/Body/Components/SharedBodyScannerComponent.cs
@@ -2,7 +2,7 @@
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization;
-namespace Content.Shared.Body.Scanner
+namespace Content.Shared.Body.Components
{
public abstract class SharedBodyScannerComponent : Component
{
diff --git a/Content.Shared/Body/Mechanism/SharedMechanismComponent.cs b/Content.Shared/Body/Components/SharedMechanismComponent.cs
similarity index 98%
rename from Content.Shared/Body/Mechanism/SharedMechanismComponent.cs
rename to Content.Shared/Body/Components/SharedMechanismComponent.cs
index 5ee2f0b558..a66a2dec91 100644
--- a/Content.Shared/Body/Mechanism/SharedMechanismComponent.cs
+++ b/Content.Shared/Body/Components/SharedMechanismComponent.cs
@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Linq;
using Content.Shared.Body.Behavior;
-using Content.Shared.Body.Components;
using Content.Shared.Body.Part;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
@@ -11,7 +10,7 @@ using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Utility;
-namespace Content.Shared.Body.Mechanism
+namespace Content.Shared.Body.Components
{
public abstract class SharedMechanismComponent : Component, ISerializationHooks
{
diff --git a/Content.Shared/Body/Metabolism/ShiverAttemptEvent.cs b/Content.Shared/Body/Events/ShiverAttemptEvent.cs
similarity index 85%
rename from Content.Shared/Body/Metabolism/ShiverAttemptEvent.cs
rename to Content.Shared/Body/Events/ShiverAttemptEvent.cs
index b43a6a5729..61ff1f50d5 100644
--- a/Content.Shared/Body/Metabolism/ShiverAttemptEvent.cs
+++ b/Content.Shared/Body/Events/ShiverAttemptEvent.cs
@@ -1,6 +1,6 @@
using Robust.Shared.GameObjects;
-namespace Content.Shared.Body.Metabolism
+namespace Content.Shared.Body.Events
{
public class ShiverAttemptEvent : CancellableEntityEventArgs
{
diff --git a/Content.Shared/Body/Metabolism/SweatAttemptEvent.cs b/Content.Shared/Body/Events/SweatAttemptEvent.cs
similarity index 85%
rename from Content.Shared/Body/Metabolism/SweatAttemptEvent.cs
rename to Content.Shared/Body/Events/SweatAttemptEvent.cs
index 6d89b84831..0cd844fdfd 100644
--- a/Content.Shared/Body/Metabolism/SweatAttemptEvent.cs
+++ b/Content.Shared/Body/Events/SweatAttemptEvent.cs
@@ -1,6 +1,6 @@
using Robust.Shared.GameObjects;
-namespace Content.Shared.Body.Metabolism
+namespace Content.Shared.Body.Events
{
public class SweatAttemptEvent : CancellableEntityEventArgs
{
diff --git a/Content.Shared/Body/Part/BodyPartCompatibility.cs b/Content.Shared/Body/Part/BodyPartCompatibility.cs
index aba82d8873..d94269989b 100644
--- a/Content.Shared/Body/Part/BodyPartCompatibility.cs
+++ b/Content.Shared/Body/Part/BodyPartCompatibility.cs
@@ -1,4 +1,5 @@
using System;
+using Content.Shared.Body.Components;
using Robust.Shared.Serialization;
namespace Content.Shared.Body.Part
diff --git a/Content.Shared/Body/Part/BodyPartSymmetry.cs b/Content.Shared/Body/Part/BodyPartSymmetry.cs
index b21bd1dc2b..6c950a8716 100644
--- a/Content.Shared/Body/Part/BodyPartSymmetry.cs
+++ b/Content.Shared/Body/Part/BodyPartSymmetry.cs
@@ -1,4 +1,5 @@
using System;
+using Content.Shared.Body.Components;
using Robust.Shared.Serialization;
namespace Content.Shared.Body.Part
diff --git a/Content.Shared/Body/Part/BodyPartType.cs b/Content.Shared/Body/Part/BodyPartType.cs
index 535f68ed35..137c6a72e9 100644
--- a/Content.Shared/Body/Part/BodyPartType.cs
+++ b/Content.Shared/Body/Part/BodyPartType.cs
@@ -1,4 +1,5 @@
using System;
+using Content.Shared.Body.Components;
using Robust.Shared.Serialization;
namespace Content.Shared.Body.Part
diff --git a/Content.Shared/Body/Part/IBodyPartAdded.cs b/Content.Shared/Body/Part/IBodyPartAdded.cs
index d8d8c4a5e9..fc19497209 100644
--- a/Content.Shared/Body/Part/IBodyPartAdded.cs
+++ b/Content.Shared/Body/Part/IBodyPartAdded.cs
@@ -1,4 +1,5 @@
using System;
+using Content.Shared.Body.Components;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization;
diff --git a/Content.Shared/Body/Part/IBodyPartRemoved.cs b/Content.Shared/Body/Part/IBodyPartRemoved.cs
index ae9e83ed74..034fc878bf 100644
--- a/Content.Shared/Body/Part/IBodyPartRemoved.cs
+++ b/Content.Shared/Body/Part/IBodyPartRemoved.cs
@@ -1,4 +1,5 @@
using System;
+using Content.Shared.Body.Components;
using Robust.Shared.Serialization;
namespace Content.Shared.Body.Part
diff --git a/Content.Shared/Body/Part/Property/BodyPartPropertyComponent.cs b/Content.Shared/Body/Part/Property/BodyPartPropertyComponent.cs
index 7b75457be7..2eeba22d26 100644
--- a/Content.Shared/Body/Part/Property/BodyPartPropertyComponent.cs
+++ b/Content.Shared/Body/Part/Property/BodyPartPropertyComponent.cs
@@ -1,3 +1,4 @@
+using Content.Shared.Body.Components;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes;
diff --git a/Content.Shared/Body/Part/Property/ExtensionComponent.cs b/Content.Shared/Body/Part/Property/ExtensionComponent.cs
index bf2df77de7..32003b4c20 100644
--- a/Content.Shared/Body/Part/Property/ExtensionComponent.cs
+++ b/Content.Shared/Body/Part/Property/ExtensionComponent.cs
@@ -1,3 +1,4 @@
+using Content.Shared.Body.Components;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes;
diff --git a/Content.Shared/Body/Part/Property/GraspComponent.cs b/Content.Shared/Body/Part/Property/GraspComponent.cs
index dca53e6112..8451654f8e 100644
--- a/Content.Shared/Body/Part/Property/GraspComponent.cs
+++ b/Content.Shared/Body/Part/Property/GraspComponent.cs
@@ -1,4 +1,5 @@
-using Robust.Shared.GameObjects;
+using Content.Shared.Body.Components;
+using Robust.Shared.GameObjects;
namespace Content.Shared.Body.Part.Property
{
diff --git a/Content.Shared/Body/Part/Property/IBodyPartProperty.cs b/Content.Shared/Body/Part/Property/IBodyPartProperty.cs
index ff29c38b7b..c9330db62d 100644
--- a/Content.Shared/Body/Part/Property/IBodyPartProperty.cs
+++ b/Content.Shared/Body/Part/Property/IBodyPartProperty.cs
@@ -1,4 +1,5 @@
-using Robust.Shared.GameObjects;
+using Content.Shared.Body.Components;
+using Robust.Shared.GameObjects;
namespace Content.Shared.Body.Part.Property
{
diff --git a/Content.Shared/Body/Part/Property/LegComponent.cs b/Content.Shared/Body/Part/Property/LegComponent.cs
index 0766db0145..1fb9744cae 100644
--- a/Content.Shared/Body/Part/Property/LegComponent.cs
+++ b/Content.Shared/Body/Part/Property/LegComponent.cs
@@ -1,3 +1,4 @@
+using Content.Shared.Body.Components;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes;
diff --git a/Content.Shared/Body/Preset/BodyPresetPrototype.cs b/Content.Shared/Body/Prototypes/BodyPresetPrototype.cs
similarity index 88%
rename from Content.Shared/Body/Preset/BodyPresetPrototype.cs
rename to Content.Shared/Body/Prototypes/BodyPresetPrototype.cs
index bc12ba059f..7a64030af4 100644
--- a/Content.Shared/Body/Preset/BodyPresetPrototype.cs
+++ b/Content.Shared/Body/Prototypes/BodyPresetPrototype.cs
@@ -1,13 +1,11 @@
using System;
using System.Collections.Generic;
-using Content.Shared.Body.Components;
-using Content.Shared.Body.Part;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
-namespace Content.Shared.Body.Preset
+namespace Content.Shared.Body.Prototypes
{
///
/// Defines the parts used in a body.
diff --git a/Content.Shared/Body/Template/BodyTemplatePrototype.cs b/Content.Shared/Body/Prototypes/BodyTemplatePrototype.cs
similarity index 97%
rename from Content.Shared/Body/Template/BodyTemplatePrototype.cs
rename to Content.Shared/Body/Prototypes/BodyTemplatePrototype.cs
index 84320087e2..828a552a37 100644
--- a/Content.Shared/Body/Template/BodyTemplatePrototype.cs
+++ b/Content.Shared/Body/Prototypes/BodyTemplatePrototype.cs
@@ -1,13 +1,12 @@
using System;
using System.Collections.Generic;
-using Content.Shared.Body.Components;
using Content.Shared.Body.Part;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
-namespace Content.Shared.Body.Template
+namespace Content.Shared.Body.Prototypes
{
///
/// Defines the layout of a body.
diff --git a/Content.Shared/Body/Metabolism/MetabolismGroupPrototype.cs b/Content.Shared/Body/Prototypes/MetabolismGroupPrototype.cs
similarity index 87%
rename from Content.Shared/Body/Metabolism/MetabolismGroupPrototype.cs
rename to Content.Shared/Body/Prototypes/MetabolismGroupPrototype.cs
index 7a7a1dad52..6e261ddd57 100644
--- a/Content.Shared/Body/Metabolism/MetabolismGroupPrototype.cs
+++ b/Content.Shared/Body/Prototypes/MetabolismGroupPrototype.cs
@@ -1,7 +1,7 @@
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.Manager.Attributes;
-namespace Content.Shared.Body.Metabolism
+namespace Content.Shared.Body.Prototypes
{
[Prototype("metabolismGroup")]
public class MetabolismGroupPrototype : IPrototype
diff --git a/Content.Shared/Body/Metabolism/MetabolizerTypePrototype.cs b/Content.Shared/Body/Prototypes/MetabolizerTypePrototype.cs
similarity index 87%
rename from Content.Shared/Body/Metabolism/MetabolizerTypePrototype.cs
rename to Content.Shared/Body/Prototypes/MetabolizerTypePrototype.cs
index a66b4f24f8..9017fbb6e7 100644
--- a/Content.Shared/Body/Metabolism/MetabolizerTypePrototype.cs
+++ b/Content.Shared/Body/Prototypes/MetabolizerTypePrototype.cs
@@ -1,7 +1,7 @@
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.Manager.Attributes;
-namespace Content.Shared.Body.Metabolism
+namespace Content.Shared.Body.Prototypes
{
[Prototype("metabolizerType")]
public class MetabolizerTypePrototype : IPrototype
diff --git a/Content.Shared/Body/Surgery/ISurgeon.cs b/Content.Shared/Body/Surgery/ISurgeon.cs
index 50f77dd281..33ec4f375b 100644
--- a/Content.Shared/Body/Surgery/ISurgeon.cs
+++ b/Content.Shared/Body/Surgery/ISurgeon.cs
@@ -1,5 +1,5 @@
using System.Collections.Generic;
-using Content.Shared.Body.Mechanism;
+using Content.Shared.Body.Components;
using Content.Shared.Body.Part;
using Robust.Shared.GameObjects;
diff --git a/Content.Shared/Body/Surgery/SurgeryDataComponent.cs b/Content.Shared/Body/Surgery/SurgeryDataComponent.cs
index 9bfd1a1476..1d9c24b93e 100644
--- a/Content.Shared/Body/Surgery/SurgeryDataComponent.cs
+++ b/Content.Shared/Body/Surgery/SurgeryDataComponent.cs
@@ -1,4 +1,4 @@
-using Content.Shared.Body.Mechanism;
+using Content.Shared.Body.Components;
using Content.Shared.Body.Part;
using Robust.Shared.GameObjects;
diff --git a/Content.Shared/Body/Mechanism/MechanismSystem.cs b/Content.Shared/Body/Systems/MechanismSystem.cs
similarity index 78%
rename from Content.Shared/Body/Mechanism/MechanismSystem.cs
rename to Content.Shared/Body/Systems/MechanismSystem.cs
index afed4bda57..1af083dbc8 100644
--- a/Content.Shared/Body/Mechanism/MechanismSystem.cs
+++ b/Content.Shared/Body/Systems/MechanismSystem.cs
@@ -1,7 +1,8 @@
-using JetBrains.Annotations;
+using Content.Shared.Body.Components;
+using JetBrains.Annotations;
using Robust.Shared.GameObjects;
-namespace Content.Shared.Body.Mechanism
+namespace Content.Shared.Body.Systems
{
[UsedImplicitly]
public class MechanismSystem : EntitySystem
diff --git a/Content.Shared/CharacterAppearance/HumanoidVisualLayersExtension.cs b/Content.Shared/CharacterAppearance/HumanoidVisualLayersExtension.cs
index 7416420837..76da183504 100644
--- a/Content.Shared/CharacterAppearance/HumanoidVisualLayersExtension.cs
+++ b/Content.Shared/CharacterAppearance/HumanoidVisualLayersExtension.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using Content.Shared.Body.Components;
using Content.Shared.Body.Part;
namespace Content.Shared.CharacterAppearance
diff --git a/Content.Shared/Chemistry/Reagent/ReagentPrototype.cs b/Content.Shared/Chemistry/Reagent/ReagentPrototype.cs
index 95d9f0cc5e..c4fb54be4a 100644
--- a/Content.Shared/Chemistry/Reagent/ReagentPrototype.cs
+++ b/Content.Shared/Chemistry/Reagent/ReagentPrototype.cs
@@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
-using Content.Shared.Body.Metabolism;
+using Content.Shared.Body.Prototypes;
using Content.Shared.Botany;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Reaction;
diff --git a/Resources/Prototypes/Body/Mechanisms/human.yml b/Resources/Prototypes/Body/Mechanisms/human.yml
index 3d53eeb359..ea74357b88 100644
--- a/Resources/Prototypes/Body/Mechanisms/human.yml
+++ b/Resources/Prototypes/Body/Mechanisms/human.yml
@@ -136,14 +136,13 @@
- type: Mechanism
size: 1
compatibility: Biological
- behaviors:
- - !type:StomachBehavior
- max_volume: 250
- digestionDelay: 20
- type: SolutionContainerManager
solutions:
stomach:
maxVol: 250
+ - type: Stomach
+ maxVolume: 250
+ digestionDelay: 20
# The stomach metabolizes stuff like foods and drinks.
# TODO: Have it work off of the ent's solution container, and move this
# to intestines instead.