Gas Condensers (#22436)

Co-authored-by: Kevin Zheng <kevinz5000@gmail.com>
This commit is contained in:
Nemanja
2023-12-13 22:35:44 -05:00
committed by GitHub
parent 0f2e9ef4df
commit 0917a9d380
21 changed files with 294 additions and 0 deletions

View File

@@ -0,0 +1,33 @@
using Content.Server.Atmos.Piping.Unary.EntitySystems;
namespace Content.Server.Atmos.Piping.Unary.Components;
/// <summary>
/// Used for an entity that converts moles of gas into units of reagent.
/// </summary>
[RegisterComponent]
[Access(typeof(GasCondenserSystem))]
public sealed partial class GasCondenserComponent : Component
{
/// <summary>
/// The ID for the pipe node.
/// </summary>
[DataField]
public string Inlet = "pipe";
/// <summary>
/// The ID for the solution.
/// </summary>
[DataField]
public string SolutionId = "tank";
/// <summary>
/// For a condenser, how many U of reagents are given per each mole of gas.
/// </summary>
/// <remarks>
/// Derived from a standard of 500u per canister:
/// 400u / 1871.71051 moles per canister
/// </remarks>
[DataField, ViewVariables(VVAccess.ReadWrite)]
public float MolesToReagentMultiplier = 0.2137f;
}

View File

@@ -0,0 +1,73 @@
using Content.Server.Atmos.EntitySystems;
using Content.Server.Atmos.Piping.Components;
using Content.Server.Atmos.Piping.Unary.Components;
using Content.Server.NodeContainer;
using Content.Server.NodeContainer.EntitySystems;
using Content.Server.NodeContainer.Nodes;
using Content.Server.Power.Components;
using Content.Shared.Atmos;
using JetBrains.Annotations;
using Content.Server.Power.EntitySystems;
using Content.Shared.Chemistry.EntitySystems;
namespace Content.Server.Atmos.Piping.Unary.EntitySystems;
[UsedImplicitly]
public sealed class GasCondenserSystem : EntitySystem
{
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
[Dependency] private readonly PowerReceiverSystem _power = default!;
[Dependency] private readonly NodeContainerSystem _nodeContainer = default!;
[Dependency] private readonly SolutionContainerSystem _solution = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<GasCondenserComponent, AtmosDeviceUpdateEvent>(OnCondenserUpdated);
}
private void OnCondenserUpdated(EntityUid uid, GasCondenserComponent component, AtmosDeviceUpdateEvent args)
{
if (!(_power.IsPowered(uid) && TryComp<ApcPowerReceiverComponent>(uid, out var receiver))
|| !TryComp<NodeContainerComponent>(uid, out var nodeContainer)
|| !_nodeContainer.TryGetNode(nodeContainer, component.Inlet, out PipeNode? inlet)
|| !_solution.TryGetSolution(uid, component.SolutionId, out var solution))
{
return;
}
if (solution.AvailableVolume == 0 || inlet.Air.TotalMoles == 0)
return;
var molesToConvert = NumberOfMolesToConvert(receiver, inlet.Air, args.dt);
var removed = inlet.Air.Remove(molesToConvert);
for (var i = 0; i < Atmospherics.TotalNumberOfGases; i++)
{
var moles = removed.Moles[i];
if (moles <= 0)
continue;
if (_atmosphereSystem.GetGas(i).Reagent is not {} gasReagent)
continue;
var moleToReagentMultiplier = component.MolesToReagentMultiplier;
var amount = moles * moleToReagentMultiplier;
if (_solution.TryAddReagent(uid, solution, gasReagent, amount, out var remaining))
continue;
// if we have leftover reagent, then convert it back to moles and put it back in the mixture.
inlet.Air.AdjustMoles(i, remaining.Float() / moleToReagentMultiplier);
}
}
public float NumberOfMolesToConvert(ApcPowerReceiverComponent comp, GasMixture mix, float dt)
{
var hc = _atmosphereSystem.GetHeatCapacity(mix);
var alpha = 0.8f; // tuned to give us 1-ish u/second of reagent conversion
// ignores the energy needed to cool down the solution to the condensation point, but that probably adds too much difficulty and so let's not simulate that
var energy = comp.Load * dt;
return energy / (alpha * hc);
}
}

View File

@@ -374,6 +374,22 @@ public sealed partial class SolutionContainerSystem : EntitySystem
return acceptedQuantity == reagentQuantity.Quantity;
}
/// <summary>
/// Adds reagent of an Id to the container.
/// </summary>
/// <param name="targetUid"></param>
/// <param name="targetSolution">Container to which we are adding reagent</param>
/// <param name="prototype">The Id of the reagent to add.</param>
/// <param name="quantity">The amount of reagent to add.</param>
/// <returns>If all the reagent could be added.</returns>
[PublicAPI]
public bool TryAddReagent(EntityUid targetUid, Solution targetSolution, string prototype, FixedPoint2 quantity,
float? temperature = null, ReagentData? data = null)
{
var reagent = new ReagentQuantity(prototype, quantity, data);
return TryAddReagent(targetUid, targetSolution, reagent, out _, temperature);
}
/// <summary>
/// Adds reagent of an Id to the container.
/// </summary>

View File

@@ -3,6 +3,7 @@ wires-board-name-default = Wires
wires-board-name-booze = BoozeDispenser
wires-board-name-soda = SodaDispenser
wires-board-name-thermomachine = Thermomachine
wires-board-name-condenser = Condenser
wires-board-name-pa = Mk2 Particle Accelerator
wires-board-name-highsec = HighSec Control
wires-board-name-vessel = Vessel

View File

@@ -338,6 +338,21 @@
deconstructionTarget: null
node: heater
- type: entity
id: CondenserMachineCircuitBoard
parent: BaseMachineCircuitboard
name: condenser machine board
description: A machine printed circuit board for a condenser.
components:
- type: Sprite
state: engineering
- type: MachineBoard
prototype: BaseGasCondenser
requirements:
MatterBin: 1
materialRequirements:
Glass: 1
- type: entity
id: PortableScrubberMachineCircuitBoard
parent: BaseMachineCircuitboard

View File

@@ -306,6 +306,8 @@
producingSound: /Audio/Machines/circuitprinter.ogg
idleState: icon
runningState: building
staticRecipes:
- CondenserMachineCircuitBoard
dynamicRecipes:
- ThermomachineFreezerMachineCircuitBoard
- PortableScrubberMachineCircuitBoard

View File

@@ -351,3 +351,89 @@
enabled: true
- type: ApcPowerReceiver
powerDisabled: false
- type: entity
parent: [ BaseMachinePowered, ConstructibleMachine ]
id: BaseGasCondenser
name: condenser
description: Condenses gases into liquids. Now we just need some plumbing.
placement:
mode: SnapgridCenter
components:
- type: Sprite
sprite: Structures/Piping/Atmospherics/condenser.rsi
snapCardinals: true
granularLayersRendering: true
layers:
- state: off
map: [ "enum.PowerDeviceVisualLayers.Powered" ]
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- state: pipe
map: [ "enum.PipeVisualLayers.Pipe" ]
renderingStrategy: Default
- state: fill-1
map: ["enum.SolutionContainerLayers.Fill"]
visible: false
- state: trans
- type: GenericVisualizer
visuals:
enum.PowerDeviceVisuals.Powered:
enum.PowerDeviceVisualLayers.Powered:
True: { state: on }
False: { state: off }
- type: SolutionContainerVisuals
maxFillLevels: 7
fillBaseName: fill-
- type: Appearance
- type: PipeColorVisuals
- type: Rotatable
- type: GasCondenser
- type: AtmosPipeColor
- type: AtmosDevice
- type: ApcPowerReceiver
powerLoad: 10000
- type: Machine
board: CondenserMachineCircuitBoard
- type: WiresPanel
- type: Wires
boardName: wires-board-name-condenser
layoutId: Condenser
- type: WiresVisuals
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 200
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- trigger:
!type:DamageTrigger
damage: 100
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- !type:SpillBehavior
solution: tank
- !type:PlaySoundBehavior
sound:
path: /Audio/Effects/metalbreak.ogg
- type: NodeContainer
nodes:
pipe:
!type:PipeNode
nodeGroupID: Pipe
pipeDirection: South
- type: Transform
noRot: false
- type: SolutionContainerManager
solutions:
tank:
maxVol: 400
canMix: true
- type: DrainableSolution
solution: tank
- type: ExaminableSolution
solution: tank
- type: PowerSwitch

View File

@@ -104,6 +104,14 @@
Glass: 900
Gold: 50
- type: latheRecipe
id: CondenserMachineCircuitBoard
result: CondenserMachineCircuitBoard
completetime: 4
materials:
Steel: 100
Glass: 900
- type: latheRecipe
id: PortableScrubberMachineCircuitBoard
result: PortableScrubberMachineCircuitBoard

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 B

View File

@@ -0,0 +1,60 @@
{
"version":1,
"size":
{
"x":32,
"y":32
},
"copyright":"Created by EmoGarbage404 (github) for Space Station 14.",
"license":"CC0-1.0",
"states":
[
{
"name":"off"
},
{
"name":"on",
"delays":
[
[
0.05,
0.05,
0.05,
0.05,
0.05
]
]
},
{
"name":"panel"
},
{
"name":"trans"
},
{
"name":"pipe",
"directions":4
},
{
"name":"fill-1"
},
{
"name":"fill-2"
},
{
"name":"fill-3"
},
{
"name":"fill-4"
},
{
"name":"fill-5"
},
{
"name":"fill-6"
},
{
"name":"fill-7"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 687 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 272 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 346 B