private void OnPumpUpdated(EntityUid uid, GasPressurePumpComponent pump, AtmosDeviceUpdateEvent args) { if (!pump.Enabled || !EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer) || !nodeContainer.TryGetNode(pump.InletName, out PipeNode? inlet) || !nodeContainer.TryGetNode(pump.OutletName, out PipeNode? outlet)) { _ambientSoundSystem.SetAmbience(pump.Owner, false); return; } var outputStartingPressure = outlet.Air.Pressure; if (outputStartingPressure >= pump.TargetPressure) { _ambientSoundSystem.SetAmbience(pump.Owner, false); return; // No need to pump gas if target has been reached. } if (inlet.Air.TotalMoles > 0 && inlet.Air.Temperature > 0) { // 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); _ambientSoundSystem.SetAmbience(pump.Owner, removed.TotalMoles > 0f); } }
private void OnPumpUpdated(EntityUid uid, GasPressurePumpComponent pump, AtmosDeviceUpdateEvent args) { var appearance = pump.Owner.GetComponentOrNull <AppearanceComponent>(); 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(PressurePumpVisuals.Enabled, false); return; } var outputStartingPressure = outlet.Air.Pressure; if (MathHelper.CloseToPercent(pump.TargetPressure, outputStartingPressure)) { appearance?.SetData(PressurePumpVisuals.Enabled, false); return; // No need to pump gas if target has been reached. } if (inlet.Air.TotalMoles > 0 && inlet.Air.Temperature > 0) { appearance?.SetData(PressurePumpVisuals.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); outlet.AssumeAir(removed); } }
private void OnVolumePumpUpdated(EntityUid uid, GasVolumePumpComponent pump, AtmosDeviceUpdateEvent args) { if (!pump.Enabled) { return; } if (!ComponentManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer)) { return; } if (!ComponentManager.TryGetComponent(uid, out AtmosDeviceComponent? device)) { return; } if (!nodeContainer.TryGetNode(pump.InletName, out PipeNode? inlet) || !nodeContainer.TryGetNode(pump.OutletName, out PipeNode? outlet)) { return; } var inputStartingPressure = inlet.Air.Pressure; var outputStartingPressure = outlet.Air.Pressure; // Pump mechanism won't do anything if the pressure is too high/too low unless you overclock it. if ((inputStartingPressure < pump.LowerThreshold) || (outputStartingPressure > pump.HigherThreshold) && !pump.Overclocked) { return; } // Overclocked pumps can only force gas a certain amount. if ((outputStartingPressure - inputStartingPressure > pump.OverclockThreshold) && pump.Overclocked) { return; } // We multiply the transfer rate in L/s by the seconds passed since the last process to get the liters. var transferRatio = (float)(pump.TransferRate * (_gameTiming.CurTime - device.LastProcess).TotalSeconds) / inlet.Air.Volume; var removed = inlet.Air.RemoveRatio(transferRatio); // Some of the gas from the mixture leaks when overclocked. if (pump.Overclocked) { var atmosphereSystem = Get <AtmosphereSystem>(); var tile = atmosphereSystem.GetTileMixture(pump.Owner.Transform.Coordinates, true); if (tile != null) { var leaked = removed.RemoveRatio(pump.LeakRatio); atmosphereSystem.Merge(tile, leaked); } } outlet.AssumeAir(removed); }
private void OnFilterUpdated(EntityUid uid, GasFilterComponent filter, AtmosDeviceUpdateEvent args) { var appearance = EntityManager.GetComponentOrNull <AppearanceComponent>(filter.Owner); if (!filter.Enabled || !EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer) || !EntityManager.TryGetComponent(uid, out AtmosDeviceComponent? device) || !nodeContainer.TryGetNode(filter.InletName, out PipeNode? inletNode) || !nodeContainer.TryGetNode(filter.FilterName, out PipeNode? filterNode) || !nodeContainer.TryGetNode(filter.OutletName, out PipeNode? outletNode) || outletNode.Air.Pressure >= Atmospherics.MaxOutputPressure) // No need to transfer if target is full. { appearance?.SetData(FilterVisuals.Enabled, false); _ambientSoundSystem.SetAmbience(filter.Owner, false); return; } // We multiply the transfer rate in L/s by the seconds passed since the last process to get the liters. var transferRatio = (float)(filter.TransferRate * (_gameTiming.CurTime - device.LastProcess).TotalSeconds) / inletNode.Air.Volume; if (transferRatio <= 0) { appearance?.SetData(FilterVisuals.Enabled, false); _ambientSoundSystem.SetAmbience(filter.Owner, false); return; } var removed = inletNode.Air.RemoveRatio(transferRatio); if (filter.FilteredGas.HasValue) { appearance?.SetData(FilterVisuals.Enabled, true); var filteredOut = new GasMixture() { Temperature = removed.Temperature }; filteredOut.SetMoles(filter.FilteredGas.Value, removed.GetMoles(filter.FilteredGas.Value)); removed.SetMoles(filter.FilteredGas.Value, 0f); var target = filterNode.Air.Pressure < Atmospherics.MaxOutputPressure ? filterNode : inletNode; _atmosphereSystem.Merge(target.Air, filteredOut); if (filteredOut.Pressure != 0f) { _ambientSoundSystem.SetAmbience(filter.Owner, true); } else { _ambientSoundSystem.SetAmbience(filter.Owner, false); } } _atmosphereSystem.Merge(outletNode.Air, removed); }
private void OnFilterUpdated(EntityUid uid, GasFilterComponent filter, AtmosDeviceUpdateEvent args) { if (!filter.Enabled) { return; } if (!ComponentManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer)) { return; } if (!ComponentManager.TryGetComponent(uid, out AtmosDeviceComponent? device)) { return; } if (!nodeContainer.TryGetNode(filter.InletName, out PipeNode? inletNode) || !nodeContainer.TryGetNode(filter.FilterName, out PipeNode? filterNode) || !nodeContainer.TryGetNode(filter.OutletName, out PipeNode? outletNode)) { return; } if (outletNode.Air.Pressure >= Atmospherics.MaxOutputPressure) { return; // No need to transfer if target is full. } // We multiply the transfer rate in L/s by the seconds passed since the last process to get the liters. var transferRatio = (float)(filter.TransferRate * (_gameTiming.CurTime - device.LastProcess).TotalSeconds) / inletNode.Air.Volume; if (transferRatio <= 0) { return; } var removed = inletNode.Air.RemoveRatio(transferRatio); if (filter.FilteredGas.HasValue) { var filteredOut = new GasMixture() { Temperature = removed.Temperature }; filteredOut.SetMoles(filter.FilteredGas.Value, removed.GetMoles(filter.FilteredGas.Value)); removed.SetMoles(filter.FilteredGas.Value, 0f); var target = filterNode.Air.Pressure < Atmospherics.MaxOutputPressure ? filterNode : inletNode; target.AssumeAir(filteredOut); } outletNode.AssumeAir(removed); }
private void OnVolumePumpUpdated(EntityUid uid, GasVolumePumpComponent pump, AtmosDeviceUpdateEvent args) { if (!pump.Enabled || !TryComp(uid, out NodeContainerComponent? nodeContainer) || !TryComp(uid, out AtmosDeviceComponent? device) || !nodeContainer.TryGetNode(pump.InletName, out PipeNode? inlet) || !nodeContainer.TryGetNode(pump.OutletName, out PipeNode? outlet)) { _ambientSoundSystem.SetAmbience(uid, false); return; } var inputStartingPressure = inlet.Air.Pressure; var outputStartingPressure = outlet.Air.Pressure; // Pump mechanism won't do anything if the pressure is too high/too low unless you overclock it. if ((inputStartingPressure < pump.LowerThreshold) || (outputStartingPressure > pump.HigherThreshold) && !pump.Overclocked) { return; } // Overclocked pumps can only force gas a certain amount. if ((outputStartingPressure - inputStartingPressure > pump.OverclockThreshold) && pump.Overclocked) { return; } // We multiply the transfer rate in L/s by the seconds passed since the last process to get the liters. var transferRatio = (float)(pump.TransferRate * (_gameTiming.CurTime - device.LastProcess).TotalSeconds) / inlet.Air.Volume; var removed = inlet.Air.RemoveRatio(transferRatio); // Some of the gas from the mixture leaks when overclocked. if (pump.Overclocked) { var transform = Transform(uid); var indices = _transformSystem.GetGridOrMapTilePosition(uid, transform); var tile = _atmosphereSystem.GetTileMixture(transform.GridUid, null, indices, true); if (tile != null) { var leaked = removed.RemoveRatio(pump.LeakRatio); _atmosphereSystem.Merge(tile, leaked); } } _atmosphereSystem.Merge(outlet.Air, removed); _ambientSoundSystem.SetAmbience(uid, removed.TotalMoles > 0f); }
private void OnMinerUpdated(EntityUid uid, GasMinerComponent miner, AtmosDeviceUpdateEvent args) { if (!CheckMinerOperation(args.Atmosphere, miner, out var tile) || !miner.Enabled || !miner.SpawnGas.HasValue || miner.SpawnAmount <= 0f) { return; } // Time to mine some gas. var merger = new GasMixture(1) { Temperature = miner.SpawnTemperature }; merger.SetMoles(miner.SpawnGas.Value, miner.SpawnAmount); tile.AssumeAir(merger); }
private void OnMinerUpdated(EntityUid uid, GasMinerComponent miner, AtmosDeviceUpdateEvent args) { var atmosphereSystem = Get <AtmosphereSystem>(); if (!CheckMinerOperation(atmosphereSystem, miner, out var environment) || !miner.Enabled || !miner.SpawnGas.HasValue || miner.SpawnAmount <= 0f) { return; } // Time to mine some gas. var merger = new GasMixture(1) { Temperature = miner.SpawnTemperature }; merger.SetMoles(miner.SpawnGas.Value, miner.SpawnAmount); atmosphereSystem.Merge(environment, merger); }
private void OnCanisterUpdated(EntityUid uid, GasCanisterComponent canister, AtmosDeviceUpdateEvent args) { if (!ComponentManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer) || !ComponentManager.TryGetComponent(uid, out AppearanceComponent? appearance)) { return; } if (!nodeContainer.TryGetNode(canister.PortName, out PipeNode? portNode)) { return; } DirtyUI(uid); // Nothing to do here. if (MathHelper.CloseTo(portNode.Air.Pressure, canister.LastPressure)) { return; } canister.LastPressure = portNode.Air.Pressure; if (portNode.Air.Pressure < 10) { appearance.SetData(GasCanisterVisuals.PressureState, 0); } else if (portNode.Air.Pressure < Atmospherics.OneAtmosphere) { appearance.SetData(GasCanisterVisuals.PressureState, 1); } else if (portNode.Air.Pressure < (15 * Atmospherics.OneAtmosphere)) { appearance.SetData(GasCanisterVisuals.PressureState, 2); } else { appearance.SetData(GasCanisterVisuals.PressureState, 3); } }
private void OnPassiveVentUpdated(EntityUid uid, GasPassiveVentComponent vent, AtmosDeviceUpdateEvent args) { var environment = _atmosphereSystem.GetContainingMixture(uid, true, true); if (environment == null) { return; } if (!EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer)) { return; } if (!nodeContainer.TryGetNode(vent.InletName, out PipeNode? inlet)) { return; } var environmentPressure = environment.Pressure; var pressureDelta = MathF.Abs(environmentPressure - inlet.Air.Pressure); if ((environment.Temperature > 0 || inlet.Air.Temperature > 0) && pressureDelta > 0.5f) { if (environmentPressure < inlet.Air.Pressure) { var airTemperature = environment.Temperature > 0 ? environment.Temperature : inlet.Air.Temperature; var transferMoles = pressureDelta * environment.Volume / (airTemperature * Atmospherics.R); var removed = inlet.Air.Remove(transferMoles); _atmosphereSystem.Merge(environment, removed); } else { var airTemperature = inlet.Air.Temperature > 0 ? inlet.Air.Temperature : environment.Temperature; var outputVolume = inlet.Air.Volume; var transferMoles = (pressureDelta * outputVolume) / (airTemperature * Atmospherics.R); transferMoles = MathF.Min(transferMoles, environment.TotalMoles * inlet.Air.Volume / environment.Volume); var removed = environment.Remove(transferMoles); _atmosphereSystem.Merge(inlet.Air, removed); } } }
private void OnPassiveVentUpdated(EntityUid uid, GasPassiveVentComponent vent, AtmosDeviceUpdateEvent args) { var environment = args.Atmosphere.GetTile(vent.Owner.Transform.Coordinates) !; if (environment.Air == null) { return; } if (!ComponentManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer)) { return; } if (!nodeContainer.TryGetNode(vent.InletName, out PipeNode? inlet)) { return; } var environmentPressure = environment.Air.Pressure; var pressureDelta = MathF.Abs(environmentPressure - inlet.Air.Pressure); if ((environment.Air.Temperature > 0 || inlet.Air.Temperature > 0) && pressureDelta > 0.5f) { if (environmentPressure < inlet.Air.Pressure) { var airTemperature = environment.Temperature > 0 ? environment.Temperature : inlet.Air.Temperature; var transferMoles = pressureDelta * environment.Air.Volume / (airTemperature * Atmospherics.R); var removed = inlet.Air.Remove(transferMoles); environment.AssumeAir(removed); } else { var airTemperature = inlet.Air.Temperature > 0 ? inlet.Air.Temperature : environment.Temperature; var outputVolume = inlet.Air.Volume; var transferMoles = (pressureDelta * outputVolume) / (airTemperature * Atmospherics.R); transferMoles = MathF.Min(transferMoles, environment.Air.TotalMoles * inlet.Air.Volume / environment.Air.Volume); var removed = environment.Air.Remove(transferMoles); inlet.AssumeAir(removed); environment.Invalidate(); } } }
private void OnGasDualPortVentPumpUpdated(EntityUid uid, GasDualPortVentPumpComponent vent, AtmosDeviceUpdateEvent args) { var appearance = vent.Owner.GetComponentOrNull <AppearanceComponent>(); if (vent.Welded) { appearance?.SetData(VentPumpVisuals.State, VentPumpState.Welded); return; } if (!vent.Enabled || !EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer) || !nodeContainer.TryGetNode(vent.InletName, out PipeNode? inlet) || !nodeContainer.TryGetNode(vent.OutletName, out PipeNode? outlet)) { appearance?.SetData(VentPumpVisuals.State, VentPumpState.Off); return; } var environment = _atmosphereSystem.GetTileMixture(vent.Owner.Transform.Coordinates, true); // We're in an air-blocked tile... Do nothing. if (environment == null) { appearance?.SetData(VentPumpVisuals.State, VentPumpState.Off); return; } if (vent.PumpDirection == VentPumpDirection.Releasing) { appearance?.SetData(VentPumpVisuals.State, VentPumpState.Out); var pressureDelta = 10000f; if ((vent.PressureChecks & DualPortVentPressureBound.ExternalBound) != 0) { pressureDelta = MathF.Min(pressureDelta, (vent.ExternalPressureBound - environment.Pressure)); } if ((vent.PressureChecks & DualPortVentPressureBound.InputMinimum) != 0) { pressureDelta = MathF.Min(pressureDelta, (inlet.Air.Pressure - vent.InputPressureMin)); } if (pressureDelta > 0 && inlet.Air.Temperature > 0) { var transferMoles = pressureDelta * environment.Volume / inlet.Air.Temperature * Atmospherics.R; var removed = inlet.Air.Remove(transferMoles); _atmosphereSystem.Merge(environment, removed); } } else if (vent.PumpDirection == VentPumpDirection.Siphoning && environment.Pressure > 0f) { appearance?.SetData(VentPumpVisuals.State, VentPumpState.In); var ourMultiplier = outlet.Air.Volume / environment.Temperature * Atmospherics.R; var molesDelta = 10000 * ourMultiplier; if ((vent.PressureChecks & DualPortVentPressureBound.ExternalBound) != 0) { molesDelta = MathF.Min(molesDelta, (environment.Pressure - vent.OutputPressureMax) * environment.Volume / (environment.Temperature * Atmospherics.R)); } if ((vent.PressureChecks & DualPortVentPressureBound.InputMinimum) != 0) { molesDelta = MathF.Min(molesDelta, (vent.InputPressureMin - outlet.Air.Pressure) * ourMultiplier); } if (molesDelta > 0) { var removed = environment.Remove(molesDelta); _atmosphereSystem.Merge(outlet.Air, removed); } } }
private void OnVentScrubberUpdated(EntityUid uid, GasVentScrubberComponent scrubber, AtmosDeviceUpdateEvent args) { if (scrubber.Welded) { return; } if (!TryComp(uid, out AtmosDeviceComponent? device)) { return; } var timeDelta = (float)(_gameTiming.CurTime - device.LastProcess).TotalSeconds; if (!scrubber.Enabled || !EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer) || !nodeContainer.TryGetNode(scrubber.OutletName, out PipeNode? outlet)) { return; } var xform = Transform(uid); if (xform.GridUid == null) { return; } var position = _transformSystem.GetGridOrMapTilePosition(uid, xform); var environment = _atmosphereSystem.GetTileMixture(xform.GridUid, xform.MapUid, position, true); Scrub(timeDelta, scrubber, environment, outlet); if (!scrubber.WideNet) { return; } // Scrub adjacent tiles too. foreach (var adjacent in _atmosphereSystem.GetAdjacentTileMixtures(xform.GridUid.Value, position, false, true)) { Scrub(timeDelta, scrubber, adjacent, outlet); } }
private void OnMixerUpdated(EntityUid uid, GasMixerComponent mixer, AtmosDeviceUpdateEvent args) { // TODO ATMOS: Cache total moles since it's expensive. if (!mixer.Enabled) { return; } if (!ComponentManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer)) { return; } if (!nodeContainer.TryGetNode(mixer.InletOneName, out PipeNode? inletOne) || !nodeContainer.TryGetNode(mixer.InletTwoName, out PipeNode? inletTwo) || !nodeContainer.TryGetNode(mixer.OutletName, out PipeNode? outlet)) { return; } var outputStartingPressure = outlet.Air.Pressure; if (outputStartingPressure >= mixer.TargetPressure) { return; // Target reached, no need to mix. } 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) { return; } 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); outlet.AssumeAir(removed); } if (transferMolesTwo > 0f) { var removed = inletTwo.Air.Remove(transferMolesTwo); outlet.AssumeAir(removed); } }
private void OnVentScrubberUpdated(EntityUid uid, GasVentScrubberComponent scrubber, AtmosDeviceUpdateEvent args) { var appearance = EntityManager.GetComponentOrNull <AppearanceComponent>(scrubber.Owner); if (scrubber.Welded) { appearance?.SetData(ScrubberVisuals.State, ScrubberState.Welded); _ambientSoundSystem.SetAmbience(scrubber.Owner, false); return; } if (!TryComp(uid, out AtmosDeviceComponent? device)) { return; } var timeDelta = (float)(_gameTiming.CurTime - device.LastProcess).TotalSeconds; if (!scrubber.Enabled || !EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer) || !nodeContainer.TryGetNode(scrubber.OutletName, out PipeNode? outlet)) { appearance?.SetData(ScrubberVisuals.State, ScrubberState.Off); _ambientSoundSystem.SetAmbience(scrubber.Owner, false); return; } _ambientSoundSystem.SetAmbience(scrubber.Owner, true); var environment = _atmosphereSystem.GetTileMixture(EntityManager.GetComponent <TransformComponent>(scrubber.Owner).Coordinates, true); Scrub(timeDelta, scrubber, appearance, environment, outlet); if (!scrubber.WideNet) { return; } // Scrub adjacent tiles too. foreach (var adjacent in _atmosphereSystem.GetAdjacentTileMixtures(EntityManager.GetComponent <TransformComponent>(scrubber.Owner).Coordinates, false, true)) { Scrub(timeDelta, scrubber, null, adjacent, outlet); } }
private void OnCanisterUpdated(EntityUid uid, GasCanisterComponent canister, AtmosDeviceUpdateEvent args) { if (!ComponentManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer) || !ComponentManager.TryGetComponent(uid, out AppearanceComponent? appearance)) { return; } if (!nodeContainer.TryGetNode(canister.PortName, out PortablePipeNode? portNode)) { return; } var atmosphereSystem = Get <AtmosphereSystem>(); atmosphereSystem.React(canister.Air, portNode); if (portNode.NodeGroup is PipeNet { NodeCount: > 1 } net) { var buffer = new GasMixture(net.Air.Volume + canister.Air.Volume); atmosphereSystem.Merge(buffer, net.Air); atmosphereSystem.Merge(buffer, canister.Air); net.Air.Clear(); atmosphereSystem.Merge(net.Air, buffer); net.Air.Multiply(net.Air.Volume / buffer.Volume); canister.Air.Clear(); atmosphereSystem.Merge(canister.Air, buffer); canister.Air.Multiply(canister.Air.Volume / buffer.Volume); } // Release valve is open, release gas. if (canister.ReleaseValve) { if (!ComponentManager.TryGetComponent(uid, out ContainerManagerComponent? containerManager) || !containerManager.TryGetContainer(canister.ContainerName, out var container)) { return; } if (container.ContainedEntities.Count > 0) { var gasTank = container.ContainedEntities[0].GetComponent <GasTankComponent>(); atmosphereSystem.ReleaseGasTo(canister.Air, gasTank.Air, canister.ReleasePressure); } else { var tileAtmosphere = canister.Owner.Transform.Coordinates.GetTileAtmosphere(); atmosphereSystem.ReleaseGasTo(canister.Air, tileAtmosphere?.Air, canister.ReleasePressure); tileAtmosphere?.Invalidate(); } } DirtyUI(uid); // If last pressure is very close to the current pressure, do nothing. if (MathHelper.CloseTo(canister.Air.Pressure, canister.LastPressure)) { return; } canister.LastPressure = canister.Air.Pressure; if (canister.Air.Pressure < 10) { appearance.SetData(GasCanisterVisuals.PressureState, 0); } else if (canister.Air.Pressure < Atmospherics.OneAtmosphere) { appearance.SetData(GasCanisterVisuals.PressureState, 1); } else if (canister.Air.Pressure < (15 * Atmospherics.OneAtmosphere)) { appearance.SetData(GasCanisterVisuals.PressureState, 2); } else { appearance.SetData(GasCanisterVisuals.PressureState, 3); } }
private void OnThermoMachineUpdated(EntityUid uid, GasThermoMachineComponent thermoMachine, AtmosDeviceUpdateEvent args) { var appearance = thermoMachine.Owner.GetComponentOrNull <AppearanceComponent>(); appearance?.SetData(ThermoMachineVisuals.Enabled, false); if (!thermoMachine.Enabled) { return; } if (!ComponentManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer)) { return; } if (!nodeContainer.TryGetNode(thermoMachine.InletName, out PipeNode? inlet)) { return; } var airHeatCapacity = _atmosphereSystem.GetHeatCapacity(inlet.Air); var combinedHeatCapacity = airHeatCapacity + thermoMachine.HeatCapacity; var oldTemperature = inlet.Air.Temperature; if (combinedHeatCapacity > 0) { appearance?.SetData(ThermoMachineVisuals.Enabled, true); var combinedEnergy = thermoMachine.HeatCapacity * thermoMachine.TargetTemperature + airHeatCapacity * inlet.Air.Temperature; inlet.Air.Temperature = combinedEnergy / combinedHeatCapacity; } // TODO ATMOS: Active power usage. }
private void OnPassiveGateUpdated(EntityUid uid, GasPassiveGateComponent gate, AtmosDeviceUpdateEvent args) { if (!gate.Enabled) { return; } if (!ComponentManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer)) { return; } if (!nodeContainer.TryGetNode(gate.InletName, out PipeNode? inlet) || !nodeContainer.TryGetNode(gate.OutletName, out PipeNode? outlet)) { return; } var outputStartingPressure = outlet.Air.Pressure; var inputStartingPressure = inlet.Air.Pressure; if (outputStartingPressure >= MathF.Min(gate.TargetPressure, inputStartingPressure - gate.FrictionPressureDifference)) { return; // No need to pump gas, target reached or input pressure too low. } if (inlet.Air.TotalMoles > 0 && inlet.Air.Temperature > 0) { // We calculate the necessary moles to transfer using our good ol' friend PV=nRT. var pressureDelta = MathF.Min(gate.TargetPressure - outputStartingPressure, (inputStartingPressure - outputStartingPressure) / 2); // We can't have a pressure delta that would cause outlet pressure > inlet pressure. var transferMoles = pressureDelta * outlet.Air.Volume / (inlet.Air.Temperature * Atmospherics.R); // Actually transfer the gas. outlet.AssumeAir(inlet.Air.Remove(transferMoles)); } }
private void OnVentScrubberUpdated(EntityUid uid, GasVentScrubberComponent scrubber, AtmosDeviceUpdateEvent args) { var appearance = scrubber.Owner.GetComponentOrNull <AppearanceComponent>(); if (scrubber.Welded) { appearance?.SetData(ScrubberVisuals.State, ScrubberState.Welded); return; } if (!scrubber.Enabled || !ComponentManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer) || !nodeContainer.TryGetNode(scrubber.OutletName, out PipeNode? outlet)) { appearance?.SetData(ScrubberVisuals.State, ScrubberState.Off); return; } var environment = _atmosphereSystem.GetTileMixture(scrubber.Owner.Transform.Coordinates, true); Scrub(_atmosphereSystem, scrubber, appearance, environment, outlet); if (!scrubber.WideNet) { return; } // Scrub adjacent tiles too. foreach (var adjacent in _atmosphereSystem.GetAdjacentTileMixtures(scrubber.Owner.Transform.Coordinates, false, true)) { Scrub(_atmosphereSystem, scrubber, null, adjacent, outlet); } }
private void OnVentScrubberUpdated(EntityUid uid, GasVentScrubberComponent scrubber, AtmosDeviceUpdateEvent args) { var appearance = scrubber.Owner.GetComponentOrNull <AppearanceComponent>(); if (scrubber.Welded) { appearance?.SetData(ScrubberVisuals.State, ScrubberState.Welded); return; } appearance?.SetData(ScrubberVisuals.State, ScrubberState.Off); if (!scrubber.Enabled) { return; } if (!ComponentManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer)) { return; } if (!nodeContainer.TryGetNode(scrubber.OutletName, out PipeNode? outlet)) { return; } var environment = args.Atmosphere.GetTile(scrubber.Owner.Transform.Coordinates) !; Scrub(scrubber, appearance, environment, outlet); if (!scrubber.WideNet) { return; } // Scrub adjacent tiles too. foreach (var adjacent in environment.AdjacentTiles) { // Pass null appearance, we don't need to set it there. Scrub(scrubber, null, adjacent, outlet); } }
private void OnGasVentPumpUpdated(EntityUid uid, GasVentPumpComponent vent, AtmosDeviceUpdateEvent args) { //Bingo waz here if (vent.Welded) { return; } var nodeName = vent.PumpDirection switch { VentPumpDirection.Releasing => vent.Inlet, VentPumpDirection.Siphoning => vent.Outlet, _ => throw new ArgumentOutOfRangeException() }; if (!vent.Enabled || !TryComp(uid, out AtmosDeviceComponent? device) || !TryComp(uid, out NodeContainerComponent? nodeContainer) || !nodeContainer.TryGetNode(nodeName, out PipeNode? pipe)) { return; } var environment = _atmosphereSystem.GetTileMixture(EntityManager.GetComponent <TransformComponent>(vent.Owner).Coordinates, true); // We're in an air-blocked tile... Do nothing. if (environment == null) { return; } var timeDelta = (_gameTiming.CurTime - device.LastProcess).TotalSeconds; var pressureDelta = (float)timeDelta * vent.TargetPressureChange; if (vent.PumpDirection == VentPumpDirection.Releasing && pipe.Air.Pressure > 0) { if (environment.Pressure > vent.MaxPressure) { return; } if ((vent.PressureChecks & VentPressureBound.ExternalBound) != 0) { pressureDelta = MathF.Min(pressureDelta, vent.ExternalPressureBound - environment.Pressure); } if (pressureDelta <= 0) { return; } // how many moles to transfer to change external pressure by pressureDelta // (ignoring temperature differences because I am lazy) var transferMoles = pressureDelta * environment.Volume / (pipe.Air.Temperature * Atmospherics.R); // limit transferMoles so the source doesn't go below its bound. if ((vent.PressureChecks & VentPressureBound.InternalBound) != 0) { var internalDelta = pipe.Air.Pressure - vent.InternalPressureBound; if (internalDelta <= 0) { return; } var maxTransfer = internalDelta * pipe.Air.Volume / (pipe.Air.Temperature * Atmospherics.R); transferMoles = MathF.Min(transferMoles, maxTransfer); } _atmosphereSystem.Merge(environment, pipe.Air.Remove(transferMoles)); } else if (vent.PumpDirection == VentPumpDirection.Siphoning && environment.Pressure > 0) { if (pipe.Air.Pressure > vent.MaxPressure) { return; } if ((vent.PressureChecks & VentPressureBound.InternalBound) != 0) { pressureDelta = MathF.Min(pressureDelta, vent.InternalPressureBound - pipe.Air.Pressure); } if (pressureDelta <= 0) { return; } // how many moles to transfer to change internal pressure by pressureDelta // (ignoring temperature differences because I am lazy) var transferMoles = pressureDelta * pipe.Air.Volume / (environment.Temperature * Atmospherics.R); // limit transferMoles so the source doesn't go below its bound. if ((vent.PressureChecks & VentPressureBound.ExternalBound) != 0) { var externalDelta = environment.Pressure - vent.ExternalPressureBound; if (externalDelta <= 0) { return; } var maxTransfer = externalDelta * environment.Volume / (environment.Temperature * Atmospherics.R); transferMoles = MathF.Min(transferMoles, maxTransfer); } _atmosphereSystem.Merge(pipe.Air, environment.Remove(transferMoles)); } }
private void OnOutletInjectorUpdated(EntityUid uid, GasOutletInjectorComponent injector, AtmosDeviceUpdateEvent args) { injector.Injecting = false; if (!injector.Enabled) { return; } if (!EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer)) { return; } if (!TryComp(uid, out AtmosDeviceComponent? device)) { return; } if (!nodeContainer.TryGetNode(injector.InletName, out PipeNode? inlet)) { return; } var environment = _atmosphereSystem.GetTileMixture(EntityManager.GetComponent <TransformComponent>(injector.Owner).Coordinates, true); if (environment == null) { return; } if (inlet.Air.Temperature < 0) { return; } var timeDelta = (float)(_gameTiming.CurTime - device.LastProcess).TotalSeconds; var ratio = MathF.Min(1f, timeDelta * injector.TransferRate / inlet.Air.Volume); var removed = inlet.Air.RemoveRatio(ratio); _atmosphereSystem.Merge(environment, removed); }
private void OnCanisterUpdated(EntityUid uid, GasCanisterComponent canister, AtmosDeviceUpdateEvent args) { _atmosphereSystem.React(canister.Air, canister); if (!EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer) || !EntityManager.TryGetComponent(uid, out AppearanceComponent? appearance)) { return; } if (!nodeContainer.TryGetNode(canister.PortName, out PortablePipeNode? portNode)) { return; } if (portNode.NodeGroup is PipeNet { NodeCount: > 1 } net) { MixContainerWithPipeNet(canister.Air, net.Air); } ContainerManagerComponent?containerManager = null; // Release valve is open, release gas. if (canister.ReleaseValve) { if (!EntityManager.TryGetComponent(uid, out containerManager) || !containerManager.TryGetContainer(canister.ContainerName, out var container)) { return; } if (container.ContainedEntities.Count > 0) { var gasTank = EntityManager.GetComponent <GasTankComponent>(container.ContainedEntities[0]); _atmosphereSystem.ReleaseGasTo(canister.Air, gasTank.Air, canister.ReleasePressure); } else { var environment = _atmosphereSystem.GetContainingMixture(uid, false, true); _atmosphereSystem.ReleaseGasTo(canister.Air, environment, canister.ReleasePressure); } } // If last pressure is very close to the current pressure, do nothing. if (MathHelper.CloseToPercent(canister.Air.Pressure, canister.LastPressure)) { return; } DirtyUI(uid, canister, nodeContainer, containerManager); canister.LastPressure = canister.Air.Pressure; if (canister.Air.Pressure < 10) { appearance.SetData(GasCanisterVisuals.PressureState, 0); } else if (canister.Air.Pressure < Atmospherics.OneAtmosphere) { appearance.SetData(GasCanisterVisuals.PressureState, 1); } else if (canister.Air.Pressure < (15 * Atmospherics.OneAtmosphere)) { appearance.SetData(GasCanisterVisuals.PressureState, 2); } else { appearance.SetData(GasCanisterVisuals.PressureState, 3); } }
private void OnOutletInjectorUpdated(EntityUid uid, GasOutletInjectorComponent injector, AtmosDeviceUpdateEvent args) { if (!injector.Enabled) { return; } if (!EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer)) { return; } if (!TryComp(uid, out AtmosDeviceComponent? device)) { return; } if (!nodeContainer.TryGetNode(injector.InletName, out PipeNode? inlet)) { return; } var environment = _atmosphereSystem.GetContainingMixture(uid, true, true); if (environment == null) { return; } if (inlet.Air.Temperature < 0) { return; } if (environment.Pressure > injector.MaxPressure) { return; } var timeDelta = (float)(_gameTiming.CurTime - device.LastProcess).TotalSeconds; // TODO adjust ratio so that environment does not go above MaxPressure? var ratio = MathF.Min(1f, timeDelta * injector.TransferRate / inlet.Air.Volume); var removed = inlet.Air.RemoveRatio(ratio); _atmosphereSystem.Merge(environment, removed); }
private void OnOutletInjectorUpdated(EntityUid uid, GasOutletInjectorComponent injector, AtmosDeviceUpdateEvent args) { injector.Injecting = false; if (!injector.Enabled) { return; } if (!ComponentManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer)) { return; } if (!nodeContainer.TryGetNode(injector.InletName, out PipeNode? inlet)) { return; } var atmosphereSystem = Get <AtmosphereSystem>(); var environment = atmosphereSystem.GetTileMixture(injector.Owner.Transform.Coordinates, true); if (environment == null) { return; } if (inlet.Air.Temperature > 0) { var transferMoles = inlet.Air.Pressure * injector.VolumeRate / (inlet.Air.Temperature * Atmospherics.R); var removed = inlet.Air.Remove(transferMoles); atmosphereSystem.Merge(environment, removed); } }
private void OnDeviceUpdated(EntityUid uid, PortableScrubberComponent component, AtmosDeviceUpdateEvent args) { if (!TryComp(uid, out AtmosDeviceComponent? device)) { return; } var timeDelta = (float)(_gameTiming.CurTime - device.LastProcess).TotalSeconds; if (!component.Enabled) { return; } /// If we are on top of a connector port, empty into it. if (TryComp <NodeContainerComponent>(uid, out var nodeContainer) && nodeContainer.TryGetNode(component.PortName, out PortablePipeNode? portableNode) && portableNode.ConnectionsEnabled) { _atmosphereSystem.React(component.Air, portableNode); if (portableNode.NodeGroup is PipeNet { NodeCount : > 1 } net) { _canisterSystem.MixContainerWithPipeNet(component.Air, net.Air); } } if (component.Full) { UpdateAppearance(uid, true, false); return; } var xform = Transform(uid); if (xform.GridUid == null) { return; } var position = _transformSystem.GetGridOrMapTilePosition(uid, xform); var environment = _atmosphereSystem.GetTileMixture(xform.GridUid, xform.MapUid, position, true); var running = Scrub(timeDelta, component, environment); UpdateAppearance(uid, false, running); /// We scrub once to see if we can and set the animation if (!running) { return; } /// widenet foreach (var adjacent in _atmosphereSystem.GetAdjacentTileMixtures(xform.GridUid.Value, position, false, true)) { Scrub(timeDelta, component, environment); } }
private void OnGasVentPumpUpdated(EntityUid uid, GasVentPumpComponent vent, AtmosDeviceUpdateEvent args) { var appearance = vent.Owner.GetComponentOrNull <AppearanceComponent>(); if (vent.Welded) { appearance?.SetData(VentPumpVisuals.State, VentPumpState.Welded); return; } appearance?.SetData(VentPumpVisuals.State, VentPumpState.Off); if (!vent.Enabled) { return; } if (!ComponentManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer)) { return; } if (!nodeContainer.TryGetNode(vent.InletName, out PipeNode? pipe)) { return; } var environment = args.Atmosphere.GetTile(vent.Owner.Transform.Coordinates) !; // We're in an air-blocked tile... Do nothing. if (environment.Air == null) { return; } if (vent.PumpDirection == VentPumpDirection.Releasing) { appearance?.SetData(VentPumpVisuals.State, VentPumpState.Out); var pressureDelta = 10000f; if ((vent.PressureChecks & VentPressureBound.ExternalBound) != 0) { pressureDelta = MathF.Min(pressureDelta, vent.ExternalPressureBound - environment.Air.Pressure); } if ((vent.PressureChecks & VentPressureBound.InternalBound) != 0) { pressureDelta = MathF.Min(pressureDelta, pipe.Air.Pressure - vent.InternalPressureBound); } if (pressureDelta > 0 && pipe.Air.Temperature > 0) { var transferMoles = pressureDelta * environment.Air.Volume / (pipe.Air.Temperature * Atmospherics.R); environment.AssumeAir(pipe.Air.Remove(transferMoles)); } } else if (vent.PumpDirection == VentPumpDirection.Siphoning && environment.Air.Pressure > 0) { appearance?.SetData(VentPumpVisuals.State, VentPumpState.In); var ourMultiplier = pipe.Air.Volume / (environment.Air.Temperature * Atmospherics.R); var molesDelta = 10000f * ourMultiplier; if ((vent.PressureChecks & VentPressureBound.ExternalBound) != 0) { molesDelta = MathF.Min(molesDelta, (environment.Air.Pressure - vent.ExternalPressureBound) * environment.Air.Volume / (environment.Air.Temperature * Atmospherics.R)); } if ((vent.PressureChecks & VentPressureBound.InternalBound) != 0) { molesDelta = MathF.Min(molesDelta, (vent.InternalPressureBound - pipe.Air.Pressure) * ourMultiplier); } if (molesDelta > 0) { var removed = environment.Air.Remove(molesDelta); pipe.AssumeAir(removed); environment.Invalidate(); } } }
private void OnCanisterUpdated(EntityUid uid, GasCanisterComponent canister, AtmosDeviceUpdateEvent args) { if (!ComponentManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer) || !ComponentManager.TryGetComponent(uid, out AppearanceComponent? appearance)) { return; } if (!nodeContainer.TryGetNode(canister.PortName, out PipeNode? portNode)) { return; } // Release valve is open, release gas. if (canister.ReleaseValve) { if (!ComponentManager.TryGetComponent(uid, out ContainerManagerComponent? containerManager) || !containerManager.TryGetContainer(canister.ContainerName, out var container)) { return; } var atmosphereSystem = Get <AtmosphereSystem>(); if (container.ContainedEntities.Count > 0) { var gasTank = container.ContainedEntities[0].GetComponent <GasTankComponent>(); atmosphereSystem.ReleaseGasTo(portNode.Air, gasTank.Air, canister.ReleasePressure); } else { var tileAtmosphere = canister.Owner.Transform.Coordinates.GetTileAtmosphere(); atmosphereSystem.ReleaseGasTo(portNode.Air, tileAtmosphere?.Air, canister.ReleasePressure); tileAtmosphere?.Invalidate(); } } DirtyUI(uid); // Nothing to do here. if (MathHelper.CloseTo(portNode.Air.Pressure, canister.LastPressure)) { return; } canister.LastPressure = portNode.Air.Pressure; if (portNode.Air.Pressure < 10) { appearance.SetData(GasCanisterVisuals.PressureState, 0); } else if (portNode.Air.Pressure < Atmospherics.OneAtmosphere) { appearance.SetData(GasCanisterVisuals.PressureState, 1); } else if (portNode.Air.Pressure < (15 * Atmospherics.OneAtmosphere)) { appearance.SetData(GasCanisterVisuals.PressureState, 2); } else { appearance.SetData(GasCanisterVisuals.PressureState, 3); } }