Entity Hydration and Needs¶
Entity carries the player "needs" stats (Hydration, Nutrition, Hygiene, Sanitation) as direct members; the Sanitation update did not move them into a separate needs/component object. What the Sanitation update DID change is the Hydrate method: the old void Hydrate(float) overload was removed and replaced by void Hydrate(Mole). Any code that still calls Entity.Hydrate(float) throws MissingMethodException: Method not found: void Assets.Scripts.Objects.Entity.Hydrate(single) at JIT time (so it fires on every invocation, not only when the drink actually happens).
The Hydrate signature change (Sanitation update)¶
Hydrate(float) no longer exists. The only two Hydrate definitions in the entire assembly are the Mole overloads below.
Assets.Scripts.Objects.Entity.Hydrate (whole-assembly line 302750):
public virtual void Hydrate(Mole water)
{
Hydration += water.Quantity.ToFloat() * HydrationBase.HydrationPerMole;
Achievements.AssessSomeHighQualityH2O(this);
}
Assets.Scripts.Objects.Entities.Human.Hydrate override (line 363073) also pushes the water into the stomach atmosphere:
public override void Hydrate(Mole water)
{
base.Hydrate(water);
if (!(OrganStomach == null) && OrganStomach.InternalAtmosphere != null && water.Quantity > MoleQuantity.Zero)
{
AtmosphericEventInstance.CreateAdd(OrganStomach.InternalAtmosphere, new GasMixture(water));
}
}
Human also exposes public Stomach OrganStomach; and public override bool CanDrink() (a helmet/suit gate). Vanilla drink paths call CanDrink() before hydrating; a suit-internal drink system may intentionally skip that check.
Mole is a struct in Assets.Scripts.Atmospherics. Constructor: public Mole(Chemistry.GasType gasType, MoleQuantity quantity, MoleEnergy energy); property public MoleQuantity Quantity { get; }; static Mole.SpecificHeat(Chemistry.GasType). MoleQuantity (readonly struct, same namespace): new MoleQuantity(double), .ToFloat(), MoleQuantity.Zero.
Needs members on Entity¶
These are UNCHANGED by the Sanitation update (still readable/writable exactly as before):
| Member | Signature | Notes |
|---|---|---|
Hydration |
public float Hydration { get; set; } |
Backing _hydration; setter clamps Mathf.Clamp(value, 0f, 8.75f). |
HydrationRatio |
public float HydrationRatio => Hydration / 5f; |
|
GetHydrationStorage() |
public float GetHydrationStorage() → return 5f * GetFoodQualityMultiplier(); |
Returns float. |
Nutrition |
public float Nutrition |
|
NutritionRatio |
public float NutritionRatio |
|
GetNutritionStorage() |
public float GetNutritionStorage() |
Human overrides BaseNutritionStorage => 50f. |
Hygiene |
public float Hygiene |
|
HygieneRatio |
public float HygieneRatio |
|
SanitationRatio |
public float SanitationRatio { get; protected set; } |
Added by the Sanitation update. |
Because Hydration is a plain clamped float property, entity.Hydration += amount; still compiles and works; only the Hydrate(float) METHOD was removed.
Hydration conversion constants (HydrationBase)¶
Assets.Scripts.Objects.Items.HydrationBase (static members, line 346856):
public static float HydrationPerLitreWater => 5f;
public static MoleQuantity WaterMolesPerUnitHydration => new MoleQuantity(55.55555555555556 / HydrationPerLitreWater); // ~= 11.111 mol
public static float HydrationPerMole => 1f / WaterMolesPerUnitHydration.ToFloat(); // ~= 0.09
Derived facts:
- 1 mole of Water gas ->
+0.09hydration. - 55.556 mol of Water (1 litre) ->
+5hydration. - Hydration clamps to
[0, 8.75].
Vanilla drink / hydrate flows¶
Objects.Structures.StructureDrinkingFountain.HandleActivate (line 147743) is the closest analog to "drink water out of a stored atmosphere": it scales a GasMixture of the source water, removes those moles, then hydrates with the removed Mole:
if (GameManager.RunSimulation)
{
GasMixture gasMixture = new GasMixture(ConnectedPipeNetwork.Atmosphere.GasMixture.Water);
gasMixture.Scale((val / gasMixture.GetTotalMolesLiquids).ToFloat());
AtmosphericEventInstance.CreateRemove(ConnectedPipeNetwork.Atmosphere, gasMixture);
human.Hydrate(gasMixture.Water); // gasMixture.Water is a Mole
}
Its serving size: Mathf.Max(0f, consumer.GetHydrationStorage() - consumer.Hydration) / 5f.
HydrationBase.OnUseItem (line 346903) is the canonical "build a Mole and hydrate" for drinkable items:
public override bool OnUseItem(float quantityToEat, Thing useOnThing)
{
if (!(useOnThing is Human human)) return false;
quantityToEat = Mathf.Min(quantityToEat, base.Quantity);
MoleQuantity moleQuantity = new MoleQuantity((double)quantityToEat / 0.018); // kg water -> moles
MoleEnergy energy = IdealGas.Energy(Chemistry.Temperature.TwentyDegrees,
Mole.SpecificHeat(Chemistry.GasType.Water), moleQuantity);
human.Hydrate(new Mole(Chemistry.GasType.Water, moleQuantity, energy));
base.Quantity -= quantityToEat;
OnStateChanged();
return true;
}
Adding hydration correctly (for mods)¶
Three ways to replace an old entity.Hydrate(amount) call, in order of fidelity:
- If you already removed water moles from a source atmosphere, pass a
Mole<Water>straight in (mirrors the fountain; also feeds the stomach viaHuman's override):
var moles = new MoleQuantity(nMolesOfWaterRemoved);
var energy = IdealGas.Energy(Chemistry.Temperature.TwentyDegrees,
Mole.SpecificHeat(Chemistry.GasType.Water), moles);
entity.Hydrate(new Mole(Chemistry.GasType.Water, moles, energy));
- If
amountwas a hydration-unit float and you just want the old effect, write the property directly (setter clamps 0..8.75). Skips the stomach-atmosphere add and the achievement:
- If
amountwas hydration units but you want to route throughHydrate, convert units -> moles first:
double waterMoles = amount * HydrationBase.WaterMolesPerUnitHydration.ToFloat(); // == amount / HydrationBase.HydrationPerMole ~= amount * 11.111
var moles = new MoleQuantity(waterMoles);
var energy = IdealGas.Energy(Chemistry.Temperature.TwentyDegrees, Mole.SpecificHeat(Chemistry.GasType.Water), moles);
entity.Hydrate(new Mole(Chemistry.GasType.Water, moles, energy));
Verification history¶
- 2026-07-06: page created from a decompile read of
Assembly-CSharpat game version 0.2.6403.27689 (.work/decomp/0.2.6403.27689/, targetedEntity/Humandumps plus the whole-assembly file). TheHydrate(Mole)signature (Entity + Human overrides), theHydration/HydrationRatio/GetHydrationStoragemembers, theHydrationBaseconversion constants, and theStructureDrinkingFountain.HandleActivate+HydrationBase.OnUseItemdrink flows are verbatim from the decompile with line numbers. The removal of theHydrate(float)overload is independently confirmed by a liveMissingMethodException: Method not found: void Assets.Scripts.Objects.Entity.Hydrate(single)thrown by Marky's Suit Drink System (Workshop 3644610659) on this version.
Open questions¶
- Whether
GetHydrationStorage()returning5f * GetFoodQualityMultiplier()whileHydrationRatiodivides by a hardcoded5fis intentional (ratio ignores the food-quality multiplier) or a game-side inconsistency. Not load-bearing for the drink calls above.