diff --git a/Content.Client/IgnoredComponents.cs b/Content.Client/IgnoredComponents.cs index 6823e56a43..101ce6c852 100644 --- a/Content.Client/IgnoredComponents.cs +++ b/Content.Client/IgnoredComponents.cs @@ -239,7 +239,8 @@ namespace Content.Client "Recyclable", "SecretStash", "Toilet", - "ClusterFlash" + "ClusterFlash", + "GasGenerator" }; } } diff --git a/Content.Server/GameObjects/Components/Atmos/Piping/GasCanisterPortComponent.cs b/Content.Server/GameObjects/Components/Atmos/Piping/GasCanisterPortComponent.cs index cdc701d36d..a5fbc16b0c 100644 --- a/Content.Server/GameObjects/Components/Atmos/Piping/GasCanisterPortComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/Piping/GasCanisterPortComponent.cs @@ -83,13 +83,13 @@ namespace Content.Server.GameObjects.Components.Atmos.Piping { if (!Owner.TryGetComponent(out var container)) { - Logger.Error($"{typeof(GasCanisterPortComponent)} on {Owner?.Prototype?.ID}, Uid {Owner?.Uid} did not have a {nameof(NodeContainerComponent)}."); + Logger.Error($"{nameof(GasCanisterPortComponent)} on {Owner?.Prototype?.ID}, Uid {Owner?.Uid} did not have a {nameof(NodeContainerComponent)}."); return; } _gasPort = container.Nodes.OfType().FirstOrDefault(); if (_gasPort == null) { - Logger.Error($"{typeof(GasCanisterPortComponent)} on {Owner?.Prototype?.ID}, Uid {Owner?.Uid} could not find compatible {nameof(PipeNode)}s on its {nameof(NodeContainerComponent)}."); + Logger.Error($"{nameof(GasCanisterPortComponent)} on {Owner?.Prototype?.ID}, Uid {Owner?.Uid} could not find compatible {nameof(PipeNode)}s on its {nameof(NodeContainerComponent)}."); return; } } diff --git a/Content.Server/GameObjects/Components/Atmos/Piping/GasFilterComponent.cs b/Content.Server/GameObjects/Components/Atmos/Piping/GasFilterComponent.cs index 8a6cd18f1d..461647fd43 100644 --- a/Content.Server/GameObjects/Components/Atmos/Piping/GasFilterComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/Piping/GasFilterComponent.cs @@ -171,7 +171,7 @@ namespace Content.Server.GameObjects.Components.Atmos.Piping.Filters if (_inletPipe == null || _filterOutletPipe == null || _outletPipe == null) { - Logger.Error($"{typeof(GasFilterComponent)} on {Owner?.Prototype?.ID}, Uid {Owner?.Uid} could not find compatible {nameof(PipeNode)}s on its {nameof(NodeContainerComponent)}."); + Logger.Error($"{nameof(GasFilterComponent)} on {Owner?.Prototype?.ID}, Uid {Owner?.Uid} could not find compatible {nameof(PipeNode)}s on its {nameof(NodeContainerComponent)}."); return; } } diff --git a/Content.Server/GameObjects/Components/Atmos/Piping/GasGeneratorComponent.cs b/Content.Server/GameObjects/Components/Atmos/Piping/GasGeneratorComponent.cs new file mode 100644 index 0000000000..5a37d7a669 --- /dev/null +++ b/Content.Server/GameObjects/Components/Atmos/Piping/GasGeneratorComponent.cs @@ -0,0 +1,105 @@ +#nullable enable +using Content.Server.GameObjects.Components.NodeContainer; +using Content.Server.GameObjects.Components.NodeContainer.Nodes; +using Content.Shared.Atmos; +using Robust.Shared.GameObjects; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Log; +using Robust.Shared.Serialization; +using Robust.Shared.ViewVariables; +using System.Linq; + +namespace Content.Server.GameObjects.Components.Atmos.Piping +{ + /// + /// Generates gas in the attached pipe. + /// + [RegisterComponent] + public class GasGeneratorComponent : Component + { + public override string Name => "GasGenerator"; + + /// + /// If the generator is producing gas. + /// + [ViewVariables(VVAccess.ReadWrite)] + public bool GeneratorEnabled { get; set; } + + /// + /// What gas is being generated. + /// + [ViewVariables(VVAccess.ReadWrite)] + public Gas GeneratedGas { get; set; } + + /// + /// Molar rate of gas generation. + /// + [ViewVariables(VVAccess.ReadWrite)] + public float GasGenerationRate { get; set; } + + /// + /// The pipe pressure above which the generator stops producing gas. + /// + [ViewVariables(VVAccess.ReadWrite)] + public float GeneratorPressureCap { get; set; } + + /// + /// The pipe to which generated gas is added. + /// + [ViewVariables] + private PipeNode? Pipe { get; set; } + + public override void ExposeData(ObjectSerializer serializer) + { + base.ExposeData(serializer); + serializer.DataField(this, x => x.GeneratorEnabled, "generatorEnabled", true); + serializer.DataField(this, x => x.GeneratedGas, "generatedGas", Gas.Oxygen); + serializer.DataField(this, x => x.GasGenerationRate, "gasGenerationRate", 10); + serializer.DataField(this, x => x.GeneratorPressureCap, "generatorPressureCap", 10); + } + + public override void Initialize() + { + base.Initialize(); + Owner.EnsureComponentWarn(); + SetPipes(); + } + + public override void HandleMessage(ComponentMessage message, IComponent? component) + { + base.HandleMessage(message, component); + switch (message) + { + case PipeNetUpdateMessage: + Update(); + break; + } + } + + private void Update() + { + if (!GeneratorEnabled) + return; + + if (Pipe == null || Pipe.Air.Pressure > GeneratorPressureCap) + return; + + Pipe.Air.AdjustMoles(GeneratedGas, GasGenerationRate); + } + + private void SetPipes() + { + if (!Owner.TryGetComponent(out var container)) + { + Logger.Error($"{nameof(GasGeneratorComponent)} on {Owner?.Prototype?.ID}, Uid {Owner?.Uid} did not have a {nameof(NodeContainerComponent)}."); + return; + } + Pipe = container.Nodes.OfType().FirstOrDefault(); + if (Pipe == null) + { + Logger.Error($"{nameof(GasGeneratorComponent)} on {Owner?.Prototype?.ID}, Uid {Owner?.Uid} could not find compatible {nameof(PipeNode)}s on its {nameof(NodeContainerComponent)}."); + return; + } + } + } +} diff --git a/Content.Server/GameObjects/Components/Atmos/Piping/Pumps/BasePumpComponent.cs b/Content.Server/GameObjects/Components/Atmos/Piping/Pumps/BasePumpComponent.cs index a4c3d6a8e9..4b7eb31895 100644 --- a/Content.Server/GameObjects/Components/Atmos/Piping/Pumps/BasePumpComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/Piping/Pumps/BasePumpComponent.cs @@ -107,7 +107,7 @@ namespace Content.Server.GameObjects.Components.Atmos.Piping.Pumps if (!Owner.TryGetComponent(out var container)) { - Logger.Error($"{typeof(BasePumpComponent)} on {Owner?.Prototype?.ID}, Uid {Owner?.Uid} did not have a {nameof(NodeContainerComponent)}."); + Logger.Error($"{nameof(BasePumpComponent)} on {Owner?.Prototype?.ID}, Uid {Owner?.Uid} did not have a {nameof(NodeContainerComponent)}."); return; } var pipeNodes = container.Nodes.OfType(); @@ -115,7 +115,7 @@ namespace Content.Server.GameObjects.Components.Atmos.Piping.Pumps _outletPipe = pipeNodes.Where(pipe => pipe.PipeDirection == _initialOutletDirection).FirstOrDefault(); if (_inletPipe == null || _outletPipe == null) { - Logger.Error($"{typeof(BasePumpComponent)} on {Owner?.Prototype?.ID}, Uid {Owner?.Uid} could not find compatible {nameof(PipeNode)}s on its {nameof(NodeContainerComponent)}."); + Logger.Error($"{nameof(BasePumpComponent)} on {Owner?.Prototype?.ID}, Uid {Owner?.Uid} could not find compatible {nameof(PipeNode)}s on its {nameof(NodeContainerComponent)}."); return; } } diff --git a/Content.Server/GameObjects/Components/Atmos/Piping/Scrubbers/BaseSiphonComponent.cs b/Content.Server/GameObjects/Components/Atmos/Piping/Scrubbers/BaseSiphonComponent.cs index fe30881d58..a67e354a4d 100644 --- a/Content.Server/GameObjects/Components/Atmos/Piping/Scrubbers/BaseSiphonComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/Piping/Scrubbers/BaseSiphonComponent.cs @@ -80,13 +80,13 @@ namespace Content.Server.GameObjects.Components.Atmos.Piping.Scrubbers { if (!Owner.TryGetComponent(out var container)) { - Logger.Error($"{typeof(BaseSiphonComponent)} on {Owner?.Prototype?.ID}, Uid {Owner?.Uid} did not have a {nameof(NodeContainerComponent)}."); + Logger.Error($"{nameof(BaseSiphonComponent)} on {Owner?.Prototype?.ID}, Uid {Owner?.Uid} did not have a {nameof(NodeContainerComponent)}."); return; } _scrubberOutlet = container.Nodes.OfType().FirstOrDefault(); if (_scrubberOutlet == null) { - Logger.Error($"{typeof(BaseSiphonComponent)} on {Owner?.Prototype?.ID}, Uid {Owner?.Uid} could not find compatible {nameof(PipeNode)}s on its {nameof(NodeContainerComponent)}."); + Logger.Error($"{nameof(BaseSiphonComponent)} on {Owner?.Prototype?.ID}, Uid {Owner?.Uid} could not find compatible {nameof(PipeNode)}s on its {nameof(NodeContainerComponent)}."); return; } } diff --git a/Content.Server/GameObjects/Components/Atmos/Piping/Vents/BaseVentComponent.cs b/Content.Server/GameObjects/Components/Atmos/Piping/Vents/BaseVentComponent.cs index db4508959b..c9b9e48f86 100644 --- a/Content.Server/GameObjects/Components/Atmos/Piping/Vents/BaseVentComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/Piping/Vents/BaseVentComponent.cs @@ -80,13 +80,13 @@ namespace Content.Server.GameObjects.Components.Atmos.Piping.Vents { if (!Owner.TryGetComponent(out var container)) { - Logger.Error($"{typeof(BaseVentComponent)} on {Owner?.Prototype?.ID}, Uid {Owner?.Uid} did not have a {nameof(NodeContainerComponent)}."); + Logger.Error($"{nameof(BaseVentComponent)} on {Owner?.Prototype?.ID}, Uid {Owner?.Uid} did not have a {nameof(NodeContainerComponent)}."); return; } _ventInlet = container.Nodes.OfType().FirstOrDefault(); if (_ventInlet == null) { - Logger.Error($"{typeof(BaseVentComponent)} on {Owner?.Prototype?.ID}, Uid {Owner?.Uid} could not find compatible {nameof(PipeNode)}s on its {nameof(NodeContainerComponent)}."); + Logger.Error($"{nameof(BaseVentComponent)} on {Owner?.Prototype?.ID}, Uid {Owner?.Uid} could not find compatible {nameof(PipeNode)}s on its {nameof(NodeContainerComponent)}."); return; } } diff --git a/Resources/Prototypes/Entities/Constructible/Ground/gasgenerator.yml b/Resources/Prototypes/Entities/Constructible/Ground/gasgenerator.yml new file mode 100644 index 0000000000..028b736c17 --- /dev/null +++ b/Resources/Prototypes/Entities/Constructible/Ground/gasgenerator.yml @@ -0,0 +1,45 @@ +- type: entity + abstract: true + id: GasGeneratorBase + placement: + mode: SnapgridCenter + components: + - type: Clickable + - type: InteractionOutline + - type: Physics + anchored: true + shapes: + - !type:PhysShapeAabb + bounds: "-0.5,-0.5,0.5,0.5" + layer: + - Impassable + - MobImpassable + - VaultImpassable + - Opaque + mask: + - Impassable + - MobImpassable + - VaultImpassable + - type: SnapGrid + offset: Center + - type: GasGenerator + +- type: entity + parent: GasGeneratorBase + id: GasGenerator + name: gas generator + description: Fabricates gas. + components: + - type: Sprite + netsync: false + sprite: Constructible/Atmos/gasgenerator.rsi + layers: + - sprite: Constructible/Atmos/pipe.rsi + state: pipeFourway + - state: gasGenerator + - type: NodeContainer + nodes: + - !type:PipeNode + nodeGroupID: Pipe + pipeDirection: Fourway + diff --git a/Resources/Textures/Constructible/Atmos/gasgenerator.rsi/gasGenerator.png b/Resources/Textures/Constructible/Atmos/gasgenerator.rsi/gasGenerator.png new file mode 100644 index 0000000000..038cde0c9b Binary files /dev/null and b/Resources/Textures/Constructible/Atmos/gasgenerator.rsi/gasGenerator.png differ diff --git a/Resources/Textures/Constructible/Atmos/gasgenerator.rsi/meta.json b/Resources/Textures/Constructible/Atmos/gasgenerator.rsi/meta.json new file mode 100644 index 0000000000..d202af0146 --- /dev/null +++ b/Resources/Textures/Constructible/Atmos/gasgenerator.rsi/meta.json @@ -0,0 +1,14 @@ +{ + "version":1, + "size":{ + "x":32, + "y":32 + }, + "license":"CC-BY-SA-3.0", + "copyright":"Taken from https://github.com/tgstation/tgstation at commit 57cd1d59ca019dd0e7811ac451f295f818e573da", + "states":[ + { + "name":"gasGenerator" + } + ] +}