2021-06-23 11:35:30 +02:00
using Content.Server.Atmos.EntitySystems ;
2021-06-19 13:25:05 +02:00
using Content.Server.Atmos.Piping.Components ;
2022-08-07 18:49:06 -07:00
using Content.Server.Cargo.Systems ;
2023-06-28 14:28:38 +03:00
using Content.Server.NodeContainer.EntitySystems ;
2021-07-12 10:00:50 +02:00
using Content.Server.NodeContainer.NodeGroups ;
2021-07-04 18:11:52 +02:00
using Content.Server.NodeContainer.Nodes ;
2021-06-19 13:25:05 +02:00
using Content.Shared.Atmos ;
2025-05-02 18:22:29 +10:00
using Content.Shared.Atmos.Components ;
2021-06-19 13:25:05 +02:00
using Content.Shared.Atmos.Piping.Binary.Components ;
2025-05-02 18:22:29 +10:00
using Content.Shared.Atmos.Piping.Unary.Systems ;
2021-11-28 14:56:53 +01:00
using Content.Shared.Database ;
2025-05-02 18:22:29 +10:00
using Content.Shared.NodeContainer ;
using GasCanisterComponent = Content . Shared . Atmos . Piping . Unary . Components . GasCanisterComponent ;
2021-06-19 13:25:05 +02:00
2023-06-15 12:03:20 +00:00
namespace Content.Server.Atmos.Piping.Unary.EntitySystems ;
2025-05-02 18:22:29 +10:00
public sealed class GasCanisterSystem : SharedGasCanisterSystem
2021-06-19 13:25:05 +02:00
{
2023-06-15 12:03:20 +00:00
[Dependency] private readonly AtmosphereSystem _atmos = default ! ;
[Dependency] private readonly SharedAppearanceSystem _appearance = default ! ;
2023-06-28 14:28:38 +03:00
[Dependency] private readonly NodeContainerSystem _nodeContainer = default ! ;
2023-06-15 12:03:20 +00:00
public override void Initialize ( )
2021-06-19 13:25:05 +02:00
{
2023-06-15 12:03:20 +00:00
base . Initialize ( ) ;
SubscribeLocalEvent < GasCanisterComponent , AtmosDeviceUpdateEvent > ( OnCanisterUpdated ) ;
SubscribeLocalEvent < GasCanisterComponent , PriceCalculationEvent > ( CalculateCanisterPrice ) ;
SubscribeLocalEvent < GasCanisterComponent , GasAnalyzerScanEvent > ( OnAnalyzed ) ;
}
2021-11-05 19:19:12 -05:00
2023-06-15 12:03:20 +00:00
/// <summary>
/// Completely dumps the content of the canister into the world.
/// </summary>
public void PurgeContents ( EntityUid uid , GasCanisterComponent ? canister = null , TransformComponent ? transform = null )
{
if ( ! Resolve ( uid , ref canister , ref transform ) )
return ;
2021-11-05 19:19:12 -05:00
2024-03-30 17:17:53 +13:00
var environment = _atmos . GetContainingMixture ( ( uid , transform ) , false , true ) ;
2023-06-15 12:03:20 +00:00
if ( environment is not null )
_atmos . Merge ( environment , canister . Air ) ;
2021-11-05 19:19:12 -05:00
2025-05-02 18:22:29 +10:00
AdminLogger . Add ( LogType . CanisterPurged , LogImpact . Medium , $"Canister {ToPrettyString(uid):canister} purged its contents of {canister.Air:gas} into the environment." ) ;
2023-06-15 12:03:20 +00:00
canister . Air . Clear ( ) ;
}
2021-11-05 19:19:12 -05:00
2025-05-02 18:22:29 +10:00
protected override void DirtyUI ( EntityUid uid , GasCanisterComponent ? canister = null , NodeContainerComponent ? nodeContainer = null )
2023-06-15 12:03:20 +00:00
{
2023-12-16 01:28:27 -07:00
if ( ! Resolve ( uid , ref canister , ref nodeContainer ) )
2023-06-15 12:03:20 +00:00
return ;
2022-09-16 09:06:29 -05:00
2023-06-15 12:03:20 +00:00
var portStatus = false ;
var tankPressure = 0f ;
2023-06-28 14:28:38 +03:00
if ( _nodeContainer . TryGetNode ( nodeContainer , canister . PortName , out PipeNode ? portNode ) & & portNode . NodeGroup ? . Nodes . Count > 1 )
2023-06-15 12:03:20 +00:00
portStatus = true ;
2021-06-19 13:25:05 +02:00
2023-12-16 01:28:27 -07:00
if ( canister . GasTankSlot . Item ! = null )
2021-06-19 13:25:05 +02:00
{
2023-12-16 01:28:27 -07:00
var tank = canister . GasTankSlot . Item . Value ;
2023-06-15 12:03:20 +00:00
var tankComponent = Comp < GasTankComponent > ( tank ) ;
tankPressure = tankComponent . Air . Pressure ;
}
2021-06-19 13:25:05 +02:00
2025-05-02 18:22:29 +10:00
UI . SetUiState ( uid , GasCanisterUiKey . Key ,
new GasCanisterBoundUserInterfaceState ( canister . Air . Pressure , portStatus , tankPressure ) ) ;
2025-01-18 00:51:32 +01:00
}
2023-12-21 18:48:18 -07:00
private void OnCanisterUpdated ( EntityUid uid , GasCanisterComponent canister , ref AtmosDeviceUpdateEvent args )
2023-06-15 12:03:20 +00:00
{
_atmos . React ( canister . Air , canister ) ;
2022-08-07 20:21:56 -03:00
2023-06-15 12:03:20 +00:00
if ( ! TryComp < NodeContainerComponent > ( uid , out var nodeContainer )
| | ! TryComp < AppearanceComponent > ( uid , out var appearance ) )
return ;
2021-11-23 22:08:17 -06:00
2023-06-28 14:28:38 +03:00
if ( ! _nodeContainer . TryGetNode ( nodeContainer , canister . PortName , out PortablePipeNode ? portNode ) )
2023-06-15 12:03:20 +00:00
return ;
2021-06-19 13:25:05 +02:00
2023-06-15 12:03:20 +00:00
if ( portNode . NodeGroup is PipeNet { NodeCount : > 1 } net )
2021-06-19 13:25:05 +02:00
{
2023-06-15 12:03:20 +00:00
MixContainerWithPipeNet ( canister . Air , net . Air ) ;
}
2023-12-21 18:48:18 -07:00
2023-06-15 12:03:20 +00:00
// Release valve is open, release gas.
if ( canister . ReleaseValve )
{
2023-12-16 01:28:27 -07:00
if ( canister . GasTankSlot . Item ! = null )
2021-07-12 10:00:50 +02:00
{
2023-12-16 01:28:27 -07:00
var gasTank = Comp < GasTankComponent > ( canister . GasTankSlot . Item . Value ) ;
2023-06-15 12:03:20 +00:00
_atmos . ReleaseGasTo ( canister . Air , gasTank . Air , canister . ReleasePressure ) ;
2021-07-12 10:00:50 +02:00
}
2023-06-15 12:03:20 +00:00
else
2021-06-23 12:02:28 +02:00
{
2024-03-30 17:17:53 +13:00
var environment = _atmos . GetContainingMixture ( uid , args . Grid , args . Map , false , true ) ;
2023-06-15 12:03:20 +00:00
_atmos . ReleaseGasTo ( canister . Air , environment , canister . ReleasePressure ) ;
2021-06-23 12:02:28 +02:00
}
2023-06-15 12:03:20 +00:00
}
2021-06-23 12:02:28 +02:00
2023-06-15 12:03:20 +00:00
// If last pressure is very close to the current pressure, do nothing.
if ( MathHelper . CloseToPercent ( canister . Air . Pressure , canister . LastPressure ) )
return ;
2021-06-19 13:25:05 +02:00
2023-12-16 01:28:27 -07:00
DirtyUI ( uid , canister , nodeContainer ) ;
2022-02-20 08:15:47 +13:00
2023-06-15 12:03:20 +00:00
canister . LastPressure = canister . Air . Pressure ;
2021-06-19 13:25:05 +02:00
2023-06-15 12:03:20 +00:00
if ( canister . Air . Pressure < 10 )
{
_appearance . SetData ( uid , GasCanisterVisuals . PressureState , 0 , appearance ) ;
2021-06-19 13:25:05 +02:00
}
2023-06-15 12:03:20 +00:00
else if ( canister . Air . Pressure < Atmospherics . OneAtmosphere )
2021-06-19 13:25:05 +02:00
{
2023-06-15 12:03:20 +00:00
_appearance . SetData ( uid , GasCanisterVisuals . PressureState , 1 , appearance ) ;
}
else if ( canister . Air . Pressure < ( 15 * Atmospherics . OneAtmosphere ) )
{
_appearance . SetData ( uid , GasCanisterVisuals . PressureState , 2 , appearance ) ;
2021-06-19 13:25:05 +02:00
}
2023-06-15 12:03:20 +00:00
else
{
_appearance . SetData ( uid , GasCanisterVisuals . PressureState , 3 , appearance ) ;
}
}
2021-06-19 13:25:05 +02:00
2023-06-15 12:03:20 +00:00
/// <summary>
/// Mix air from a gas container into a pipe net.
/// Useful for anything that uses connector ports.
/// </summary>
public void MixContainerWithPipeNet ( GasMixture containerAir , GasMixture pipeNetAir )
{
var buffer = new GasMixture ( pipeNetAir . Volume + containerAir . Volume ) ;
2022-09-08 14:22:14 +00:00
2023-06-15 12:03:20 +00:00
_atmos . Merge ( buffer , pipeNetAir ) ;
_atmos . Merge ( buffer , containerAir ) ;
pipeNetAir . Clear ( ) ;
_atmos . Merge ( pipeNetAir , buffer ) ;
pipeNetAir . Multiply ( pipeNetAir . Volume / buffer . Volume ) ;
containerAir . Clear ( ) ;
_atmos . Merge ( containerAir , buffer ) ;
containerAir . Multiply ( containerAir . Volume / buffer . Volume ) ;
}
private void CalculateCanisterPrice ( EntityUid uid , GasCanisterComponent component , ref PriceCalculationEvent args )
{
args . Price + = _atmos . GetPrice ( component . Air ) ;
}
2022-09-16 09:06:29 -05:00
2023-06-15 12:03:20 +00:00
/// <summary>
/// Returns the gas mixture for the gas analyzer
/// </summary>
2024-04-17 19:42:24 +02:00
private void OnAnalyzed ( EntityUid uid , GasCanisterComponent canisterComponent , GasAnalyzerScanEvent args )
2023-06-15 12:03:20 +00:00
{
2024-04-17 19:42:24 +02:00
args . GasMixtures ? ? = new List < ( string , GasMixture ? ) > ( ) ;
args . GasMixtures . Add ( ( Name ( uid ) , canisterComponent . Air ) ) ;
// if a tank is inserted show it on the analyzer as well
if ( canisterComponent . GasTankSlot . Item ! = null )
{
var tank = canisterComponent . GasTankSlot . Item . Value ;
var tankComponent = Comp < GasTankComponent > ( tank ) ;
args . GasMixtures . Add ( ( Name ( tank ) , tankComponent . Air ) ) ;
}
2023-06-15 12:03:20 +00:00
}
2021-06-19 13:25:05 +02:00
}