From 9df4f599f449f0f82aea5ba0278225ac00dad958 Mon Sep 17 00:00:00 2001 From: Kevin Zheng Date: Sat, 19 Mar 2022 22:10:48 -0700 Subject: [PATCH] Gas analyzers now analyze gases in pipes (#7112) --- Content.Client/Entry/IgnoredComponents.cs | 1 + .../Components/GasAnalyzableComponent.cs | 18 ++++ .../EntitySystems/GasAnalyzableSystem.cs | 88 +++++++++++++++++++ .../en-US/atmos/gas-analyzable-system.ftl | 7 ++ .../Structures/Piping/Atmospherics/pipes.yml | 1 + 5 files changed, 115 insertions(+) create mode 100644 Content.Server/Atmos/Components/GasAnalyzableComponent.cs create mode 100644 Content.Server/Atmos/EntitySystems/GasAnalyzableSystem.cs create mode 100644 Resources/Locale/en-US/atmos/gas-analyzable-system.ftl diff --git a/Content.Client/Entry/IgnoredComponents.cs b/Content.Client/Entry/IgnoredComponents.cs index 9818bf7239..e067f012bd 100644 --- a/Content.Client/Entry/IgnoredComponents.cs +++ b/Content.Client/Entry/IgnoredComponents.cs @@ -198,6 +198,7 @@ namespace Content.Client.Entry "Rehydratable", "Headset", "ComputerBoard", + "GasAnalyzable", "GasCanister", "GasPort", "GasPortable", diff --git a/Content.Server/Atmos/Components/GasAnalyzableComponent.cs b/Content.Server/Atmos/Components/GasAnalyzableComponent.cs new file mode 100644 index 0000000000..ba9f9e92f9 --- /dev/null +++ b/Content.Server/Atmos/Components/GasAnalyzableComponent.cs @@ -0,0 +1,18 @@ +using Content.Server.Atmos.Piping.EntitySystems; +using JetBrains.Annotations; +using Robust.Shared.GameObjects; +using Robust.Shared.Maths; +using Robust.Shared.Serialization.Manager.Attributes; +using Robust.Shared.ViewVariables; + +/** + * GasAnalyzableComponent is a component for anything that can be examined with a gas analyzer. + */ +namespace Content.Server.Atmos.Components +{ + [RegisterComponent] + public sealed class GasAnalyzableComponent : Component + { + // Empty + } +} diff --git a/Content.Server/Atmos/EntitySystems/GasAnalyzableSystem.cs b/Content.Server/Atmos/EntitySystems/GasAnalyzableSystem.cs new file mode 100644 index 0000000000..6c18ea70fc --- /dev/null +++ b/Content.Server/Atmos/EntitySystems/GasAnalyzableSystem.cs @@ -0,0 +1,88 @@ +using Content.Server.Atmos.Components; +using Content.Server.NodeContainer.NodeGroups; +using Content.Server.NodeContainer.Nodes; +using Content.Server.NodeContainer; +using Content.Server.Tools; +using Content.Shared.Atmos.Components; +using Content.Shared.Examine; +using Content.Shared.Temperature; +using Content.Shared.Verbs; +using JetBrains.Annotations; +using Robust.Shared.Utility; +using System.Linq; + +namespace Content.Server.Atmos.EntitySystems +{ + [UsedImplicitly] + public sealed class GasAnalyzableSystem : EntitySystem + { + [Dependency] private readonly ToolSystem _toolSystem = default!; + [Dependency] private readonly ExamineSystemShared _examineSystem = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent>(OnGetExamineVerbs); + } + + private void OnGetExamineVerbs(EntityUid uid, GasAnalyzableComponent component, GetVerbsEvent args) + { + // Must be in details range to try this. + if (_examineSystem.IsInDetailsRange(args.User, args.Target)) + { + var held = args.Using; + var enabled = held != null && EntityManager.HasComponent(held); + var verb = new ExamineVerb + { + Disabled = !enabled, + Message = Loc.GetString("gas-analyzable-system-verb-tooltip"), + Text = Loc.GetString("gas-analyzable-system-verb-name"), + Category = VerbCategory.Examine, + IconTexture = "/Textures/Interface/VerbIcons/examine.svg.192dpi.png", + Act = () => + { + var markup = FormattedMessage.FromMarkup(GeneratePipeMarkup(uid)); + _examineSystem.SendExamineTooltip(args.User, uid, markup, false, false); + } + }; + + args.Verbs.Add(verb); + } + } + + private string GeneratePipeMarkup(EntityUid uid, NodeContainerComponent? nodeContainer = null) + { + if (!Resolve(uid, ref nodeContainer)) + return Loc.GetString("gas-analyzable-system-internal-error-missing-component"); + + List portNames = new List(); + List portData = new List(); + foreach (var node in nodeContainer.Nodes) + { + if (node.Value is not PipeNode pn) + continue; + float pressure = pn.Air.Pressure; + float temp = pn.Air.Temperature; + portNames.Add(node.Key); + portData.Add(Loc.GetString("gas-analyzable-system-statistics", + ("pressure", pressure), + ("tempK", $"{temp:0.#}"), + ("tempC", $"{TemperatureHelpers.KelvinToCelsius(temp):0.#}") + )); + } + + int count = portNames.Count; + if (count == 0) + return Loc.GetString("gas-anlayzable-system-internal-error-no-gas-node"); + else if (count == 1) + // omit names if only one node + return Loc.GetString("gas-analyzable-system-header") + "\n" + portData[0]; + else + { + var outputs = portNames.Zip(portData, ((name, data) => name + ":\n" + data)); + return Loc.GetString("gas-analyzable-system-header") + "\n\n" + String.Join("\n\n", outputs); + } + } + } +} diff --git a/Resources/Locale/en-US/atmos/gas-analyzable-system.ftl b/Resources/Locale/en-US/atmos/gas-analyzable-system.ftl new file mode 100644 index 0000000000..b19405cd2d --- /dev/null +++ b/Resources/Locale/en-US/atmos/gas-analyzable-system.ftl @@ -0,0 +1,7 @@ +gas-analyzable-system-internal-error-missing-component = Your gas analyzer whirrs for a while, then stops. +gas-anlayzable-system-internal-error-no-gas-node = Your gas analyzer reads, "NO GAS FOUND". +gas-analyzable-system-verb-name = Analyze +gas-analyzable-system-verb-tooltip = Analyze Contents +gas-analyzable-system-header = Your gas analyzer shows a list of statistics: +gas-analyzable-system-statistics = Pressure: {PRESSURE($pressure)} + Temperature: {$tempK}K ({$tempC}°C) diff --git a/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/pipes.yml b/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/pipes.yml index 43543b2896..82669de719 100644 --- a/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/pipes.yml +++ b/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/pipes.yml @@ -71,6 +71,7 @@ range: 2 sound: path: /Audio/Ambience/Objects/gas_hiss.ogg + - type: GasAnalyzable #Note: The PipeDirection of the PipeNode should be the south-facing version, because the entity starts at an angle of 0 (south)