From c7c651e3decc06a35a97421a0e6ce149e0a4096c Mon Sep 17 00:00:00 2001 From: Flipp Syder <76629141+vulppine@users.noreply.github.com> Date: Fri, 29 Oct 2021 01:18:43 -0700 Subject: [PATCH] Refactors TemperatureComponent and AtmosExposed to ECS (#4927) Co-authored-by: Vera Aguilera Puerto <6766154+Zumorica@users.noreply.github.com> --- .../Atmos/Components/AtmosExposedComponent.cs | 23 +-- .../Atmos/EntitySystems/AtmosExposedSystem.cs | 26 ++++ .../Atmos/EntitySystems/AtmosphereSystem.cs | 7 +- .../Atmos/EntitySystems/FlammableSystem.cs | 10 +- .../Body/Respiratory/RespiratorComponent.cs | 14 +- .../Components/TemperatureComponent.cs | 82 ---------- .../Temperature/Systems/TemperatureSystem.cs | 140 ++++++++++++++++++ 7 files changed, 185 insertions(+), 117 deletions(-) create mode 100644 Content.Server/Atmos/EntitySystems/AtmosExposedSystem.cs create mode 100644 Content.Server/Temperature/Systems/TemperatureSystem.cs diff --git a/Content.Server/Atmos/Components/AtmosExposedComponent.cs b/Content.Server/Atmos/Components/AtmosExposedComponent.cs index 04c81e9a7c..e2573d9f7f 100644 --- a/Content.Server/Atmos/Components/AtmosExposedComponent.cs +++ b/Content.Server/Atmos/Components/AtmosExposedComponent.cs @@ -1,11 +1,8 @@ -using Content.Server.Atmos.EntitySystems; -using Content.Server.Temperature.Components; -using Robust.Shared.GameObjects; -using Robust.Shared.ViewVariables; +using Robust.Shared.GameObjects; namespace Content.Server.Atmos.Components { - // TODO: Kill this. With fire. + // not if i get there first - Flipp /// /// Represents that entity can be exposed to Atmos /// @@ -13,21 +10,5 @@ namespace Content.Server.Atmos.Components public class AtmosExposedComponent : Component { public override string Name => "AtmosExposed"; - - [ViewVariables] - [ComponentDependency] private readonly TemperatureComponent? _temperatureComponent = null; - - public void Update(GasMixture air, float frameDelta, AtmosphereSystem atmosphereSystem) - { - // TODO: I'm coming for you next, TemperatureComponent... Fear me for I am death, destroyer of shitcode. - if (_temperatureComponent != null) - { - var temperatureDelta = air.Temperature - _temperatureComponent.CurrentTemperature; - var tileHeatCapacity = atmosphereSystem.GetHeatCapacity(air); - var heat = temperatureDelta * (tileHeatCapacity * _temperatureComponent.HeatCapacity / (tileHeatCapacity + _temperatureComponent.HeatCapacity)); - _temperatureComponent.ReceiveHeat(heat); - _temperatureComponent.Update(); - } - } } } diff --git a/Content.Server/Atmos/EntitySystems/AtmosExposedSystem.cs b/Content.Server/Atmos/EntitySystems/AtmosExposedSystem.cs new file mode 100644 index 0000000000..0da7d35429 --- /dev/null +++ b/Content.Server/Atmos/EntitySystems/AtmosExposedSystem.cs @@ -0,0 +1,26 @@ +using Content.Server.Atmos.Components; +using Content.Server.Temperature.Components; +using Content.Server.Temperature.Systems; +using Robust.Shared.GameObjects; +using Robust.Shared.IoC; +using Robust.Shared.Map; + +namespace Content.Server.Atmos.EntitySystems +{ + /* doesn't seem to be a use for this at the moment, so it's disabled + public class AtmosExposedSystem : EntitySystem + {} + */ + + public readonly struct AtmosExposedUpdateEvent + { + public readonly EntityCoordinates Coordinates; + public readonly GasMixture GasMixture; + + public AtmosExposedUpdateEvent(EntityCoordinates coordinates, GasMixture mixture) + { + Coordinates = coordinates; + GasMixture = mixture; + } + } +} diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.cs index 0e619420ac..1a467ddacb 100644 --- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.cs +++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.cs @@ -1,8 +1,11 @@ using Content.Server.Atmos.Components; using Content.Server.NodeContainer.EntitySystems; +using Content.Server.Temperature.Components; +using Content.Server.Temperature.Systems; using Content.Shared.Atmos.EntitySystems; using Content.Shared.Maps; using JetBrains.Annotations; +using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Map; @@ -70,10 +73,10 @@ namespace Content.Server.Atmos.EntitySystems { foreach (var exposed in EntityManager.EntityQuery()) { - // TODO ATMOS: Kill this with fire. var tile = GetTileMixture(exposed.Owner.Transform.Coordinates); if (tile == null) continue; - exposed.Update(tile, _exposedTimer, this); + var updateEvent = new AtmosExposedUpdateEvent(exposed.Owner.Transform.Coordinates, tile); + RaiseLocalEvent(exposed.Owner.Uid, ref updateEvent); } _exposedTimer -= ExposedUpdateDelay; diff --git a/Content.Server/Atmos/EntitySystems/FlammableSystem.cs b/Content.Server/Atmos/EntitySystems/FlammableSystem.cs index 0c04055e15..a52b48af93 100644 --- a/Content.Server/Atmos/EntitySystems/FlammableSystem.cs +++ b/Content.Server/Atmos/EntitySystems/FlammableSystem.cs @@ -4,6 +4,7 @@ using Content.Server.Atmos.Components; using Content.Server.Stunnable; using Content.Server.Stunnable.Components; using Content.Server.Temperature.Components; +using Content.Server.Temperature.Systems; using Content.Shared.ActionBlocker; using Content.Shared.Alert; using Content.Shared.Atmos; @@ -27,6 +28,7 @@ namespace Content.Server.Atmos.EntitySystems [Dependency] private readonly DamageableSystem _damageableSystem = default!; [Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!; [Dependency] private readonly StunSystem _stunSystem = default!; + [Dependency] private readonly TemperatureSystem _temperatureSystem = default!; private const float MinimumFireStacks = -10f; private const float MaximumFireStacks = 20f; @@ -207,14 +209,10 @@ namespace Content.Server.Atmos.EntitySystems if (flammable.FireStacks > 0) { - if (flammable.Owner.TryGetComponent(out TemperatureComponent? temp)) - { - temp.ReceiveHeat(200 * flammable.FireStacks); - } - + _temperatureSystem.ReceiveHeat(uid, 200 * flammable.FireStacks); // TODO ATMOS Fire resistance from armor var damageScale = Math.Min((int) (flammable.FireStacks * 2.5f), 10); - _damageableSystem.TryChangeDamage(flammable.Owner.Uid, flammable.Damage * damageScale); + _damageableSystem.TryChangeDamage(uid, flammable.Damage * damageScale); AdjustFireStacks(uid, -0.1f * (flammable.Resisting ? 10f : 1f), flammable); } diff --git a/Content.Server/Body/Respiratory/RespiratorComponent.cs b/Content.Server/Body/Respiratory/RespiratorComponent.cs index af62035418..69071910b6 100644 --- a/Content.Server/Body/Respiratory/RespiratorComponent.cs +++ b/Content.Server/Body/Respiratory/RespiratorComponent.cs @@ -7,6 +7,7 @@ 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; using Content.Shared.Alert; using Content.Shared.Atmos; @@ -238,20 +239,21 @@ namespace Content.Server.Body.Respiratory /// private void ProcessThermalRegulation(float frameTime) { + var temperatureSystem = EntitySystem.Get(); if (!Owner.TryGetComponent(out TemperatureComponent? temperatureComponent)) return; - temperatureComponent.ReceiveHeat(MetabolismHeat); - temperatureComponent.RemoveHeat(RadiatedHeat); + temperatureSystem.ReceiveHeat(Owner.Uid, MetabolismHeat, temperatureComponent); + temperatureSystem.RemoveHeat(Owner.Uid, RadiatedHeat, temperatureComponent); // implicit heat regulation var tempDiff = Math.Abs(temperatureComponent.CurrentTemperature - NormalBodyTemperature); var targetHeat = tempDiff * temperatureComponent.HeatCapacity; if (temperatureComponent.CurrentTemperature > NormalBodyTemperature) { - temperatureComponent.RemoveHeat(Math.Min(targetHeat, ImplicitHeatRegulation)); + temperatureSystem.RemoveHeat(Owner.Uid, Math.Min(targetHeat, ImplicitHeatRegulation), temperatureComponent); } else { - temperatureComponent.ReceiveHeat(Math.Min(targetHeat, ImplicitHeatRegulation)); + temperatureSystem.ReceiveHeat(Owner.Uid, Math.Min(targetHeat, ImplicitHeatRegulation), temperatureComponent); } // recalc difference and target heat @@ -287,7 +289,7 @@ namespace Content.Server.Body.Respiratory // creadth: sweating does not help in airless environment if (EntitySystem.Get().GetTileMixture(Owner.Transform.Coordinates) is not {}) { - temperatureComponent.RemoveHeat(Math.Min(targetHeat, SweatHeatRegulation)); + temperatureSystem.RemoveHeat(Owner.Uid, Math.Min(targetHeat, SweatHeatRegulation), temperatureComponent); } } else @@ -299,7 +301,7 @@ namespace Content.Server.Body.Respiratory _isShivering = true; } - temperatureComponent.ReceiveHeat(Math.Min(targetHeat, ShiveringHeatRegulation)); + temperatureSystem.ReceiveHeat(Owner.Uid, Math.Min(targetHeat, ShiveringHeatRegulation), temperatureComponent); } } diff --git a/Content.Server/Temperature/Components/TemperatureComponent.cs b/Content.Server/Temperature/Components/TemperatureComponent.cs index 653d6062d8..f74242c7ea 100644 --- a/Content.Server/Temperature/Components/TemperatureComponent.cs +++ b/Content.Server/Temperature/Components/TemperatureComponent.cs @@ -1,14 +1,9 @@ -using System; -using Content.Server.Alert; -using Content.Shared.Alert; using Content.Shared.Atmos; using Content.Shared.Damage; using Robust.Shared.GameObjects; using Robust.Shared.Physics; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.ViewVariables; -using Robust.Shared.IoC; -using Robust.Shared.Prototypes; namespace Content.Server.Temperature.Components { @@ -57,82 +52,5 @@ namespace Content.Server.Temperature.Components [DataField("heatDamage", required: true)] [ViewVariables(VVAccess.ReadWrite)] public DamageSpecifier HeatDamage = default!; - - public void Update() - { - - if (Owner.TryGetComponent(out ServerAlertsComponent? status)) - { - switch (CurrentTemperature) - { - // Cold strong. - case <= 260: - status.ShowAlert(AlertType.Cold, 3); - break; - - // Cold mild. - case <= 280 and > 260: - status.ShowAlert(AlertType.Cold, 2); - break; - - // Cold weak. - case <= 292 and > 280: - status.ShowAlert(AlertType.Cold, 1); - break; - - // Safe. - case <= 327 and > 292: - status.ClearAlertCategory(AlertCategory.Temperature); - break; - - // Heat weak. - case <= 335 and > 327: - status.ShowAlert(AlertType.Hot, 1); - break; - - // Heat mild. - case <= 345 and > 335: - status.ShowAlert(AlertType.Hot, 2); - break; - - // Heat strong. - case > 345: - status.ShowAlert(AlertType.Hot, 3); - break; - } - } - - if (!Owner.HasComponent()) return; - - if (CurrentTemperature >= _heatDamageThreshold) - { - int tempDamage = (int) Math.Floor((CurrentTemperature - _heatDamageThreshold) * _tempDamageCoefficient); - EntitySystem.Get().TryChangeDamage(Owner.Uid, HeatDamage * tempDamage); - } - else if (CurrentTemperature <= _coldDamageThreshold) - { - int tempDamage = (int) Math.Floor((_coldDamageThreshold - CurrentTemperature) * _tempDamageCoefficient); - EntitySystem.Get().TryChangeDamage(Owner.Uid, ColdDamage * tempDamage); - } - } - - /// - /// Forcefully give heat to this component - /// - /// - public void ReceiveHeat(float heatAmount) - { - CurrentTemperature += heatAmount / HeatCapacity; - } - - /// - /// Forcefully remove heat from this component - /// - /// - public void RemoveHeat(float heatAmount) - { - CurrentTemperature -= heatAmount / HeatCapacity; - } - } } diff --git a/Content.Server/Temperature/Systems/TemperatureSystem.cs b/Content.Server/Temperature/Systems/TemperatureSystem.cs new file mode 100644 index 0000000000..73292831cc --- /dev/null +++ b/Content.Server/Temperature/Systems/TemperatureSystem.cs @@ -0,0 +1,140 @@ +using System; +using Content.Server.Alert; +using Content.Server.Atmos.EntitySystems; +using Content.Server.Temperature.Components; +using Content.Shared.Alert; +using Content.Shared.Damage; +using Robust.Shared.GameObjects; +using Robust.Shared.IoC; + +namespace Content.Server.Temperature.Systems +{ + public class TemperatureSystem : EntitySystem + { + [Dependency] private readonly DamageableSystem _damageableSystem = default!; + [Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!; + + public override void Initialize() + { + SubscribeLocalEvent(ChangeDamage); + SubscribeLocalEvent(OnAtmosExposedUpdate); + SubscribeLocalEvent(ServerAlert); + } + + public void ForceChangeTemperature(EntityUid uid, float temp, TemperatureComponent? temperature = null) + { + if (Resolve(uid, ref temperature)) + { + float lastTemp = temperature.CurrentTemperature; + float delta = temperature.CurrentTemperature - temp; + temperature.CurrentTemperature = temp; + RaiseLocalEvent(uid, new OnTemperatureChangeEvent(temperature.CurrentTemperature, lastTemp, delta)); + } + } + + public void ReceiveHeat(EntityUid uid, float heatAmount, TemperatureComponent? temperature = null) + { + if (Resolve(uid, ref temperature)) + { + float lastTemp = temperature.CurrentTemperature; + temperature.CurrentTemperature += heatAmount / temperature.HeatCapacity; + float delta = temperature.CurrentTemperature - lastTemp; + + RaiseLocalEvent(uid, new OnTemperatureChangeEvent(temperature.CurrentTemperature, lastTemp, delta)); + } + } + + public void RemoveHeat(EntityUid uid, float heatAmount, TemperatureComponent? temperature = null) + { + if (Resolve(uid, ref temperature)) + { + float lastTemp = temperature.CurrentTemperature; + temperature.CurrentTemperature -= heatAmount / temperature.HeatCapacity; + float delta = temperature.CurrentTemperature - lastTemp; + + RaiseLocalEvent(uid, new OnTemperatureChangeEvent(temperature.CurrentTemperature, lastTemp, delta)); + } + } + + private void OnAtmosExposedUpdate(EntityUid uid, TemperatureComponent temperature, ref AtmosExposedUpdateEvent args) + { + var temperatureDelta = args.GasMixture.Temperature - temperature.CurrentTemperature; + var tileHeatCapacity = _atmosphereSystem.GetHeatCapacity(args.GasMixture); + var heat = temperatureDelta * (tileHeatCapacity * temperature.HeatCapacity / (tileHeatCapacity + temperature.HeatCapacity)); + ReceiveHeat(uid, heat, temperature); + } + + private void ServerAlert(EntityUid uid, ServerAlertsComponent status, OnTemperatureChangeEvent args) + { + switch (args.CurrentTemperature) + { + // Cold strong. + case <= 260: + status.ShowAlert(AlertType.Cold, 3); + break; + + // Cold mild. + case <= 280 and > 260: + status.ShowAlert(AlertType.Cold, 2); + break; + + // Cold weak. + case <= 292 and > 280: + status.ShowAlert(AlertType.Cold, 1); + break; + + // Safe. + case <= 327 and > 292: + status.ClearAlertCategory(AlertCategory.Temperature); + break; + + // Heat weak. + case <= 335 and > 327: + status.ShowAlert(AlertType.Hot, 1); + break; + + // Heat mild. + case <= 345 and > 335: + status.ShowAlert(AlertType.Hot, 2); + break; + + // Heat strong. + case > 345: + status.ShowAlert(AlertType.Hot, 3); + break; + } + } + + private void ChangeDamage(EntityUid uid, TemperatureComponent temperature, OnTemperatureChangeEvent args) + { + if (!EntityManager.TryGetComponent(uid, out var damage)) + return; + + if (args.CurrentTemperature >= temperature.HeatDamageThreshold) + { + int tempDamage = (int) Math.Floor((args.CurrentTemperature - temperature.HeatDamageThreshold) * temperature.TempDamageCoefficient); + _damageableSystem.TryChangeDamage(uid, temperature.HeatDamage * tempDamage); + } + else if (args.CurrentTemperature <= temperature.ColdDamageThreshold) + { + int tempDamage = (int) Math.Floor((temperature.ColdDamageThreshold - args.CurrentTemperature) * temperature.TempDamageCoefficient); + _damageableSystem.TryChangeDamage(uid, temperature.ColdDamage * tempDamage); + } + + } + } + + public class OnTemperatureChangeEvent : EntityEventArgs + { + public float CurrentTemperature { get; } + public float LastTemperature { get; } + public float TemperatureDelta { get; } + + public OnTemperatureChangeEvent(float current, float last, float delta) + { + CurrentTemperature = current; + LastTemperature = last; + TemperatureDelta = delta; + } + } +}