]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Improve Gas Yaml Serialization (#40070)
authorNemanja <98561806+EmoGarbage404@users.noreply.github.com>
Thu, 4 Sep 2025 18:48:46 +0000 (14:48 -0400)
committerGitHub <noreply@github.com>
Thu, 4 Sep 2025 18:48:46 +0000 (20:48 +0200)
* Make yaml gas serialization cleaner

* fix exception

* fix validation code

* rudimentary test & permissive loading

* change it a bit

* Test fixes and adjustments

13 files changed:
Content.IntegrationTests/Tests/Atmos/GasArrayTest.cs [new file with mode: 0644]
Content.Server/Atmos/EntitySystems/AtmosphereSystem.Gases.cs
Content.Server/Atmos/Reactions/GasReactionPrototype.cs
Content.Shared/Atmos/GasArraySerializer.cs [new file with mode: 0644]
Content.Shared/Atmos/GasMixture.cs
Resources/Prototypes/Atmospherics/reactions.yml
Resources/Prototypes/Catalog/Fills/Items/gas_tanks.yml
Resources/Prototypes/Entities/Clothing/Shoes/magboots.yml
Resources/Prototypes/Entities/Mobs/Player/mothershipcore.yml
Resources/Prototypes/Entities/Objects/Tools/jetpacks.yml
Resources/Prototypes/Entities/Objects/Weapons/Throwable/grenades.yml
Resources/Prototypes/Entities/Structures/Power/substation.yml
Resources/Prototypes/Entities/Structures/Storage/Canisters/gas_canisters.yml

diff --git a/Content.IntegrationTests/Tests/Atmos/GasArrayTest.cs b/Content.IntegrationTests/Tests/Atmos/GasArrayTest.cs
new file mode 100644 (file)
index 0000000..07caf44
--- /dev/null
@@ -0,0 +1,85 @@
+using System.Linq;
+using Content.Shared.Atmos;
+using Content.Shared.Atmos.Components;
+using Robust.Shared.GameObjects;
+using Robust.Shared.Prototypes;
+
+namespace Content.IntegrationTests.Tests.Atmos;
+
+[TestFixture]
+[TestOf(typeof(Atmospherics))]
+public sealed class GasArrayTest
+{
+    private const string GasTankTestDummyId = "GasTankTestDummy";
+
+    private const string GasTankLegacyTestDummyId = "GasTankLegacyTestDummy";
+
+    [TestPrototypes]
+    private const string Prototypes = $@"
+- type: entity
+  id: {GasTankTestDummyId}
+  components:
+  - type: GasTank
+    air:
+      volume: 5
+      moles:
+        Frezon: 20
+        Oxygen: 10
+
+- type: entity
+  id: {GasTankLegacyTestDummyId}
+  components:
+  - type: GasTank
+    air:
+      volume: 5
+      moles:
+      - 0
+      - 0
+      - 0
+      - 10
+";
+
+    [Test]
+    public async Task TestGasArrayDeserialization()
+    {
+        await using var pair = await PoolManager.GetServerClient();
+        var server = pair.Server;
+
+        var compFactory = server.ResolveDependency<IComponentFactory>();
+        var prototypeManager = server.ResolveDependency<IPrototypeManager>();
+
+        await server.WaitAssertion(() =>
+        {
+            var gasTank = prototypeManager.Index(GasTankTestDummyId);
+            Assert.Multiple(() =>
+            {
+                Assert.That(gasTank.TryGetComponent<GasTankComponent>(out var gasTankComponent, compFactory));
+
+                Assert.That(gasTankComponent!.Air.GetMoles(Gas.Oxygen), Is.EqualTo(10));
+                Assert.That(gasTankComponent!.Air.GetMoles(Gas.Frezon), Is.EqualTo(20));
+                foreach (var gas in Enum.GetValues<Gas>().Where(p => p != Gas.Oxygen && p != Gas.Frezon))
+                {
+                    Assert.That(gasTankComponent!.Air.GetMoles(gas), Is.EqualTo(0));
+                }
+            });
+
+            var legacyGasTank = prototypeManager.Index(GasTankLegacyTestDummyId);
+            Assert.Multiple(() =>
+            {
+                Assert.That(legacyGasTank.TryGetComponent<GasTankComponent>(out var gasTankComponent, compFactory));
+
+                Assert.That(gasTankComponent!.Air.GetMoles(3), Is.EqualTo(10));
+
+                // Iterate through all other gases: check for 0 values
+                for (var i = 0; i < Atmospherics.AdjustedNumberOfGases; i++)
+                {
+                    if (i == 3) // our case with a value.
+                        continue;
+
+                    Assert.That(gasTankComponent!.Air.GetMoles(i), Is.EqualTo(0));
+                }
+            });
+        });
+        await pair.CleanReturnAsync();
+    }
+}
index 6893940a97e6ef39954696d7c394b902a60dd93d..c5451866690c3276513daf45b5e9682be0b9e0db 100644 (file)
@@ -458,11 +458,8 @@ namespace Content.Server.Atmos.EntitySystems
                     continue;
 
                 var doReaction = true;
-                for (var i = 0; i < prototype.MinimumRequirements.Length; i++)
+                for (var i = 0; i < Atmospherics.TotalNumberOfGases; i++)
                 {
-                    if(i >= Atmospherics.TotalNumberOfGases)
-                        throw new IndexOutOfRangeException("Reaction Gas Minimum Requirements Array Prototype exceeds total number of gases!");
-
                     var req = prototype.MinimumRequirements[i];
 
                     if (!(mixture.GetMoles(i) < req))
index 48e32a3b589681a9de3416306526cdc380051680..dc7ba85dcc376eb52992a764325accf99022654c 100644 (file)
@@ -15,7 +15,7 @@ namespace Content.Server.Atmos.Reactions
         /// <summary>
         ///     Minimum gas amount requirements.
         /// </summary>
-        [DataField("minimumRequirements")]
+        [DataField("minimumRequirements", customTypeSerializer: typeof(GasArraySerializer))]
         public float[] MinimumRequirements { get; private set; } = new float[Atmospherics.TotalNumberOfGases];
 
         /// <summary>
diff --git a/Content.Shared/Atmos/GasArraySerializer.cs b/Content.Shared/Atmos/GasArraySerializer.cs
new file mode 100644 (file)
index 0000000..0834eed
--- /dev/null
@@ -0,0 +1,105 @@
+using Robust.Shared.Serialization;
+using Robust.Shared.Serialization.Manager;
+using Robust.Shared.Serialization.Markdown;
+using Robust.Shared.Serialization.Markdown.Mapping;
+using Robust.Shared.Serialization.Markdown.Sequence;
+using Robust.Shared.Serialization.Markdown.Validation;
+using Robust.Shared.Serialization.TypeSerializers.Interfaces;
+
+namespace Content.Shared.Atmos;
+
+public sealed class GasArraySerializer : ITypeSerializer<float[], SequenceDataNode>, ITypeSerializer<float[], MappingDataNode>
+{
+    public ValidationNode Validate(ISerializationManager serializationManager,
+        SequenceDataNode node,
+        IDependencyCollection dependencies,
+        ISerializationContext? context = null)
+    {
+        var list = new List<ValidationNode>();
+
+        foreach (var elem in node.Sequence)
+        {
+            list.Add(serializationManager.ValidateNode<float>(elem, context));
+        }
+
+        return new ValidatedSequenceNode(list);
+    }
+
+    public float[] Read(ISerializationManager serializationManager,
+        SequenceDataNode node,
+        IDependencyCollection dependencies,
+        SerializationHookContext hookCtx,
+        ISerializationContext? context = null,
+        ISerializationManager.InstantiationDelegate<float[]>? instanceProvider = null)
+    {
+        var list = instanceProvider != null ? instanceProvider() : new float[Atmospherics.AdjustedNumberOfGases];
+
+        for (var i = 0; i < node.Sequence.Count; i++)
+        {
+            list[i] = serializationManager.Read<float>(node.Sequence[i], hookCtx, context);
+        }
+
+        return list;
+    }
+
+    public ValidationNode Validate(ISerializationManager serializationManager,
+        MappingDataNode node,
+        IDependencyCollection dependencies,
+        ISerializationContext? context = null)
+    {
+        var dict = new Dictionary<ValidationNode, ValidationNode>();
+
+        foreach (var (key, value) in node.Children)
+        {
+            ValidationNode keyNode = Enum.TryParse<Gas>(key, out _)
+                ? new ValidatedValueNode(node.GetKeyNode(key))
+                : new ErrorNode(node.GetKeyNode(key), $"Failed to parse Gas: {key}");
+
+            dict.Add(keyNode, serializationManager.ValidateNode<float>(value, context));
+        }
+
+        return new ValidatedMappingNode(dict);
+    }
+
+    public float[] Read(ISerializationManager serializationManager,
+        MappingDataNode node,
+        IDependencyCollection dependencies,
+        SerializationHookContext hookCtx,
+        ISerializationContext? context = null,
+        ISerializationManager.InstantiationDelegate<float[]>? instanceProvider = null)
+    {
+        var list = instanceProvider != null ? instanceProvider() : new float[Atmospherics.AdjustedNumberOfGases];
+
+        foreach (var (gas, value) in node.Children)
+        {
+            // In the event that an invalid gas got serialized into something,
+            // we simply ignore it and continue reading.
+            // Errors should already be caught by Validate().
+            if (!Enum.TryParse<Gas>(gas, out var gasEnum))
+                continue;
+
+            list[(int)gasEnum] = serializationManager.Read<float>(value, hookCtx, context);
+        }
+
+        return list;
+    }
+
+    public DataNode Write(ISerializationManager serializationManager,
+        float[] value,
+        IDependencyCollection dependencies,
+        bool alwaysWrite = false,
+        ISerializationContext? context = null)
+    {
+        var mapping = new MappingDataNode();
+
+        for (var i = 0; i < Atmospherics.TotalNumberOfGases; i++)
+        {
+            if (value[i] <= 0)
+                continue;
+
+            mapping.Add(((Gas) i).ToString(), serializationManager.WriteValue(value[i], alwaysWrite, context));
+        }
+
+        return mapping;
+    }
+}
index 612626d614b78cdccd2b60968db5118a89fc9a15..3da7827cdd8e6da67146f92a4da2c06718e96a3e 100644 (file)
@@ -20,7 +20,7 @@ namespace Content.Shared.Atmos
 
         // No access, to ensure immutable mixtures are never accidentally mutated.
         [Access(typeof(SharedAtmosphereSystem), typeof(SharedAtmosDebugOverlaySystem), typeof(GasEnumerator), Other = AccessPermissions.None)]
-        [DataField]
+        [DataField(customTypeSerializer: typeof(GasArraySerializer))]
         public float[] Moles = new float[Atmospherics.AdjustedNumberOfGases];
 
         public float this[int gas] => Moles[gas];
index d226c81f6cc5fef04616cace99ee47089c5d6f9c..88c986ab970fbfa344a03815fd0956bdb8ac89ec 100644 (file)
@@ -3,10 +3,8 @@
   priority: -2
   minimumTemperature: 373.149 # Same as Atmospherics.FireMinimumTemperatureToExist
   minimumRequirements: # In this case, same as minimum mole count.
-    - 0.01  # oxygen
-    - 0     # nitrogen
-    - 0     # carbon dioxide
-    - 0.01  # plasma
+    Oxygen: 0.01
+    Plasma: 0.01
   effects:
     - !type:PlasmaFireReaction {}
 
   priority: -1
   minimumTemperature: 373.149 # Same as Atmospherics.FireMinimumTemperatureToExist
   minimumRequirements: # In this case, same as minimum mole count.
-    - 0.01  # oxygen
-    - 0     # nitrogen
-    - 0     # carbon dioxide
-    - 0     # plasma
-    - 0.01  # tritium
+    Oxygen: 0.01
+    Tritium: 0.01
   effects:
     - !type:TritiumFireReaction {}
 
   priority: 1
   minimumTemperature: 23.15
   minimumRequirements:
-  - 0     # oxygen
-  - 0.01  # nitrogen
-  - 0     # carbon dioxide
-  - 0     # plasma
-  - 0     # tritium
-  - 0     # vapor
-  - 0     # ammonia
-  - 0     # n2o
-  - 0.01  # frezon
+    Nitrogen: 0.01
+    Frezon: 0.01
   effects:
   - !type:FrezonCoolantReaction {}
 
   priority: 2
   maximumTemperature: 73.15 # Cold tritium fire, basically.
   minimumRequirements:
-  - 0.01  # oxygen
-  - 0.01  # nitrogen
-  - 0     # carbon dioxide
-  - 0     # plasma
-  - 0.01  # tritium
-  - 0     # vapor
-  - 0     # ammonia
-  - 0     # n2o
-  - 0     # frezon
+    Oxygen: 0.01
+    Nitrogen: 0.01
+    Tritium: 0.01
   effects:
   - !type:FrezonProductionReaction {}
 
   priority: 2
   minimumTemperature: 323.149
   minimumRequirements:
-  - 0.01  # oxygen
-  - 0     # nitrogen
-  - 0     # carbon dioxide
-  - 0     # plasma
-  - 0     # tritium
-  - 0     # vapor
-  - 0.01  # ammonia
-  - 0     # n2o
-  - 0     # frezon
+    Oxygen: 0.01
+    Ammonia: 0.01
   effects:
   - !type:AmmoniaOxygenReaction {}
 
   priority: 0
   minimumTemperature: 850
   minimumRequirements:
-  - 0     # oxygen
-  - 0     # nitrogen
-  - 0     # carbon dioxide
-  - 0     # plasma
-  - 0     # tritium
-  - 0     # vapor
-  - 0     # ammonia
-  - 0.01  # n2o
-  - 0     # frezon
+    NitrousOxide: 0.01
   effects:
   - !type:N2ODecompositionReaction {}
 
 #  priority: 1
 #  maximumTemperature: 373.13 # Boiling point of water.
 #  minimumRequirements: # In this case, same as minimum mole count.
-#    - 0  # oxygen
-#    - 0  # nitrogen
-#    - 0  # carbon dioxide
-#    - 0  # plasma
-#    - 0  # tritium
-#    - 1  # water vapor
+#    WaterVapor: 1
 #  effects:
 #    - !type:WaterVaporReaction
 #      gas: 5
index 2cf1354c143cf5b7e31aefc5e57edbf7b94ea5bd..2bbcc3b13dfd67456460b0f75ba58bc29dd82ba7 100644 (file)
@@ -31,7 +31,7 @@
       # 31 minutes
       volume: 5
       moles:
-        - 2.051379050 # oxygen
+        Oxygen: 2.051379050 # oxygen
       temperature: 293.15
 
 - type: entity
@@ -45,7 +45,7 @@
       # 4 minutes
       volume: 0.66
       moles:
-        - 0.270782035 # oxygen
+        Oxygen: 0.270782035 # oxygen
       temperature: 293.15
 
 - type: entity
@@ -59,8 +59,7 @@
       # 4 minutes
       volume: 0.66
       moles:
-        - 0 # oxygen
-        - 0.270782035 # nitrogen
+        Nitrogen: 0.270782035 # nitrogen
       temperature: 293.15
 
 
@@ -75,7 +74,7 @@
       # 9 minutes
       volume: 1.5
       moles:
-        - 0.615413715 # oxygen
+        Oxygen: 0.615413715 # oxygen
       temperature: 293.15
 
 - type: entity
@@ -89,8 +88,7 @@
       # 9 minutes
       volume: 1.5
       moles:
-        - 0 # oxygen
-        - 0.615413715 # nitrogen
+        Nitrogen: 0.615413715 # nitrogen
       temperature: 293.15
 
 
       # 15 minutes
       volume: 2.5
       moles:
-        - 1.025689525 # oxygen
+        Oxygen: 1.025689525 # oxygen
       temperature: 293.15
 
 - type: entity
       # 15 minutes
       volume: 2.5
       moles:
-        - 0 # oxygen
-        - 1.025689525 # nitrogen
+        Nitrogen: 1.025689525 # nitrogen
       temperature: 293.15
 
 - type: entity
       # 4 minutes
       volume: 0.66
       moles:
-        - 0.270782035 # 95% oxygen
-        - 0 # nitrogen
-        - 0 # CO2
-        - 0 # plasma
-        - 0 # tritium
-        - 0 # water vapor
-        - 0 # ammonia
-        - 0.014251686 # 5% N2O
-        # 0.285033721       total 
+        Oxygen: 0.270782035 # 95% oxygen
+        NitrousOxide: 0.014251686 # 5% N2O
+        # 0.285033721       total
       temperature: 293.15
 
 - type: entity
       # 6 minutes due to output pressure
       volume: 5
       moles:
-        - 0.451303391 # 22% oxygen
-        - 1.600075659 # 78% nitrogen
+        Oxygen: 0.451303391 # 22% oxygen
+        Nitrogen: 1.600075659 # 78% nitrogen
         # 2.051379050       total
       temperature: 293.15
 
       # 31 minutes
       volume: 5
       moles:
-        - 0           # oxygen not included
-        - 2.051379050 # nitrogen
+        Nitrogen: 2.051379050 # nitrogen
       temperature: 293.15
 
 - type: entity
       # only 22 minutes due to pressure
       volume: 5
       moles:
-        - 1.435965335 # 70% oxygen
-        - 0 # nitrogen
-        - 0 # CO2
-        - 0 # plasma
-        - 0 # tritium
-        - 0 # water vapor
-        - 0 # ammonia
-        - 0.615413715 # 30% N2O
+        Oxygen: 1.435965335 # 70% oxygen
+        NitrousOxide: 0.615413715 # 30% N2O
         # 2.051379050       total
       temperature: 293.15
 
       # 6 minutes of agony
       volume: 5
       moles:
-        - 0           # oxygen
-        - 0           # nitrogen
-        - 0           # CO2
-        - 2.051379050 # plasma
+        Plasma: 2.051379050
       temperature: 293.15
index 0e9873780fe6abf9adfb9c09044e795a0b2c957d..19a907f5d1de7cd1f960d4096c8c92d42a5f3ca0 100644 (file)
       volume: 0.75
       temperature: 293.15
       moles:
-      - 0.153853429 # oxygen
-      - 0.153853429 # nitrogen
+        Oxygen: 0.153853429 # oxygen
+        Nitrogen: 0.153853429 # nitrogen
   - type: Item
     sprite: null
     size: Normal
index 3535a55e7ffbf63d541aa31c439b86076b12156e..c557d38b36cc1311b25af3462ebf81fadd1da204 100644 (file)
@@ -77,9 +77,7 @@
         gasMixture:
           volume: 1000
           moles:
-            - 0 # oxygen
-            - 0 # nitrogen
-            - 340.5701689 # carbon dioxide
+            CarbonDioxide: 340.5701689 # carbon dioxide
           temperature: 373.15
   - type: Repairable
     doAfterDelay: 30 # you can heal the mothership core, but it takes a while
index fbe5b5a20873e86a455a8e74f4c3c8f35800ac36..5a6bc352c44dd09f15fec6c734843eb72a57497a 100644 (file)
       volume: 5
       temperature: 293.15
       moles:
-        - 1.025689525 # oxygen
-        - 1.025689525 # nitrogen
+        Oxygen: 1.025689525 # oxygen
+        Nitrogen: 1.025689525 # nitrogen
 
 #Empty black
 - type: entity
       volume: 5
       temperature: 293.15
       moles:
-        - 1.025689525 # oxygen
-        - 1.025689525 # nitrogen
+        Oxygen: 1.025689525 # oxygen
+        Nitrogen: 1.025689525 # nitrogen
 
 #Empty captain
 - type: entity
       volume: 5
       temperature: 293.15
       moles:
-        - 1.025689525 # oxygen
-        - 1.025689525 # nitrogen
+        Oxygen: 1.025689525 # oxygen
+        Nitrogen: 1.025689525 # nitrogen
 
 #Empty mini
 - type: entity
       volume: 1.5
       temperature: 293.15
       moles:
-        - 0.307706858 # oxygen
-        - 0.307706858 # nitrogen
+        Oxygen: 0.307706858 # oxygen
+        Nitrogen: 0.307706858 # nitrogen
 
 #Empty security
 - type: entity
       volume: 1.5
       temperature: 293.15
       moles:
-      - 0.307706858 # oxygen
-      - 0.307706858 # nitrogen
+        Oxygen: 0.307706858 # oxygen
+        Nitrogen: 0.307706858 # nitrogen
 
 #Empty void
 - type: entity
       volume: 5
       temperature: 293.15
       moles:
-        - 1.025689525 # oxygen
-        - 1.025689525 # nitrogen
+        Oxygen: 1.025689525 # oxygen
+        Nitrogen: 1.025689525 # nitrogen
 
 # Infinite jetpack
 - type: entity
index eb390bbff955a7a1a7ceb1f69b194513e7ede8f2..c1e87643bcb422a76907e01cfd885b7c9f88bf3f 100644 (file)
     air:
       volume: 1000
       moles: # Target is 3117.84 mols total for filling 30 tiles (goal is 101.325 kPa @ 20C)
-      - 654.7464 # oxygen
-      - 2463.0936 # nitrogen
+        Oxygen: 654.7464 # oxygen
+        Nitrogen: 2463.0936 # nitrogen
       temperature: 293.15
   - type: StaticPrice
     price: 350
index db1127021524a6afd70d37418510180bed7e7650..f2d86a3900d98d1998d900ff8b903dd20a4eb130 100644 (file)
         gasMixture:
           volume: 1000
           moles:
-          - 0 # oxygen
-          - 0 # nitrogen
-          - 340.5701689 # carbon dioxide
+            CarbonDioxide: 340.5701689 # carbon dioxide
           temperature: 373.15
   - type: Explosive
     explosionType: Default
index 2ab12c170504a7687bd80bb5e8570c18ed77d545..b37d3d4c4dc06eb2b462808b197b4926e6f0dba0 100644 (file)
     - type: GasCanister
       gasMixture:
         volume: 1500
-        moles: # List of gasses for easy reference
-          - 0 # oxygen
-          - 0 # nitrogen
-          - 0 # CO2
-          - 0 # Plasma
-          - 0 # Tritium
-          - 0 # Water vapor
-          - 0 # Ammonia
-          - 0 # N2O
-          - 0 # Frezon
         temperature: 293.15
     - type: Destructible
       thresholds:
     gasMixture:
       volume: 1500
       moles:
-      - 581.56 # oxygen 21%
-      - 2187.79 # nitrogen 79%
+        Oxygen: 581.56 # oxygen 21%
+        Nitrogen: 2187.79 # nitrogen 79%
       temperature: 293.15
   - type: Destructible
     thresholds:
     gasMixture:
       volume: 1500
       moles:
-      - 2769.36 # oxygen
+        Oxygen: 2769.36 # oxygen
       temperature: 293.15
   - type: Destructible
     thresholds:
     gasMixture:
       volume: 1500
       moles:
-        - 18710.71051 # oxygen
+        Oxygen: 18710.71051 # oxygen
       temperature: 72
   - type: AccessReader
     access: [["Atmospherics"]]
       gasMixture:
         volume: 1500
         moles:
-          - 0 # oxygen
-          - 2769.36 # nitrogen
+          Nitrogen: 2769.36 # nitrogen
         temperature: 293.15
     - type: Destructible
       thresholds:
     gasMixture:
       volume: 1500
       moles:
-        - 0 # oxygen
-        - 18710.71051 # nitrogen
+        Nitrogen: 18710.71051 # nitrogen
       temperature: 72
   - type: AccessReader
     access: [["Atmospherics"]]
       gasMixture:
         volume: 1500
         moles:
-          - 0 # oxygen
-          - 0 # nitrogen
-          - 2769.36 # CO2
+          CarbonDioxide: 2769.36 # CO2
         temperature: 293.15
     - type: Destructible
       thresholds:
     gasMixture:
       volume: 1500
       moles:
-        - 0 # oxygen
-        - 0 # nitrogen
-        - 18710.71051 # CO2
+        CarbonDioxide: 18710.71051 # CO2
       temperature: 72
   - type: AccessReader
     access: [["Atmospherics"]]
       gasMixture:
         volume: 1500
         moles:
-          - 0 # oxygen
-          - 0 # nitrogen
-          - 0 # carbon dioxide
-          - 2769.36 # plasma
+          Plasma: 2769.36 # plasma
         temperature: 293.15
     - type: Destructible
       thresholds:
       gasMixture:
         volume: 1500
         moles:
-          - 0 # oxygen
-          - 0 # nitrogen
-          - 0 # CO2
-          - 0 # Plasma
-          - 2769.36 # Tritium
+          Tritium: 2769.36 # Tritium
         temperature: 293.15
     - type: Destructible
       thresholds:
       gasMixture:
         volume: 1500
         moles:
-          - 0 # oxygen
-          - 0 # nitrogen
-          - 0 # CO2
-          - 0 # Plasma
-          - 0 # Tritium
-          - 2769.36 # Water vapor
+          WaterVapor: 2769.36 # Water vapor
         temperature: 293.15
     - type: Destructible
       thresholds:
       gasMixture:
         volume: 1500
         moles:
-          - 0 # oxygen
-          - 0 # nitrogen
-          - 0 # CO2
-          - 0 # Plasma
-          - 0 # Tritium
-          - 0 #  Water vapor
-          - 2769.36 # Ammonia
+          Ammonia: 2769.36 # Ammonia
         temperature: 293.15
     - type: Destructible
       thresholds:
       gasMixture:
         volume: 1500
         moles:
-          - 0 # oxygen
-          - 0 # nitrogen
-          - 0 # CO2
-          - 0 # Plasma
-          - 0 # Tritium
-          - 0 #  Water vapor
-          - 0 # Ammonia
-          - 2769.36 # N2O
+          NitrousOxide: 2769.36 # N2O
         temperature: 293.15
     - type: Destructible
       thresholds:
     gasMixture:
       volume: 1500
       moles:
-      - 0 # oxygen
-      - 0 # nitrogen
-      - 0 # CO2
-      - 0 # Plasma
-      - 0 # Tritium
-      - 0 # Water vapor
-      - 0 # Ammonia
-      - 0 # N2O
-      - 2769.36 # Frezon
+        Frezon: 2769.36 # Frezon
       temperature: 293.15
   - type: Destructible
     thresholds: