using System; using Content.Server.Administration.Logs; using Content.Server.Atmos.EntitySystems; using Content.Server.Atmos.Piping.Binary.Components; using Content.Server.Atmos.Piping.Components; using Content.Server.NodeContainer; using Content.Server.NodeContainer.Nodes; using Content.Shared.Atmos; using Content.Shared.Atmos.Piping; using Content.Shared.Atmos.Piping.Binary.Components; using Content.Shared.Database; using Content.Shared.Examine; using Content.Shared.Interaction; using Content.Shared.Popups; using JetBrains.Annotations; using Robust.Server.GameObjects; namespace Content.Server.Atmos.Piping.Binary.EntitySystems { [UsedImplicitly] public sealed class GasPressurePumpSystem : EntitySystem { [Dependency] private UserInterfaceSystem _userInterfaceSystem = default!; [Dependency] private AdminLogSystem _adminLogSystem = default!; [Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!; public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnPumpUpdated); SubscribeLocalEvent(OnPumpLeaveAtmosphere); SubscribeLocalEvent(OnExamined); SubscribeLocalEvent(OnPumpInteractHand); // Bound UI subscriptions SubscribeLocalEvent(OnOutputPressureChangeMessage); SubscribeLocalEvent(OnToggleStatusMessage); } private void OnExamined(EntityUid uid, GasPressurePumpComponent pump, ExaminedEvent args) { if (!EntityManager.GetComponent(pump.Owner).Anchored || !args.IsInDetailsRange) // Not anchored? Out of range? No status. return; if (Loc.TryGetString("gas-pressure-pump-system-examined", out var str, ("statusColor", "lightblue"), // TODO: change with pressure? ("pressure", pump.TargetPressure) )) args.PushMarkup(str); } private void OnPumpUpdated(EntityUid uid, GasPressurePumpComponent pump, AtmosDeviceUpdateEvent args) { var appearance = EntityManager.GetComponentOrNull(pump.Owner); if (!pump.Enabled || !EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer) || !nodeContainer.TryGetNode(pump.InletName, out PipeNode? inlet) || !nodeContainer.TryGetNode(pump.OutletName, out PipeNode? outlet)) { appearance?.SetData(PumpVisuals.Enabled, false); return; } var outputStartingPressure = outlet.Air.Pressure; if (MathHelper.CloseToPercent(pump.TargetPressure, outputStartingPressure)) { appearance?.SetData(PumpVisuals.Enabled, false); return; // No need to pump gas if target has been reached. } if (inlet.Air.TotalMoles > 0 && inlet.Air.Temperature > 0) { appearance?.SetData(PumpVisuals.Enabled, true); // We calculate the necessary moles to transfer using our good ol' friend PV=nRT. var pressureDelta = pump.TargetPressure - outputStartingPressure; var transferMoles = pressureDelta * outlet.Air.Volume / inlet.Air.Temperature * Atmospherics.R; var removed = inlet.Air.Remove(transferMoles); _atmosphereSystem.Merge(outlet.Air, removed); } } private void OnPumpLeaveAtmosphere(EntityUid uid, GasPressurePumpComponent component, AtmosDeviceDisabledEvent args) { if (EntityManager.TryGetComponent(uid, out AppearanceComponent? appearance)) { appearance.SetData(PumpVisuals.Enabled, false); } } private void OnPumpInteractHand(EntityUid uid, GasPressurePumpComponent component, InteractHandEvent args) { if (!EntityManager.TryGetComponent(args.User, out ActorComponent? actor)) return; if (EntityManager.GetComponent(component.Owner).Anchored) { _userInterfaceSystem.TryOpen(uid, GasPressurePumpUiKey.Key, actor.PlayerSession); DirtyUI(uid, component); } else { args.User.PopupMessageCursor(Loc.GetString("comp-gas-pump-ui-needs-anchor")); } args.Handled = true; } private void OnToggleStatusMessage(EntityUid uid, GasPressurePumpComponent pump, GasPressurePumpToggleStatusMessage args) { pump.Enabled = args.Enabled; _adminLogSystem.Add(LogType.AtmosPowerChanged, LogImpact.Medium, $"{ToPrettyString(args.Session.AttachedEntity!.Value):player} set the power on {ToPrettyString(uid):device} to {args.Enabled}"); DirtyUI(uid, pump); } private void OnOutputPressureChangeMessage(EntityUid uid, GasPressurePumpComponent pump, GasPressurePumpChangeOutputPressureMessage args) { pump.TargetPressure = Math.Clamp(args.Pressure, 0f, Atmospherics.MaxOutputPressure); _adminLogSystem.Add(LogType.AtmosPressureChanged, LogImpact.Medium, $"{ToPrettyString(args.Session.AttachedEntity!.Value):player} set the pressure on {ToPrettyString(uid):device} to {args.Pressure}kPa"); DirtyUI(uid, pump); } private void DirtyUI(EntityUid uid, GasPressurePumpComponent? pump) { if (!Resolve(uid, ref pump)) return; _userInterfaceSystem.TrySetUiState(uid, GasPressurePumpUiKey.Key, new GasPressurePumpBoundUserInterfaceState(EntityManager.GetComponent(pump.Owner).EntityName, pump.TargetPressure, pump.Enabled)); } } }