2021-12-10 12:23:18 -06:00
using Content.Server.Administration.Logs ;
2022-02-05 23:57:26 +13:00
using Content.Server.Atmos.EntitySystems ;
2021-06-19 13:25:05 +02:00
using Content.Server.Atmos.Piping.Components ;
using Content.Server.Atmos.Piping.Trinary.Components ;
using Content.Server.NodeContainer ;
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 ;
2022-02-08 09:42:07 +13:00
using Content.Shared.Atmos.Piping ;
2021-11-11 16:10:21 -06:00
using Content.Shared.Atmos.Piping.Trinary.Components ;
2022-03-12 16:20:31 -06:00
using Content.Shared.Audio ;
2021-12-10 12:23:18 -06:00
using Content.Shared.Database ;
2021-11-11 16:10:21 -06:00
using Content.Shared.Interaction ;
using Content.Shared.Popups ;
2021-06-19 13:25:05 +02:00
using JetBrains.Annotations ;
2021-11-11 16:10:21 -06:00
using Robust.Server.GameObjects ;
2021-06-19 13:25:05 +02:00
namespace Content.Server.Atmos.Piping.Trinary.EntitySystems
{
[UsedImplicitly]
2022-02-08 09:42:07 +13:00
public sealed class GasMixerSystem : EntitySystem
2021-06-19 13:25:05 +02:00
{
2021-11-11 16:10:21 -06:00
[Dependency] private UserInterfaceSystem _userInterfaceSystem = default ! ;
2021-12-10 12:23:18 -06:00
[Dependency] private AdminLogSystem _adminLogSystem = default ! ;
2022-02-05 23:57:26 +13:00
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default ! ;
2022-03-12 16:20:31 -06:00
[Dependency] private readonly SharedAmbientSoundSystem _ambientSoundSystem = default ! ;
2021-12-10 12:23:18 -06:00
2021-06-19 13:25:05 +02:00
public override void Initialize ( )
{
base . Initialize ( ) ;
2022-02-08 09:42:07 +13:00
SubscribeLocalEvent < GasMixerComponent , ComponentInit > ( OnInit ) ;
2021-06-19 13:25:05 +02:00
SubscribeLocalEvent < GasMixerComponent , AtmosDeviceUpdateEvent > ( OnMixerUpdated ) ;
2021-11-11 16:10:21 -06:00
SubscribeLocalEvent < GasMixerComponent , InteractHandEvent > ( OnMixerInteractHand ) ;
// Bound UI subscriptions
SubscribeLocalEvent < GasMixerComponent , GasMixerChangeOutputPressureMessage > ( OnOutputPressureChangeMessage ) ;
SubscribeLocalEvent < GasMixerComponent , GasMixerChangeNodePercentageMessage > ( OnChangeNodePercentageMessage ) ;
SubscribeLocalEvent < GasMixerComponent , GasMixerToggleStatusMessage > ( OnToggleStatusMessage ) ;
2022-02-10 16:28:11 +13:00
SubscribeLocalEvent < GasMixerComponent , AnchorStateChangedEvent > ( OnAnchorChanged ) ;
}
private void OnAnchorChanged ( EntityUid uid , GasMixerComponent component , ref AnchorStateChangedEvent args )
{
if ( args . Anchored )
return ;
component . Enabled = false ;
DirtyUI ( uid , component ) ;
UpdateAppearance ( uid , component ) ;
_userInterfaceSystem . TryCloseAll ( uid , GasFilterUiKey . Key ) ;
2021-06-19 13:25:05 +02:00
}
2022-02-08 09:42:07 +13:00
private void OnInit ( EntityUid uid , GasMixerComponent component , ComponentInit args )
{
UpdateAppearance ( uid , component ) ;
}
2021-06-19 13:25:05 +02:00
private void OnMixerUpdated ( EntityUid uid , GasMixerComponent mixer , AtmosDeviceUpdateEvent args )
{
// TODO ATMOS: Cache total moles since it's expensive.
if ( ! mixer . Enabled )
2022-03-12 16:20:31 -06:00
{
_ambientSoundSystem . SetAmbience ( mixer . Owner , false ) ;
2021-06-19 13:25:05 +02:00
return ;
2022-03-12 16:20:31 -06:00
}
2021-06-19 13:25:05 +02:00
2021-09-28 13:35:29 +02:00
if ( ! EntityManager . TryGetComponent ( uid , out NodeContainerComponent ? nodeContainer ) )
2021-06-19 13:25:05 +02:00
return ;
if ( ! nodeContainer . TryGetNode ( mixer . InletOneName , out PipeNode ? inletOne )
| | ! nodeContainer . TryGetNode ( mixer . InletTwoName , out PipeNode ? inletTwo )
| | ! nodeContainer . TryGetNode ( mixer . OutletName , out PipeNode ? outlet ) )
2022-03-12 16:20:31 -06:00
{
_ambientSoundSystem . SetAmbience ( mixer . Owner , false ) ;
2021-06-19 13:25:05 +02:00
return ;
2022-03-12 16:20:31 -06:00
}
2021-06-19 13:25:05 +02:00
var outputStartingPressure = outlet . Air . Pressure ;
if ( outputStartingPressure > = mixer . TargetPressure )
return ; // Target reached, no need to mix.
2022-03-12 16:20:31 -06:00
2021-06-19 13:25:05 +02:00
var generalTransfer = ( mixer . TargetPressure - outputStartingPressure ) * outlet . Air . Volume / Atmospherics . R ;
var transferMolesOne = inletOne . Air . Temperature > 0 ? mixer . InletOneConcentration * generalTransfer / inletOne . Air . Temperature : 0f ;
var transferMolesTwo = inletTwo . Air . Temperature > 0 ? mixer . InletTwoConcentration * generalTransfer / inletTwo . Air . Temperature : 0f ;
if ( mixer . InletTwoConcentration < = 0f )
{
if ( inletOne . Air . Temperature < = 0f )
return ;
transferMolesOne = MathF . Min ( transferMolesOne , inletOne . Air . TotalMoles ) ;
transferMolesTwo = 0f ;
}
else if ( mixer . InletOneConcentration < = 0 )
{
if ( inletTwo . Air . Temperature < = 0f )
return ;
transferMolesOne = 0f ;
transferMolesTwo = MathF . Min ( transferMolesTwo , inletTwo . Air . TotalMoles ) ;
}
else
{
if ( inletOne . Air . Temperature < = 0f | | inletTwo . Air . Temperature < = 0f )
return ;
if ( transferMolesOne < = 0 | | transferMolesTwo < = 0 )
2022-03-12 16:20:31 -06:00
{
_ambientSoundSystem . SetAmbience ( mixer . Owner , false ) ;
2021-06-19 13:25:05 +02:00
return ;
2022-03-12 16:20:31 -06:00
}
2021-06-19 13:25:05 +02:00
if ( inletOne . Air . TotalMoles < transferMolesOne | | inletTwo . Air . TotalMoles < transferMolesTwo )
{
var ratio = MathF . Min ( inletOne . Air . TotalMoles / transferMolesOne , inletTwo . Air . TotalMoles / transferMolesTwo ) ;
transferMolesOne * = ratio ;
transferMolesTwo * = ratio ;
}
}
// Actually transfer the gas now.
if ( transferMolesOne > 0f )
{
var removed = inletOne . Air . Remove ( transferMolesOne ) ;
2022-02-05 23:57:26 +13:00
_atmosphereSystem . Merge ( outlet . Air , removed ) ;
2021-06-19 13:25:05 +02:00
}
if ( transferMolesTwo > 0f )
{
var removed = inletTwo . Air . Remove ( transferMolesTwo ) ;
2022-02-05 23:57:26 +13:00
_atmosphereSystem . Merge ( outlet . Air , removed ) ;
2021-06-19 13:25:05 +02:00
}
2022-03-12 16:20:31 -06:00
_ambientSoundSystem . SetAmbience ( mixer . Owner , true ) ;
2021-06-19 13:25:05 +02:00
}
2021-11-11 16:10:21 -06:00
private void OnMixerInteractHand ( EntityUid uid , GasMixerComponent component , InteractHandEvent args )
{
2021-12-08 13:00:43 +01:00
if ( ! EntityManager . TryGetComponent ( args . User , out ActorComponent ? actor ) )
2021-11-11 16:10:21 -06:00
return ;
2021-12-08 13:00:43 +01:00
if ( EntityManager . GetComponent < TransformComponent > ( component . Owner ) . Anchored )
2021-11-11 16:10:21 -06:00
{
_userInterfaceSystem . TryOpen ( uid , GasMixerUiKey . Key , actor . PlayerSession ) ;
DirtyUI ( uid , component ) ;
}
else
{
args . User . PopupMessageCursor ( Loc . GetString ( "comp-gas-mixer-ui-needs-anchor" ) ) ;
}
args . Handled = true ;
}
private void DirtyUI ( EntityUid uid , GasMixerComponent ? mixer )
{
if ( ! Resolve ( uid , ref mixer ) )
return ;
_userInterfaceSystem . TrySetUiState ( uid , GasMixerUiKey . Key ,
2021-12-08 13:00:43 +01:00
new GasMixerBoundUserInterfaceState ( EntityManager . GetComponent < MetaDataComponent > ( mixer . Owner ) . EntityName , mixer . TargetPressure , mixer . Enabled , mixer . InletOneConcentration ) ) ;
2021-11-11 16:10:21 -06:00
}
2022-02-08 09:42:07 +13:00
private void UpdateAppearance ( EntityUid uid , GasMixerComponent ? mixer = null , AppearanceComponent ? appearance = null )
{
if ( ! Resolve ( uid , ref mixer , ref appearance , false ) )
return ;
appearance . SetData ( FilterVisuals . Enabled , mixer . Enabled ) ;
}
2021-11-11 16:10:21 -06:00
private void OnToggleStatusMessage ( EntityUid uid , GasMixerComponent mixer , GasMixerToggleStatusMessage args )
{
mixer . Enabled = args . Enabled ;
2021-12-10 12:23:18 -06:00
_adminLogSystem . Add ( LogType . AtmosPowerChanged , LogImpact . Medium ,
2021-12-11 16:00:10 +01:00
$"{ToPrettyString(args.Session.AttachedEntity!.Value):player} set the power on {ToPrettyString(uid):device} to {args.Enabled}" ) ;
2021-11-11 16:10:21 -06:00
DirtyUI ( uid , mixer ) ;
2022-02-08 09:42:07 +13:00
UpdateAppearance ( uid , mixer ) ;
2021-11-11 16:10:21 -06:00
}
private void OnOutputPressureChangeMessage ( EntityUid uid , GasMixerComponent mixer , GasMixerChangeOutputPressureMessage args )
{
2022-03-01 03:39:30 +13:00
mixer . TargetPressure = Math . Clamp ( args . Pressure , 0f , mixer . MaxTargetPressure ) ;
2021-12-10 12:23:18 -06:00
_adminLogSystem . Add ( LogType . AtmosPressureChanged , LogImpact . Medium ,
2021-12-11 16:00:10 +01:00
$"{ToPrettyString(args.Session.AttachedEntity!.Value):player} set the pressure on {ToPrettyString(uid):device} to {args.Pressure}kPa" ) ;
2021-11-11 16:10:21 -06:00
DirtyUI ( uid , mixer ) ;
}
private void OnChangeNodePercentageMessage ( EntityUid uid , GasMixerComponent mixer ,
GasMixerChangeNodePercentageMessage args )
{
float nodeOne = Math . Clamp ( args . NodeOne , 0f , 100.0f ) / 100.0f ;
mixer . InletOneConcentration = nodeOne ;
mixer . InletTwoConcentration = 1.0f - mixer . InletOneConcentration ;
2021-12-10 12:23:18 -06:00
_adminLogSystem . Add ( LogType . AtmosRatioChanged , LogImpact . Medium ,
$"{EntityManager.ToPrettyString(args.Session.AttachedEntity!.Value):player} set the ratio on {EntityManager.ToPrettyString(uid):device} to {mixer.InletOneConcentration}:{mixer.InletTwoConcentration}" ) ;
2021-11-11 16:10:21 -06:00
DirtyUI ( uid , mixer ) ;
}
2021-06-19 13:25:05 +02:00
}
}