Atmos pipe rework (#3833)

* Initial

* Cleanup a bunch of things

* some changes dunno

* RequireAnchored

* a

* stuff

* more work

* Lots of progress

* delete pipe visualizer

* a

* b

* pipenet and pipenode cleanup

* Fixes

* Adds GasValve

* Adds GasMiner

* Fix stuff, maybe?

* More fixes

* Ignored components on the client

* Adds thermomachine behavior, change a bunch of stuff

* Remove Anchored

* some work, but it's shitcode

* significantly more ECS

* ECS AtmosDevices

* Cleanup

* fix appearance

* when the pipe direction is sus

* Gas tanks and canisters

* pipe anchoring and stuff

* coding is my passion

* Unsafe pipes take longer to unanchor

* turns out we're no longer using eris canisters

* Gas canister inserted tank appearance, improvements

* Work on a bunch of appearances

* Scrubber appearance

* Reorganize AtmosphereSystem.Piping into a bunch of different systems

* Appearance for vent/scrubber/pump turns off when leaving atmosphere

* ThermoMachine appearance

* Cleanup gas tanks

* Remove passive gate unused imports

* remove old canister UI functionality

* PipeNode environment air, make everything use AssumeAir instead of merging manually

* a

* Reorganize atmos to follow new structure

* ?????

* Canister UI, restructure client

* Restructure shared

* Fix build tho

* listen, at least the canister UI works entirely...

* fix build : )

* Atmos device prototypes have names and descriptions

* gas canister ui slider doesn't jitter

* trinary prototypes

* sprite for miners

* ignore components

* fix YAML

* Fix port system doing useless thing

* Fix build

* fix thinking moment

* fix build again because

* canister direction

* pipenode is a word

* GasTank Air will throw on invalid states

* fix build....

* Unhardcode volume pump thresholds

* Volume pump and filter take time into account

* Rename Join/Leave atmosphere events to AtmosDeviceEnabled/Disabled Event

* Gas tank node volume is set by initial mixtuer

* I love node container
This commit is contained in:
Vera Aguilera Puerto
2021-06-19 13:25:05 +02:00
committed by GitHub
parent cfc3f2e7fc
commit a2b737d945
250 changed files with 3964 additions and 3163 deletions

View File

@@ -1,8 +1,9 @@
#nullable enable
using System.Collections.Generic;
using System.Linq;
using Content.Client.GameObjects.EntitySystems;
using Content.Client.Atmos.EntitySystems;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Prototypes;
using JetBrains.Annotations;
using Robust.Client.AutoGenerated;
using Robust.Client.Console;

View File

@@ -1,8 +1,9 @@
#nullable enable
using System.Collections.Generic;
using System.Linq;
using Content.Client.GameObjects.EntitySystems;
using Content.Client.Atmos.EntitySystems;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Prototypes;
using JetBrains.Annotations;
using Robust.Client.AutoGenerated;
using Robust.Client.Console;

View File

@@ -1,7 +1,7 @@
using Content.Client.Items.Components;
using Content.Client.Message;
using Content.Client.Stylesheets;
using Content.Shared.GameObjects.Components;
using Content.Shared.Atmos.Components;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.GameObjects;
@@ -9,7 +9,7 @@ using Robust.Shared.Localization;
using Robust.Shared.Timing;
using Robust.Shared.ViewVariables;
namespace Content.Client.GameObjects.Components.Atmos
namespace Content.Client.Atmos.Components
{
[RegisterComponent]
internal class GasAnalyzerComponent : SharedGasAnalyzerComponent, IItemStatus

View File

@@ -1,9 +1,8 @@
#nullable enable
using System;
using System.Collections.Generic;
using Content.Client.Atmos;
using Content.Shared.GameObjects.EntitySystems.Atmos;
using Content.Client.Atmos.Overlays;
using Content.Shared.Atmos;
using Content.Shared.Atmos.EntitySystems;
using Content.Shared.GameTicking;
using JetBrains.Annotations;
using Robust.Client.Graphics;
@@ -11,7 +10,7 @@ using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Maths;
namespace Content.Client.GameObjects.EntitySystems
namespace Content.Client.Atmos.EntitySystems
{
[UsedImplicitly]
internal sealed class AtmosDebugOverlaySystem : SharedAtmosDebugOverlaySystem, IResettingEntitySystem

View File

@@ -1,7 +1,7 @@
using Content.Shared.GameObjects.EntitySystems.Atmos;
using Content.Shared.Atmos.EntitySystems;
using JetBrains.Annotations;
namespace Content.Client.GameObjects.EntitySystems
namespace Content.Client.Atmos.EntitySystems
{
[UsedImplicitly]
public class AtmosphereSystem : SharedAtmosphereSystem

View File

@@ -1,20 +1,19 @@
#nullable enable
using System;
using System.Collections.Generic;
using Content.Client.Atmos;
using Content.Client.Atmos.Overlays;
using Content.Shared.Atmos;
using Content.Shared.GameObjects.EntitySystems.Atmos;
using Content.Shared.Atmos.EntitySystems;
using JetBrains.Annotations;
using Robust.Client.Graphics;
using Robust.Client.ResourceManagement;
using Robust.Client.Utility;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Utility;
namespace Content.Client.GameObjects.EntitySystems
namespace Content.Client.Atmos.EntitySystems
{
[UsedImplicitly]
internal sealed class GasTileOverlaySystem : SharedGasTileOverlaySystem

View File

@@ -1,15 +1,14 @@
using Content.Client.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.Atmos;
using Content.Client.Atmos.EntitySystems;
using Content.Shared.Atmos;
using Content.Shared.Atmos.EntitySystems;
using Robust.Client.Graphics;
using Robust.Shared.Enums;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Enums;
using System;
namespace Content.Client.Atmos
namespace Content.Client.Atmos.Overlays
{
public class AtmosDebugOverlay : Overlay
{

View File

@@ -1,12 +1,12 @@
using Content.Client.GameObjects.EntitySystems;
using Robust.Shared.Enums;
using Content.Client.Atmos.EntitySystems;
using Robust.Client.Graphics;
using Robust.Shared.Enums;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Maths;
namespace Content.Client.Atmos
namespace Content.Client.Atmos.Overlays
{
public class GasTileOverlay : Overlay
{

View File

@@ -0,0 +1,39 @@
using System;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Client.Atmos.Piping
{
[UsedImplicitly]
public abstract class EnabledAtmosDeviceVisualizer : AppearanceVisualizer
{
[DataField("enabledState")]
private string _enabledState = string.Empty;
protected abstract object LayerMap { get; }
protected abstract Enum DataKey { get; }
public override void InitializeEntity(IEntity entity)
{
base.InitializeEntity(entity);
if (!entity.TryGetComponent(out ISpriteComponent? sprite))
return;
sprite.LayerMapSet(LayerMap, sprite.AddLayerState(_enabledState));
sprite.LayerSetVisible(LayerMap, false);
}
public override void OnChangeData(AppearanceComponent component)
{
base.OnChangeData(component);
if (!component.Owner.TryGetComponent(out ISpriteComponent? sprite))
return;
if(component.TryGetData(DataKey, out bool enabled))
sprite.LayerSetVisible(LayerMap, enabled);
}
}
}

View File

@@ -0,0 +1,18 @@
using System;
using Content.Shared.Atmos.Piping;
using JetBrains.Annotations;
namespace Content.Client.Atmos.Piping
{
[UsedImplicitly]
public class OutletInjectorVisualizer : EnabledAtmosDeviceVisualizer
{
protected override object LayerMap => Layers.Enabled;
protected override Enum DataKey => OutletInjectorVisuals.Enabled;
enum Layers
{
Enabled,
}
}
}

View File

@@ -0,0 +1,18 @@
using System;
using Content.Shared.Atmos.Piping;
using JetBrains.Annotations;
namespace Content.Client.Atmos.Piping
{
[UsedImplicitly]
public class PassiveVentVisualizer : EnabledAtmosDeviceVisualizer
{
protected override object LayerMap => Layers.Enabled;
protected override Enum DataKey => PassiveVentVisuals.Enabled;
enum Layers
{
Enabled,
}
}
}

View File

@@ -1,6 +1,6 @@
#nullable enable
using System;
using Content.Shared.GameObjects.Components.Atmos;
using Content.Shared.Atmos;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
@@ -10,9 +10,8 @@ using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using YamlDotNet.RepresentationModel;
namespace Content.Client.GameObjects.Components.Atmos.Piping
namespace Content.Client.Atmos.Piping
{
[UsedImplicitly]
public class PipeConnectorVisualizer : AppearanceVisualizer, ISerializationHooks
@@ -33,7 +32,7 @@ namespace Content.Client.GameObjects.Components.Atmos.Piping
if (resourceCache.TryGetResource(rsiString, out RSIResource? rsi))
_connectorRsi = rsi.RSI;
else
Logger.Error($"{nameof(PipeVisualizer)} could not load to load RSI {rsiString}.");
Logger.Error($"{nameof(PipeConnectorVisualizer)} could not load to load RSI {rsiString}.");
}
public override void InitializeEntity(IEntity entity)

View File

@@ -0,0 +1,18 @@
using System;
using Content.Shared.Atmos.Piping;
using JetBrains.Annotations;
namespace Content.Client.Atmos.Piping
{
[UsedImplicitly]
public class PressurePumpVisualizer : EnabledAtmosDeviceVisualizer
{
protected override object LayerMap => Layers.Enabled;
protected override Enum DataKey => PressurePumpVisuals.Enabled;
enum Layers
{
Enabled,
}
}
}

View File

@@ -0,0 +1,52 @@
using Content.Shared.Atmos.Piping.Unary.Visuals;
using Content.Shared.Atmos.Visuals;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
namespace Content.Client.Atmos.Piping
{
[UsedImplicitly]
public class ScrubberVisualizer : AppearanceVisualizer
{
private string _offState = "scrub_off";
private string _scrubState = "scrub_on";
private string _siphonState = "scrub_purge";
private string _weldedState = "scrub_welded";
private string _wideState = "scrub_wide";
public override void OnChangeData(AppearanceComponent component)
{
base.OnChangeData(component);
if (!component.Owner.TryGetComponent(out ISpriteComponent? sprite))
return;
if (!component.TryGetData(ScrubberVisuals.State, out ScrubberState state))
return;
switch (state)
{
case ScrubberState.Off:
sprite.LayerSetState(ScrubberVisualLayers.Scrubber, _offState);
break;
case ScrubberState.Scrub:
sprite.LayerSetState(ScrubberVisualLayers.Scrubber, _scrubState);
break;
case ScrubberState.Siphon:
sprite.LayerSetState(ScrubberVisualLayers.Scrubber, _siphonState);
break;
case ScrubberState.Welded:
sprite.LayerSetState(ScrubberVisualLayers.Scrubber, _weldedState);
break;
case ScrubberState.WideScrub:
sprite.LayerSetState(ScrubberVisualLayers.Scrubber, _wideState);
break;
}
}
}
public enum ScrubberVisualLayers
{
Scrubber,
}
}

View File

@@ -0,0 +1,18 @@
using System;
using Content.Shared.Atmos.Piping;
using JetBrains.Annotations;
namespace Content.Client.Atmos.Piping
{
[UsedImplicitly]
public class ThermoMachineVisualizer : EnabledAtmosDeviceVisualizer
{
protected override object LayerMap => Layers.Enabled;
protected override Enum DataKey => ThermoMachineVisuals.Enabled;
enum Layers
{
Enabled,
}
}
}

View File

@@ -0,0 +1,47 @@
using Content.Shared.Atmos.Visuals;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
namespace Content.Client.Atmos.Piping
{
[UsedImplicitly]
public class VentPumpVisualizer : AppearanceVisualizer
{
private string _offState = "vent_off";
private string _inState = "vent_in";
private string _outState = "vent_out";
private string _weldedState = "vent_welded";
public override void OnChangeData(AppearanceComponent component)
{
base.OnChangeData(component);
if (!component.Owner.TryGetComponent(out ISpriteComponent? sprite))
return;
if (!component.TryGetData(VentPumpVisuals.State, out VentPumpState state))
return;
switch (state)
{
case VentPumpState.Off:
sprite.LayerSetState(VentVisualLayers.Vent, _offState);
break;
case VentPumpState.In:
sprite.LayerSetState(VentVisualLayers.Vent, _inState);
break;
case VentPumpState.Out:
sprite.LayerSetState(VentVisualLayers.Vent, _outState);
break;
case VentPumpState.Welded:
sprite.LayerSetState(VentVisualLayers.Vent, _weldedState);
break;
}
}
}
public enum VentVisualLayers
{
Vent,
}
}

View File

@@ -1,8 +1,8 @@
using Robust.Client.GameObjects;
using Robust.Shared.GameObjects;
using static Content.Shared.GameObjects.Components.SharedGasAnalyzerComponent;
using static Content.Shared.Atmos.Components.SharedGasAnalyzerComponent;
namespace Content.Client.GameObjects.Components.Atmos
namespace Content.Client.Atmos.UI
{
public class GasAnalyzerBoundUserInterface : BoundUserInterface
{

View File

@@ -9,9 +9,9 @@ using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Maths;
using static Content.Shared.GameObjects.Components.SharedGasAnalyzerComponent;
using static Content.Shared.Atmos.Components.SharedGasAnalyzerComponent;
namespace Content.Client.GameObjects.Components.Atmos
namespace Content.Client.Atmos.UI
{
public class GasAnalyzerWindow : BaseWindow
{

View File

@@ -0,0 +1,86 @@
using Content.Shared.Atmos.Piping.Binary.Components;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Shared.GameObjects;
namespace Content.Client.Atmos.UI
{
/// <summary>
/// Initializes a <see cref="GasCanisterWindow"/> and updates it when new server messages are received.
/// </summary>
[UsedImplicitly]
public class GasCanisterBoundUserInterface : BoundUserInterface
{
private GasCanisterWindow? _window;
public GasCanisterBoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey)
{
}
protected override void Open()
{
base.Open();
_window = new GasCanisterWindow();
if(State != null)
UpdateState(State);
_window.OpenCentered();
_window.OnClose += Close;
_window.ReleaseValveCloseButtonPressed += OnReleaseValveClosePressed;
_window.ReleaseValveOpenButtonPressed += OnReleaseValveOpenPressed;
_window.ReleasePressureSliderChanged += OnReleasePressurePressed;
_window.TankEjectButtonPressed += OnTankEjectPressed;
}
private void OnTankEjectPressed()
{
SendMessage(new GasCanisterHoldingTankEjectMessage());
}
private void OnReleasePressurePressed(float value)
{
SendMessage(new GasCanisterChangeReleasePressureMessage(value));
}
private void OnReleaseValveOpenPressed()
{
SendMessage(new GasCanisterChangeReleaseValveMessage(true));
}
private void OnReleaseValveClosePressed()
{
SendMessage(new GasCanisterChangeReleaseValveMessage(false));
}
/// <summary>
/// Update the UI state based on server-sent info
/// </summary>
/// <param name="state"></param>
protected override void UpdateState(BoundUserInterfaceState state)
{
base.UpdateState(state);
if (_window == null || state is not GasCanisterBoundUserInterfaceState cast)
return;
_window.SetCanisterLabel(cast.CanisterLabel);
_window.SetCanisterPressure(cast.CanisterPressure);
_window.SetPortStatus(cast.PortStatus);
_window.SetTankLabel(cast.TankLabel);
_window.SetTankPressure(cast.TankPressure);
_window.SetReleasePressureRange(cast.ReleasePressureMin, cast.ReleasePressureMax);
_window.SetReleasePressure(cast.ReleasePressure);
_window.SetReleaseValve(cast.ReleaseValve);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (!disposing) return;
_window?.Dispose();
}
}
}

View File

@@ -0,0 +1,52 @@
<SS14Window xmlns="https://spacestation14.io"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:Content.Client.Stylesheets"
MinSize="480 400" Title="Canister">
<VBoxContainer Margin="5 5 5 5" SeparationOverride="10">
<VBoxContainer VerticalExpand="True">
<Label Text="{Loc comp-gas-canister-ui-canister-status}" FontColorOverride="{x:Static s:StyleNano.NanoGold}" StyleClasses="LabelBig"/>
<HBoxContainer>
<Label Text="{Loc comp-gas-canister-ui-canister-pressure}"/>
<Label Name="CanisterPressureLabel" Align="Center" HorizontalExpand="True"/>
</HBoxContainer>
<HBoxContainer>
<Label Text="{Loc comp-gas-canister-ui-port-status}"/>
<Label Name="PortStatusLabel" Align="Center" HorizontalExpand="True"/>
</HBoxContainer>
</VBoxContainer>
<VBoxContainer VerticalExpand="True">
<Label Text="{Loc comp-gas-canister-ui-holding-tank-status}" FontColorOverride="{x:Static s:StyleNano.NanoGold}" StyleClasses="LabelBig"/>
<HBoxContainer>
<Label Text="{Loc comp-gas-canister-ui-holding-tank-label}"/>
<Label Name="TankLabelLabel" Text="{Loc comp-gas-canister-ui-holding-tank-label-empty}" Align="Center" HorizontalExpand="True"/>
<Button Name="TankEjectButton" Text="{Loc comp-gas-canister-ui-holding-tank-eject}"/>
</HBoxContainer>
<HBoxContainer>
<Label Text="{Loc comp-gas-canister-ui-holding-tank-pressure}"/>
<Label Name="TankPressureLabel" Align="Center" HorizontalExpand="True"/>
</HBoxContainer>
</VBoxContainer>
<VBoxContainer VerticalExpand="True">
<Label Text="{Loc comp-gas-canister-ui-release-valve-status}" FontColorOverride="{x:Static s:StyleNano.NanoGold}" StyleClasses="LabelBig"/>
<HBoxContainer>
<VBoxContainer>
<Label Text="{Loc comp-gas-canister-ui-release-pressure}"/>
<Control VerticalExpand="True"/>
</VBoxContainer>
<VBoxContainer HorizontalExpand="True" Margin="15 0 0 15" SeparationOverride="5">
<Slider Name="ReleasePressureSlider" HorizontalExpand="True"/>
<Label Name="ReleasePressureLabel" Align="Center" HorizontalExpand="True"/>
</VBoxContainer>
</HBoxContainer>
<HBoxContainer>
<Label Text="{Loc comp-gas-canister-ui-release-valve}"/>
<Control HorizontalExpand="True"/>
<Button Name="ReleaseValveOpenButton" Text="{Loc comp-gas-canister-ui-release-valve-open}" ToggleMode="True"/>
<Button Name="ReleaseValveCloseButton" Text="{Loc comp-gas-canister-ui-release-valve-close}" ToggleMode="True"/>
<Control HorizontalExpand="True"/>
</HBoxContainer>
</VBoxContainer>
</VBoxContainer>
</SS14Window>

View File

@@ -0,0 +1,98 @@
using System;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Localization;
namespace Content.Client.Atmos.UI
{
/// <summary>
/// Client-side UI used to control a canister.
/// </summary>
[GenerateTypedNameReferences]
public partial class GasCanisterWindow : SS14Window
{
private readonly ButtonGroup _buttonGroup = new();
public event Action? TankEjectButtonPressed;
public event Action<float>? ReleasePressureSliderChanged;
public event Action? ReleaseValveCloseButtonPressed;
public event Action? ReleaseValveOpenButtonPressed;
public GasCanisterWindow()
{
RobustXamlLoader.Load(this);
ReleaseValveCloseButton.Group = _buttonGroup;
ReleaseValveOpenButton.Group = _buttonGroup;
ReleaseValveCloseButton.OnPressed += _ => ReleaseValveCloseButtonPressed?.Invoke();
ReleaseValveOpenButton.OnPressed += _ => ReleaseValveOpenButtonPressed?.Invoke();
TankEjectButton.OnPressed += _ => TankEjectButtonPressed?.Invoke();
ReleasePressureSlider.OnValueChanged += r => ReleasePressureSliderChanged?.Invoke(r.Value);
}
public void SetCanisterLabel(string label)
{
Title = label;
}
public void SetCanisterPressure(float pressure)
{
CanisterPressureLabel.Text = Loc.GetString("comp-gas-canister-ui-pressure", ("pressure", Math.Round(pressure)));
}
public void SetPortStatus(bool status)
{
if (status)
{
PortStatusLabel.Text = Loc.GetString("comp-gas-canister-ui-port-connected");
}
else
{
PortStatusLabel.Text = Loc.GetString("comp-gas-canister-ui-port-disconnected");
}
}
public void SetTankLabel(string? label)
{
if (label == null)
{
TankEjectButton.Disabled = true;
TankLabelLabel.Text = Loc.GetString("comp-gas-canister-ui-holding-tank-label-empty");
return;
}
TankEjectButton.Disabled = false;
TankLabelLabel.Text = label;
}
public void SetTankPressure(float pressure)
{
TankPressureLabel.Text = Loc.GetString("comp-gas-canister-ui-pressure", ("pressure", Math.Round(pressure)));
}
public void SetReleasePressureRange(float min, float max)
{
ReleasePressureSlider.MinValue = min;
ReleasePressureSlider.MaxValue = max;
}
public void SetReleasePressure(float pressure)
{
if(!ReleasePressureSlider.Grabbed)
ReleasePressureSlider.SetValueWithoutEvent(pressure);
ReleasePressureLabel.Text = Loc.GetString("comp-gas-canister-ui-pressure", ("pressure", Math.Round(pressure)));
}
public void SetReleaseValve(bool valve)
{
if (valve)
ReleaseValveOpenButton.Pressed = true;
else
ReleaseValveCloseButton.Pressed = true;
}
}
}

View File

@@ -1,10 +1,10 @@
using Content.Shared.GameObjects.Components.Atmos;
using Content.Shared.Atmos.Visuals;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Client.GameObjects.Components.Atmos
namespace Content.Client.Atmos.Visualizers
{
[UsedImplicitly]
public class AtmosPlaqueVisualizer : AppearanceVisualizer

View File

@@ -1,10 +1,10 @@
using Content.Shared.GameObjects.Components.Atmos;
using Content.Shared.Atmos.Components;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Client.GameObjects.Components.Atmos
namespace Content.Client.Atmos.Visualizers
{
[UsedImplicitly]
public class FireVisualizer : AppearanceVisualizer

View File

@@ -1,9 +1,9 @@
using Content.Shared.GameObjects.Components.Atmos;
using Content.Shared.Atmos.Components;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Client.GameObjects.Components.Atmos
namespace Content.Client.Atmos.Visualizers
{
[UsedImplicitly]
public class GasAnalyzerVisualizer : AppearanceVisualizer

View File

@@ -0,0 +1,54 @@
using Content.Shared.Atmos.Piping.Binary.Components;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Client.Atmos.Visualizers
{
[UsedImplicitly]
public class GasCanisterVisualizer : AppearanceVisualizer
{
[DataField("pressureStates")]
private readonly string[] _statePressure = {"", "", "", ""};
[DataField("insertedTankState")]
private readonly string _insertedTankState = string.Empty;
public override void InitializeEntity(IEntity entity)
{
base.InitializeEntity(entity);
var sprite = entity.GetComponent<ISpriteComponent>();
sprite.LayerMapSet(Layers.PressureLight, sprite.AddLayerState(_statePressure[0]));
sprite.LayerSetShader(Layers.PressureLight, "unshaded");
sprite.LayerMapSet(Layers.TankInserted, sprite.AddLayerState(_insertedTankState));
sprite.LayerSetVisible(Layers.TankInserted, false);
}
public override void OnChangeData(AppearanceComponent component)
{
base.OnChangeData(component);
if (!component.Owner.TryGetComponent(out ISpriteComponent? sprite))
{
return;
}
// Update the canister lights
if (component.TryGetData(GasCanisterVisuals.PressureState, out int pressureState))
if ((pressureState >= 0) && (pressureState < _statePressure.Length))
sprite.LayerSetState(Layers.PressureLight, _statePressure[pressureState]);
if(component.TryGetData(GasCanisterVisuals.TankInserted, out bool inserted))
sprite.LayerSetVisible(Layers.TankInserted, inserted);
}
private enum Layers
{
PressureLight,
TankInserted,
}
}
}

View File

@@ -1,18 +1,17 @@
using Content.Shared.GameObjects.Components.Atmos;
using Content.Shared.Atmos.Piping.Unary.Components;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Client.GameObjects.Components.Atmos
namespace Content.Client.Atmos.Visualizers
{
public class GasCanisterVisualizer : AppearanceVisualizer
[UsedImplicitly]
public class GasPortableVisualizer : AppearanceVisualizer
{
[DataField("stateConnected")]
private string? _stateConnected;
[DataField("pressureStates")]
private string[] _statePressure = new string[] {"", "", "", ""};
public override void InitializeEntity(IEntity entity)
{
base.InitializeEntity(entity);
@@ -23,9 +22,6 @@ namespace Content.Client.GameObjects.Components.Atmos
{
sprite.LayerMapSet(Layers.ConnectedToPort, sprite.AddLayerState(_stateConnected));
sprite.LayerSetVisible(Layers.ConnectedToPort, false);
sprite.LayerMapSet(Layers.PressureLight, sprite.AddLayerState(_stateConnected));
sprite.LayerSetShader(Layers.PressureLight, "unshaded");
}
}
@@ -44,21 +40,15 @@ namespace Content.Client.GameObjects.Components.Atmos
}
// Update the visuals : Is the canister connected to a port or not
if (component.TryGetData(GasCanisterVisuals.ConnectedState, out bool isConnected))
if (component.TryGetData(GasPortableVisuals.ConnectedState, out bool isConnected))
{
sprite.LayerSetVisible(Layers.ConnectedToPort, isConnected);
}
// Update the visuals : Canister lights
if (component.TryGetData(GasCanisterVisuals.PressureState, out int pressureState))
if ((pressureState >= 0) && (pressureState < _statePressure.Length))
sprite.LayerSetState(Layers.PressureLight, _statePressure[pressureState]);
}
enum Layers
private enum Layers
{
ConnectedToPort,
PressureLight
}
}
}

View File

@@ -1,5 +1,4 @@
using System;
using Content.Shared.GameObjects.Components;
using Content.Shared.Vapor;
using JetBrains.Annotations;
using Robust.Client.Animations;
@@ -8,7 +7,7 @@ using Robust.Shared.Maths;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Client.GameObjects.Components.Atmos
namespace Content.Client.Chemistry.Visualizers
{
[UsedImplicitly]
public class VaporVisualizer : AppearanceVisualizer, ISerializationHooks

View File

@@ -1,7 +1,7 @@
using JetBrains.Annotations;
using Content.Client.GameObjects.EntitySystems;
using Content.Shared.Atmos;
using System;
using Content.Client.Atmos.EntitySystems;
using Robust.Shared.Console;
using Robust.Shared.GameObjects;

View File

@@ -1,12 +1,6 @@
// ReSharper disable once RedundantUsingDirective
// Used to warn the player in big red letters in debug mode
using System;
using Content.Client.GameObjects.Components;
using Content.Client.GameObjects.EntitySystems;
using Content.Client.Markers;
using Content.Client.Notifications.Managers;
using Content.Shared.GameObjects.Components;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.SubFloor;
using Robust.Client.GameObjects;
using Robust.Shared.Console;

View File

@@ -1,5 +1,4 @@
#nullable enable
using Content.Client.GameObjects.EntitySystems;
using Content.Shared;
using Content.Shared.CCVar;
using Robust.Shared.Configuration;

View File

@@ -1,5 +1,4 @@
using System.Collections.Generic;
using Content.Client.GameObjects.EntitySystems;
using Content.Shared.Construction;
using Content.Shared.Construction.Prototypes;
using Robust.Client.Graphics;

View File

@@ -143,6 +143,16 @@ namespace Content.Client.Entry
"Barotrauma",
"GasSprayer",
"GasVapor",
"GasVentPump",
"GasPassiveVent",
"GasVentScrubber",
"GasOutletInjector",
"GasMiner",
"GasPressurePump",
"GasVolumePump",
"GasPassiveGate",
"GasValve",
"GasThermoMachine",
"Metabolism",
"AiFactionTag",
"PressureProtection",
@@ -154,7 +164,7 @@ namespace Content.Client.Entry
"VolumePump",
"PressureSiphon",
"PipeHeater",
"PipeNetDevice",
"AtmosDevice",
"SignalReceiver",
"SignalSwitch",
"SignalTransmitter",
@@ -179,6 +189,10 @@ namespace Content.Client.Entry
"ComputerBoard",
"GasCanister",
"GasCanisterPort",
"GasPort",
"GasPortable",
"AtmosUnsafeUnanchor",
"GasMixer",
"Cleanable",
"Configuration",
"PlantHolder",

View File

@@ -1,118 +0,0 @@
using Content.Shared.GameObjects.Components.Atmos;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.Localization;
namespace Content.Client.GameObjects.Components.Atmos
{
/// <summary>
/// Initializes a <see cref="GasCanisterWindow"/> and updates it when new server messages are received.
/// </summary>
[UsedImplicitly]
public class GasCanisterBoundUserInterface : BoundUserInterface
{
private GasCanisterWindow? _window;
public GasCanisterBoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey)
{
}
/// <summary>
/// When a button is pressed, send a network message to the server
/// </summary>
/// <param name="button">Which button has been pressed, as an enum item</param>
private void ButtonPressed(UiButton button)
{
SendMessage(new UiButtonPressedMessage(button));
}
/// <summary>
/// When the release pressure is changed
/// </summary>
/// <param name="value">The pressure value</param>
private void ReleasePressureButtonPressed(float value)
{
SendMessage(new ReleasePressureButtonPressedMessage(value));
}
protected override void Open()
{
base.Open();
_window = new GasCanisterWindow();
_window.Title = Loc.GetString("Gas Canister");
_window.OpenCentered();
_window.OnClose += Close;
// Bind buttons OnPressed event
foreach (ReleasePressureButton btn in _window.ReleasePressureButtons)
{
btn.OnPressed += _ => ReleasePressureButtonPressed(btn.PressureChange);
}
// Bind events
_window.EditLabelBtn.OnPressed += _ => EditLabel();
_window.ToggleValve.OnPressed += _ => ToggleValve();
}
/// <summary>
/// Called when the edit label button is pressed
/// </summary>
private void EditLabel()
{
// Obligatory check because bool isn't nullable
if (_window == null) return;
if (_window.LabelInputEditable)
{
if (_window.LabelInput.Text != _window.OldLabel)
SendMessage(new CanisterLabelChangedMessage(_window.LabelInput.Text));
_window.LabelInputEditable = false;
}
else
{
_window.LabelInputEditable = true;
_window.LabelInput.HasKeyboardFocus();
}
}
private void ToggleValve()
{
SendMessage(new UiButtonPressedMessage(UiButton.ValveToggle));
}
/// <summary>
/// Update the UI state based on server-sent info
/// </summary>
/// <param name="state"></param>
protected override void UpdateState(BoundUserInterfaceState state)
{
base.UpdateState(state);
if (!(state is GasCanisterBoundUserInterfaceState cast))
{
return;
}
_window?.UpdateState(cast);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (!disposing) return;
_window?.Dispose();
}
}
}

View File

@@ -1,167 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using Content.Shared.GameObjects.Components.Atmos;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.Localization;
using Robust.Shared.Maths;
namespace Content.Client.GameObjects.Components.Atmos
{
/// <summary>
/// Client-side UI used to control a <see cref="SharedGasCanisterComponent"/>
/// </summary>
public class GasCanisterWindow : SS14Window
{
private readonly Label _pressure;
private readonly Label _releasePressure;
public readonly CheckButton ToggleValve;
public readonly LineEdit LabelInput;
public readonly Button EditLabelBtn;
public string OldLabel { get; set; } = "";
public bool LabelInputEditable {
get => LabelInput.Editable;
set {
LabelInput.Editable = value;
EditLabelBtn.Text = value ? Loc.GetString("OK") : Loc.GetString("Edit");
}
}
public List<ReleasePressureButton> ReleasePressureButtons { get; private set; }
public GasCanisterWindow()
{
SetSize = MinSize = (450, 200);
HBoxContainer releasePressureButtons;
Contents.AddChild(new VBoxContainer
{
Children =
{
new VBoxContainer
{
Children =
{
new HBoxContainer()
{
Children =
{
new Label(){ Text = Loc.GetString("Label: ") },
(LabelInput = new LineEdit() { Text = Name ?? "", Editable = false,
MinSize = new Vector2(200, 30)}),
(EditLabelBtn = new Button()),
}
},
new HBoxContainer
{
Children =
{
new Label {Text = Loc.GetString("Pressure: ")},
(_pressure = new Label())
}
},
new VBoxContainer()
{
Children =
{
new HBoxContainer()
{
Children =
{
new Label() {Text = Loc.GetString("Release pressure: ")},
(_releasePressure = new Label())
}
},
(releasePressureButtons = new HBoxContainer()
{
Children =
{
new ReleasePressureButton() {PressureChange = -50},
new ReleasePressureButton() {PressureChange = -10},
new ReleasePressureButton() {PressureChange = -1},
new ReleasePressureButton() {PressureChange = -0.1f},
new ReleasePressureButton() {PressureChange = 0.1f},
new ReleasePressureButton() {PressureChange = 1},
new ReleasePressureButton() {PressureChange = 10},
new ReleasePressureButton() {PressureChange = 50}
}
})
}
},
new HBoxContainer()
{
Children =
{
new Label { Text = Loc.GetString("Valve: ") },
(ToggleValve = new CheckButton() { Text = Loc.GetString("Closed") })
}
}
},
}
}
});
// Create the release pressure buttons list
ReleasePressureButtons = new List<ReleasePressureButton>();
foreach (var control in releasePressureButtons.Children.ToList())
{
var btn = (ReleasePressureButton) control;
ReleasePressureButtons.Add(btn);
}
// Reset the editable label
LabelInputEditable = false;
}
/// <summary>
/// Update the UI based on <see cref="GasCanisterBoundUserInterfaceState"/>
/// </summary>
/// <param name="state">The state the UI should reflect</param>
public void UpdateState(GasCanisterBoundUserInterfaceState state)
{
_pressure.Text = Loc.GetString("{0}kPa", state.Volume);
_releasePressure.Text = Loc.GetString("{0}kPa", state.ReleasePressure);
// Update the canister label
OldLabel = LabelInput.Text;
LabelInput.Text = state.Label;
Title = state.Label;
// Reset the editable label
LabelInputEditable = false;
ToggleValve.Pressed = state.ValveOpened;
if (ToggleValve.Pressed)
{
ToggleValve.Text = Loc.GetString("Open");
}
else
{
ToggleValve.Text = Loc.GetString("Closed");
}
}
}
/// <summary>
/// Special button class which stores a numerical value and has it as a label
/// </summary>
public class ReleasePressureButton : Button
{
public float PressureChange
{
get { return _pressureChange; }
set
{
_pressureChange = value;
Text = (value >= 0) ? ("+" + value) : value.ToString();
}
}
private float _pressureChange;
public ReleasePressureButton() : base() {}
}
}

View File

@@ -1,42 +0,0 @@
using Content.Shared.GameObjects.Components.Atmos;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Client.GameObjects.Components.Atmos.Piping
{
[UsedImplicitly]
[DataDefinition]
public class GasFilterVisualizer : AppearanceVisualizer
{
[DataField("filterEnabledState")] private string _filterEnabledState = "gasFilterOn";
public override void InitializeEntity(IEntity entity)
{
base.InitializeEntity(entity);
if (!entity.TryGetComponent<ISpriteComponent>(out var sprite)) return;
sprite.LayerMapReserveBlank(Layer.FilterEnabled);
var filterEnabledLayer = sprite.LayerMapGet(Layer.FilterEnabled);
sprite.LayerSetState(filterEnabledLayer, _filterEnabledState);
}
public override void OnChangeData(AppearanceComponent component)
{
base.OnChangeData(component);
if (!component.Owner.TryGetComponent<ISpriteComponent>(out var sprite)) return;
if (!component.TryGetData(FilterVisuals.VisualState, out FilterVisualState filterVisualState)) return;
var filterEnabledLayer = sprite.LayerMapGet(Layer.FilterEnabled);
sprite.LayerSetVisible(filterEnabledLayer, filterVisualState.Enabled);
}
public enum Layer : byte
{
FilterEnabled,
}
}
}

View File

@@ -1,72 +0,0 @@
#nullable enable
using System;
using Content.Shared.GameObjects.Components.Atmos;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.ResourceManagement;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Client.GameObjects.Components.Atmos.Piping
{
/// <summary>
/// Sets the state of the sprite based on what shape of pipe it is.
/// </summary>
[UsedImplicitly]
[DataDefinition]
public class PipeVisualizer : AppearanceVisualizer, ISerializationHooks
{
[DataField("rsi")] private string _rsiString = "Constructible/Atmos/pipe.rsi";
private RSI? _pipeRSI;
void ISerializationHooks.AfterDeserialization()
{
var rsiPath = SharedSpriteComponent.TextureRoot / _rsiString;
var resourceCache = IoCManager.Resolve<IResourceCache>();
if (resourceCache.TryGetResource(rsiPath, out RSIResource? rsi))
{
_pipeRSI = rsi.RSI;
}
}
public override void InitializeEntity(IEntity entity)
{
base.InitializeEntity(entity);
if (!entity.TryGetComponent<ISpriteComponent>(out var sprite)) return;
sprite.LayerMapReserveBlank(Layer.PipeBase);
var pipeBaseLayer = sprite.LayerMapGet(Layer.PipeBase);
if (_pipeRSI != null)
sprite.LayerSetRSI(pipeBaseLayer, _pipeRSI);
sprite.LayerSetVisible(pipeBaseLayer, true);
}
public override void OnChangeData(AppearanceComponent component)
{
base.OnChangeData(component);
if (!component.Owner.TryGetComponent<ISpriteComponent>(out var sprite)) return;
if (!component.TryGetData(PipeVisuals.VisualState, out PipeVisualState pipeVisualState)) return;
var pipeBase = sprite.LayerMapGet(Layer.PipeBase);
var pipeBaseStateId = GetPipeBaseStateId(pipeVisualState);
sprite.LayerSetState(pipeBase, pipeBaseStateId);
}
private string GetPipeBaseStateId(PipeVisualState pipeVisualState)
{
var stateId = "pipe";
stateId += pipeVisualState.PipeShape.ToString();
return stateId;
}
private enum Layer : byte
{
PipeBase,
}
}
}

View File

@@ -1,42 +0,0 @@
using Content.Shared.GameObjects.Components.Atmos;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Client.GameObjects.Components.Atmos.Piping
{
[UsedImplicitly]
[DataDefinition]
public class PumpVisualizer : AppearanceVisualizer
{
[DataField("pumpEnabledState")] private string _pumpEnabledState = "pumpPressureOn";
public override void InitializeEntity(IEntity entity)
{
base.InitializeEntity(entity);
if (!entity.TryGetComponent(out ISpriteComponent? sprite)) return;
sprite.LayerMapReserveBlank(Layer.PumpEnabled);
var pumpEnabledLayer = sprite.LayerMapGet(Layer.PumpEnabled);
sprite.LayerSetState(pumpEnabledLayer, _pumpEnabledState);
}
public override void OnChangeData(AppearanceComponent component)
{
base.OnChangeData(component);
if (!component.Owner.TryGetComponent(out ISpriteComponent? sprite)) return;
if (!component.TryGetData(PumpVisuals.VisualState, out PumpVisualState pumpVisualState)) return;
var pumpEnabledLayer = sprite.LayerMapGet(Layer.PumpEnabled);
sprite.LayerSetVisible(pumpEnabledLayer, pumpVisualState.PumpEnabled);
}
public enum Layer : byte
{
PumpEnabled,
}
}
}

View File

@@ -1,42 +0,0 @@
using Content.Shared.GameObjects.Components.Atmos;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Client.GameObjects.Components.Atmos.Piping
{
[UsedImplicitly]
[DataDefinition]
public class SiphonVisualizer : AppearanceVisualizer
{
[DataField("siphonOnState")] private string _siphonOnState = "scrubOn";
public override void InitializeEntity(IEntity entity)
{
base.InitializeEntity(entity);
if (!entity.TryGetComponent(out ISpriteComponent? sprite)) return;
sprite.LayerMapReserveBlank(Layer.SiphonEnabled);
var layer = sprite.LayerMapGet(Layer.SiphonEnabled);
sprite.LayerSetState(layer, _siphonOnState);
}
public override void OnChangeData(AppearanceComponent component)
{
base.OnChangeData(component);
if (!component.Owner.TryGetComponent(out ISpriteComponent? sprite)) return;
if (!component.TryGetData(SiphonVisuals.VisualState, out SiphonVisualState siphonVisualState)) return;
var layer = sprite.LayerMapGet(Layer.SiphonEnabled);
sprite.LayerSetVisible(layer, siphonVisualState.SiphonEnabled);
}
private enum Layer : byte
{
SiphonEnabled,
}
}
}

View File

@@ -1,42 +0,0 @@
using Content.Shared.GameObjects.Components.Atmos;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Client.GameObjects.Components.Atmos.Piping
{
[UsedImplicitly]
[DataDefinition]
public class VentVisualizer : AppearanceVisualizer
{
[DataField("ventOnState")] private string _ventOnState = "ventOn";
public override void InitializeEntity(IEntity entity)
{
base.InitializeEntity(entity);
if (!entity.TryGetComponent(out ISpriteComponent? sprite)) return;
sprite.LayerMapReserveBlank(Layer.VentEnabled);
var layer = sprite.LayerMapGet(Layer.VentEnabled);
sprite.LayerSetState(layer, _ventOnState);
}
public override void OnChangeData(AppearanceComponent component)
{
base.OnChangeData(component);
if (!component.Owner.TryGetComponent(out ISpriteComponent? sprite)) return;
if (!component.TryGetData(VentVisuals.VisualState, out VentVisualState ventVisualState)) return;
var layer = sprite.LayerMapGet(Layer.VentEnabled);
sprite.LayerSetVisible(layer, ventVisualState.VentEnabled);
}
private enum Layer : byte
{
VentEnabled,
}
}
}

View File

@@ -1,6 +1,5 @@
#nullable enable
using System.Collections.Generic;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.Ghost;
using Robust.Client.Console;
using Robust.Client.UserInterface;

View File

@@ -1,9 +1,6 @@
using System;
using Content.Client.GameObjects.EntitySystems;
using Content.Client.HUD;
using Content.Client.Markers;
using Content.Client.UserInterface;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.Input;
using Content.Shared.Sandbox;
using Content.Shared.SubFloor;

View File

@@ -1,4 +1,4 @@
using Content.Shared.GameObjects.Components.Atmos.GasTank;
using Content.Shared.Atmos.Components;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Shared.GameObjects;

View File

@@ -1,7 +1,7 @@
using Content.Client.Message;
using Content.Client.Resources;
using Content.Client.Stylesheets;
using Content.Shared.GameObjects.Components.Atmos.GasTank;
using Content.Shared.Atmos.Components;
using Robust.Client.Graphics;
using Robust.Client.ResourceManagement;
using Robust.Client.UserInterface;