Add reagent sources to the guidebook (#22627)
* source in my guidebook * finish it! * sir yes sir oorah * network that bitch, baby
This commit is contained in:
@@ -1,16 +1,39 @@
|
|||||||
using Content.Shared.Chemistry;
|
using System.Linq;
|
||||||
|
using Content.Shared.Atmos.Prototypes;
|
||||||
|
using Content.Shared.Body.Part;
|
||||||
|
using Content.Shared.Chemistry;
|
||||||
|
using Content.Shared.Chemistry.Components;
|
||||||
|
using Content.Shared.Chemistry.Components.SolutionManager;
|
||||||
|
using Content.Shared.Chemistry.Reaction;
|
||||||
|
using Content.Shared.Chemistry.Reagent;
|
||||||
|
using Content.Shared.Kitchen.Components;
|
||||||
|
using Content.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
namespace Content.Client.Chemistry.EntitySystems;
|
namespace Content.Client.Chemistry.EntitySystems;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public sealed class ChemistryGuideDataSystem : SharedChemistryGuideDataSystem
|
public sealed class ChemistryGuideDataSystem : SharedChemistryGuideDataSystem
|
||||||
{
|
{
|
||||||
|
[ValidatePrototypeId<MixingCategoryPrototype>]
|
||||||
|
private const string DefaultMixingCategory = "DummyMix";
|
||||||
|
[ValidatePrototypeId<MixingCategoryPrototype>]
|
||||||
|
private const string DefaultGrindCategory = "DummyGrind";
|
||||||
|
[ValidatePrototypeId<MixingCategoryPrototype>]
|
||||||
|
private const string DefaultJuiceCategory = "DummyJuice";
|
||||||
|
[ValidatePrototypeId<MixingCategoryPrototype>]
|
||||||
|
private const string DefaultCondenseCategory = "DummyCondense";
|
||||||
|
|
||||||
|
private readonly Dictionary<string, List<ReagentSourceData>> _reagentSources = new();
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
SubscribeNetworkEvent<ReagentGuideRegistryChangedEvent>(OnReceiveRegistryUpdate);
|
SubscribeNetworkEvent<ReagentGuideRegistryChangedEvent>(OnReceiveRegistryUpdate);
|
||||||
|
SubscribeLocalEvent<PrototypesReloadedEventArgs>(OnPrototypesReloaded);
|
||||||
|
OnPrototypesReloaded(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnReceiveRegistryUpdate(ReagentGuideRegistryChangedEvent message)
|
private void OnReceiveRegistryUpdate(ReagentGuideRegistryChangedEvent message)
|
||||||
@@ -26,4 +49,176 @@ public sealed class ChemistryGuideDataSystem : SharedChemistryGuideDataSystem
|
|||||||
Registry[key] = val;
|
Registry[key] = val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnPrototypesReloaded(PrototypesReloadedEventArgs? ev)
|
||||||
|
{
|
||||||
|
// this doesn't check what prototypes are being reloaded because, to be frank, we use a lot of them.
|
||||||
|
_reagentSources.Clear();
|
||||||
|
foreach (var reagent in PrototypeManager.EnumeratePrototypes<ReagentPrototype>())
|
||||||
|
{
|
||||||
|
_reagentSources.Add(reagent.ID, new());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (var reaction in PrototypeManager.EnumeratePrototypes<ReactionPrototype>())
|
||||||
|
{
|
||||||
|
if (!reaction.Source)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var data = new ReagentReactionSourceData(
|
||||||
|
reaction.MixingCategories ?? new () { DefaultMixingCategory },
|
||||||
|
reaction);
|
||||||
|
foreach (var product in reaction.Products.Keys)
|
||||||
|
{
|
||||||
|
_reagentSources[product].Add(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var gas in PrototypeManager.EnumeratePrototypes<GasPrototype>())
|
||||||
|
{
|
||||||
|
if (gas.Reagent == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var data = new ReagentGasSourceData(
|
||||||
|
new () { DefaultCondenseCategory },
|
||||||
|
gas);
|
||||||
|
_reagentSources[gas.Reagent].Add(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// store the names of the entities used so we don't get repeats in the guide.
|
||||||
|
var usedNames = new List<string>();
|
||||||
|
foreach (var entProto in PrototypeManager.EnumeratePrototypes<EntityPrototype>())
|
||||||
|
{
|
||||||
|
if (entProto.Abstract || usedNames.Contains(entProto.Name))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!entProto.TryGetComponent<ExtractableComponent>(out var extractableComponent))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
//these bloat the hell out of blood/fat
|
||||||
|
if (entProto.HasComponent<BodyPartComponent>())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
//these feel obvious...
|
||||||
|
if (entProto.HasComponent<PillComponent>())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (extractableComponent.JuiceSolution is { } juiceSolution)
|
||||||
|
{
|
||||||
|
var data = new ReagentEntitySourceData(
|
||||||
|
new() { DefaultJuiceCategory },
|
||||||
|
entProto,
|
||||||
|
juiceSolution);
|
||||||
|
foreach (var (id, _) in juiceSolution.Contents)
|
||||||
|
{
|
||||||
|
_reagentSources[id.Prototype].Add(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
usedNames.Add(entProto.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extractableComponent.GrindableSolution is { } grindableSolutionId &&
|
||||||
|
entProto.TryGetComponent<SolutionContainerManagerComponent>(out var manager) &&
|
||||||
|
manager.Solutions.TryGetValue(grindableSolutionId, out var grindableSolution))
|
||||||
|
{
|
||||||
|
var data = new ReagentEntitySourceData(
|
||||||
|
new() { DefaultGrindCategory },
|
||||||
|
entProto,
|
||||||
|
grindableSolution);
|
||||||
|
foreach (var (id, _) in grindableSolution.Contents)
|
||||||
|
{
|
||||||
|
_reagentSources[id.Prototype].Add(data);
|
||||||
|
}
|
||||||
|
usedNames.Add(entProto.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ReagentSourceData> GetReagentSources(string id)
|
||||||
|
{
|
||||||
|
return _reagentSources.GetValueOrDefault(id) ?? new List<ReagentSourceData>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A generic class meant to hold information about a reagent source.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class ReagentSourceData
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The mixing type that applies to this source.
|
||||||
|
/// </summary>
|
||||||
|
public readonly IReadOnlyList<ProtoId<MixingCategoryPrototype>> MixingType;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The number of distinct outputs. Used for primary ordering.
|
||||||
|
/// </summary>
|
||||||
|
public abstract int OutputCount { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A text string corresponding to this source. Typically a name. Used for secondary ordering.
|
||||||
|
/// </summary>
|
||||||
|
public abstract string IdentifierString { get; }
|
||||||
|
|
||||||
|
protected ReagentSourceData(List<ProtoId<MixingCategoryPrototype>> mixingType)
|
||||||
|
{
|
||||||
|
MixingType = mixingType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Used to store a reagent source that's an entity with a corresponding solution.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class ReagentEntitySourceData : ReagentSourceData
|
||||||
|
{
|
||||||
|
public readonly EntityPrototype SourceEntProto;
|
||||||
|
|
||||||
|
public readonly Solution Solution;
|
||||||
|
|
||||||
|
public override int OutputCount => Solution.Contents.Count;
|
||||||
|
|
||||||
|
public override string IdentifierString => SourceEntProto.Name;
|
||||||
|
|
||||||
|
public ReagentEntitySourceData(List<ProtoId<MixingCategoryPrototype>> mixingType, EntityPrototype sourceEntProto, Solution solution)
|
||||||
|
: base(mixingType)
|
||||||
|
{
|
||||||
|
SourceEntProto = sourceEntProto;
|
||||||
|
Solution = solution;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Used to store a reagent source that comes from a reaction between multiple reagents.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class ReagentReactionSourceData : ReagentSourceData
|
||||||
|
{
|
||||||
|
public readonly ReactionPrototype ReactionPrototype;
|
||||||
|
|
||||||
|
public override int OutputCount => ReactionPrototype.Products.Count + ReactionPrototype.Reactants.Count(r => r.Value.Catalyst);
|
||||||
|
|
||||||
|
public override string IdentifierString => ReactionPrototype.ID;
|
||||||
|
|
||||||
|
public ReagentReactionSourceData(List<ProtoId<MixingCategoryPrototype>> mixingType, ReactionPrototype reactionPrototype)
|
||||||
|
: base(mixingType)
|
||||||
|
{
|
||||||
|
ReactionPrototype = reactionPrototype;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Used to store a reagent source that comes from gas condensation.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class ReagentGasSourceData : ReagentSourceData
|
||||||
|
{
|
||||||
|
public readonly GasPrototype GasPrototype;
|
||||||
|
|
||||||
|
public override int OutputCount => 1;
|
||||||
|
|
||||||
|
public override string IdentifierString => Loc.GetString(GasPrototype.Name);
|
||||||
|
|
||||||
|
public ReagentGasSourceData(List<ProtoId<MixingCategoryPrototype>> mixingType, GasPrototype gasPrototype)
|
||||||
|
: base(mixingType)
|
||||||
|
{
|
||||||
|
GasPrototype = gasPrototype;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,19 @@
|
|||||||
<CollapsibleHeading Title="{Loc 'guidebook-reagent-recipes-header'}"/>
|
<CollapsibleHeading Title="{Loc 'guidebook-reagent-recipes-header'}"/>
|
||||||
<CollapsibleBody>
|
<CollapsibleBody>
|
||||||
<GridContainer Name="RecipesDescriptionContainer"
|
<GridContainer Name="RecipesDescriptionContainer"
|
||||||
|
Margin="10 0 10 0"
|
||||||
|
Columns="1"
|
||||||
|
HSeparationOverride="0"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
HorizontalExpand="True"/>
|
||||||
|
</CollapsibleBody>
|
||||||
|
</Collapsible>
|
||||||
|
</BoxContainer>
|
||||||
|
<BoxContainer Name="SourcesContainer" HorizontalExpand="True">
|
||||||
|
<Collapsible Orientation="Vertical" HorizontalExpand="True">
|
||||||
|
<CollapsibleHeading Title="{Loc 'guidebook-reagent-sources-header'}"/>
|
||||||
|
<CollapsibleBody>
|
||||||
|
<GridContainer Name="SourcesDescriptionContainer"
|
||||||
Margin="10 0 10 0"
|
Margin="10 0 10 0"
|
||||||
Columns="1"
|
Columns="1"
|
||||||
HSeparationOverride="5"
|
HSeparationOverride="5"
|
||||||
|
|||||||
@@ -6,10 +6,8 @@ using Content.Client.Message;
|
|||||||
using Content.Client.UserInterface.ControlExtensions;
|
using Content.Client.UserInterface.ControlExtensions;
|
||||||
using Content.Shared.Chemistry.Reaction;
|
using Content.Shared.Chemistry.Reaction;
|
||||||
using Content.Shared.Chemistry.Reagent;
|
using Content.Shared.Chemistry.Reagent;
|
||||||
using Content.Shared.Localizations;
|
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Client.AutoGenerated;
|
using Robust.Client.AutoGenerated;
|
||||||
using Robust.Client.GameObjects;
|
|
||||||
using Robust.Client.Graphics;
|
using Robust.Client.Graphics;
|
||||||
using Robust.Client.UserInterface;
|
using Robust.Client.UserInterface;
|
||||||
using Robust.Client.UserInterface.Controls;
|
using Robust.Client.UserInterface.Controls;
|
||||||
@@ -99,7 +97,7 @@ public sealed partial class GuideReagentEmbed : BoxContainer, IDocumentTag, ISea
|
|||||||
|
|
||||||
#region Recipe
|
#region Recipe
|
||||||
var reactions = _prototype.EnumeratePrototypes<ReactionPrototype>()
|
var reactions = _prototype.EnumeratePrototypes<ReactionPrototype>()
|
||||||
.Where(p => p.Products.ContainsKey(reagent.ID))
|
.Where(p => !p.Source && p.Products.ContainsKey(reagent.ID))
|
||||||
.OrderBy(p => p.Priority)
|
.OrderBy(p => p.Priority)
|
||||||
.ThenBy(p => p.Products.Count)
|
.ThenBy(p => p.Products.Count)
|
||||||
.ToList();
|
.ToList();
|
||||||
@@ -108,8 +106,7 @@ public sealed partial class GuideReagentEmbed : BoxContainer, IDocumentTag, ISea
|
|||||||
{
|
{
|
||||||
foreach (var reactionPrototype in reactions)
|
foreach (var reactionPrototype in reactions)
|
||||||
{
|
{
|
||||||
var ctrl = GetRecipeGuide(reactionPrototype);
|
RecipesDescriptionContainer.AddChild(new GuideReagentReaction(reactionPrototype, _prototype, _systemManager));
|
||||||
RecipesDescriptionContainer.AddChild(ctrl);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -159,6 +156,8 @@ public sealed partial class GuideReagentEmbed : BoxContainer, IDocumentTag, ISea
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
GenerateSources(reagent);
|
||||||
|
|
||||||
FormattedMessage description = new();
|
FormattedMessage description = new();
|
||||||
description.AddText(reagent.LocalizedDescription);
|
description.AddText(reagent.LocalizedDescription);
|
||||||
description.PushNewline();
|
description.PushNewline();
|
||||||
@@ -167,64 +166,45 @@ public sealed partial class GuideReagentEmbed : BoxContainer, IDocumentTag, ISea
|
|||||||
ReagentDescription.SetMessage(description);
|
ReagentDescription.SetMessage(description);
|
||||||
}
|
}
|
||||||
|
|
||||||
private GuideReagentReaction GetRecipeGuide(ReactionPrototype reactionPrototype)
|
private void GenerateSources(ReagentPrototype reagent)
|
||||||
{
|
{
|
||||||
var control = new GuideReagentReaction();
|
var sources = _chemistryGuideData.GetReagentSources(reagent.ID);
|
||||||
|
if (sources.Count == 0)
|
||||||
var reactantMsg = new FormattedMessage();
|
|
||||||
var reactantsCount = reactionPrototype.Reactants.Count;
|
|
||||||
var i = 0;
|
|
||||||
foreach (var (product, reactant) in reactionPrototype.Reactants)
|
|
||||||
{
|
{
|
||||||
reactantMsg.AddMarkup(Loc.GetString("guidebook-reagent-recipes-reagent-display",
|
SourcesContainer.Visible = false;
|
||||||
("reagent", _prototype.Index<ReagentPrototype>(product).LocalizedName), ("ratio", reactant.Amount)));
|
return;
|
||||||
i++;
|
|
||||||
if (i < reactantsCount)
|
|
||||||
reactantMsg.PushNewline();
|
|
||||||
}
|
}
|
||||||
reactantMsg.Pop();
|
SourcesContainer.Visible = true;
|
||||||
control.ReactantsLabel.SetMessage(reactantMsg);
|
|
||||||
|
|
||||||
var productMsg = new FormattedMessage();
|
var orderedSources = sources
|
||||||
var productCount = reactionPrototype.Products.Count;
|
.OrderBy(o => o.OutputCount)
|
||||||
var u = 0;
|
.ThenBy(o => o.IdentifierString);
|
||||||
foreach (var (product, ratio) in reactionPrototype.Products)
|
foreach (var source in orderedSources)
|
||||||
{
|
{
|
||||||
productMsg.AddMarkup(Loc.GetString("guidebook-reagent-recipes-reagent-display",
|
if (source is ReagentEntitySourceData entitySourceData)
|
||||||
("reagent", _prototype.Index<ReagentPrototype>(product).LocalizedName), ("ratio", ratio)));
|
|
||||||
u++;
|
|
||||||
if (u < productCount)
|
|
||||||
productMsg.PushNewline();
|
|
||||||
}
|
|
||||||
productMsg.Pop();
|
|
||||||
control.ProductsLabel.SetMessage(productMsg);
|
|
||||||
|
|
||||||
var mixingCategories = new List<MixingCategoryPrototype>();
|
|
||||||
if (reactionPrototype.MixingCategories != null)
|
|
||||||
{
|
{
|
||||||
foreach (var category in reactionPrototype.MixingCategories)
|
SourcesDescriptionContainer.AddChild(new GuideReagentReaction(
|
||||||
|
entitySourceData.SourceEntProto,
|
||||||
|
entitySourceData.Solution,
|
||||||
|
entitySourceData.MixingType,
|
||||||
|
_prototype,
|
||||||
|
_systemManager));
|
||||||
|
}
|
||||||
|
else if (source is ReagentReactionSourceData reactionSourceData)
|
||||||
{
|
{
|
||||||
mixingCategories.Add(_prototype.Index(category));
|
SourcesDescriptionContainer.AddChild(new GuideReagentReaction(
|
||||||
|
reactionSourceData.ReactionPrototype,
|
||||||
|
_prototype,
|
||||||
|
_systemManager));
|
||||||
}
|
}
|
||||||
}
|
else if (source is ReagentGasSourceData gasSourceData)
|
||||||
|
|
||||||
// only use the first one for the icon.
|
|
||||||
if (mixingCategories.FirstOrDefault() is { } primaryCategory)
|
|
||||||
{
|
{
|
||||||
control.MixTexture.Texture = _systemManager.GetEntitySystem<SpriteSystem>().Frame0(primaryCategory.Icon);
|
SourcesDescriptionContainer.AddChild(new GuideReagentReaction(
|
||||||
}
|
gasSourceData.GasPrototype,
|
||||||
|
gasSourceData.MixingType,
|
||||||
var mixingVerb = mixingCategories.Count == 0
|
_prototype,
|
||||||
? Loc.GetString("guidebook-reagent-recipes-mix")
|
_systemManager));
|
||||||
: ContentLocalizationManager.FormatList(mixingCategories.Select(p => Loc.GetString(p.VerbText)).ToList());
|
}
|
||||||
|
}
|
||||||
var text = Loc.GetString("guidebook-reagent-recipes-mix-info",
|
|
||||||
("verb", mixingVerb),
|
|
||||||
("minTemp", reactionPrototype.MinimumTemperature),
|
|
||||||
("maxTemp", reactionPrototype.MaximumTemperature),
|
|
||||||
("hasMax", !float.IsPositiveInfinity(reactionPrototype.MaximumTemperature)));
|
|
||||||
|
|
||||||
control.MixLabel.SetMarkup(text);
|
|
||||||
return control;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
<BoxContainer xmlns="https://spacestation14.io"
|
<BoxContainer xmlns="https://spacestation14.io"
|
||||||
Orientation="Horizontal"
|
Orientation="Horizontal"
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
HorizontalExpand="True">
|
HorizontalExpand="True"
|
||||||
<BoxContainer Orientation="Vertical" HorizontalExpand="True" VerticalAlignment="Center">
|
Margin="0 0 0 5">
|
||||||
|
<BoxContainer Name="ReactantsContainer" Orientation="Vertical" HorizontalExpand="True" VerticalAlignment="Center">
|
||||||
<RichTextLabel Name="ReactantsLabel"
|
<RichTextLabel Name="ReactantsLabel"
|
||||||
HorizontalAlignment="Center"
|
HorizontalAlignment="Center"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Access="Public"/>
|
Access="Public"
|
||||||
|
Visible="False"/>
|
||||||
</BoxContainer>
|
</BoxContainer>
|
||||||
<BoxContainer Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
|
<BoxContainer Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||||
<TextureRect TexturePath="/Textures/Interface/Misc/beakerlarge.png"
|
<TextureRect TexturePath="/Textures/Interface/Misc/beakerlarge.png"
|
||||||
@@ -22,6 +24,7 @@
|
|||||||
<RichTextLabel Name="ProductsLabel"
|
<RichTextLabel Name="ProductsLabel"
|
||||||
HorizontalAlignment="Center"
|
HorizontalAlignment="Center"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Access="Public"/>
|
Access="Public"
|
||||||
|
Visible="False"/>
|
||||||
</BoxContainer>
|
</BoxContainer>
|
||||||
</BoxContainer>
|
</BoxContainer>
|
||||||
|
|||||||
@@ -1,13 +1,206 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using Content.Client.Message;
|
||||||
using Content.Client.UserInterface.ControlExtensions;
|
using Content.Client.UserInterface.ControlExtensions;
|
||||||
|
using Content.Shared.Atmos.Prototypes;
|
||||||
|
using Content.Shared.Chemistry.Components;
|
||||||
|
using Content.Shared.Chemistry.Reaction;
|
||||||
|
using Content.Shared.Chemistry.Reagent;
|
||||||
|
using Content.Shared.FixedPoint;
|
||||||
|
using Content.Shared.Localizations;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Client.AutoGenerated;
|
using Robust.Client.AutoGenerated;
|
||||||
|
using Robust.Client.GameObjects;
|
||||||
using Robust.Client.UserInterface.Controls;
|
using Robust.Client.UserInterface.Controls;
|
||||||
|
using Robust.Client.UserInterface.XAML;
|
||||||
|
using Robust.Shared.Graphics.RSI;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
namespace Content.Client.Guidebook.Controls;
|
namespace Content.Client.Guidebook.Controls;
|
||||||
|
|
||||||
[UsedImplicitly, GenerateTypedNameReferences]
|
[UsedImplicitly, GenerateTypedNameReferences]
|
||||||
public sealed partial class GuideReagentReaction : BoxContainer, ISearchableControl
|
public sealed partial class GuideReagentReaction : BoxContainer, ISearchableControl
|
||||||
{
|
{
|
||||||
|
[ValidatePrototypeId<MixingCategoryPrototype>]
|
||||||
|
private const string DefaultMixingCategory = "DummyMix";
|
||||||
|
|
||||||
|
private readonly IPrototypeManager _protoMan;
|
||||||
|
|
||||||
|
public GuideReagentReaction(IPrototypeManager protoMan)
|
||||||
|
{
|
||||||
|
RobustXamlLoader.Load(this);
|
||||||
|
_protoMan = protoMan;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GuideReagentReaction(ReactionPrototype prototype, IPrototypeManager protoMan, IEntitySystemManager sysMan) : this(protoMan)
|
||||||
|
{
|
||||||
|
var reactantsLabel = ReactantsLabel;
|
||||||
|
SetReagents(prototype.Reactants, ref reactantsLabel, protoMan);
|
||||||
|
var productLabel = ProductsLabel;
|
||||||
|
var products = new Dictionary<string, FixedPoint2>(prototype.Products);
|
||||||
|
foreach (var (reagent, reactantProto) in prototype.Reactants)
|
||||||
|
{
|
||||||
|
if (reactantProto.Catalyst)
|
||||||
|
products.Add(reagent, reactantProto.Amount);
|
||||||
|
}
|
||||||
|
SetReagents(products, ref productLabel, protoMan);
|
||||||
|
|
||||||
|
var mixingCategories = new List<MixingCategoryPrototype>();
|
||||||
|
if (prototype.MixingCategories != null)
|
||||||
|
{
|
||||||
|
foreach (var category in prototype.MixingCategories)
|
||||||
|
{
|
||||||
|
mixingCategories.Add(protoMan.Index(category));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mixingCategories.Add(protoMan.Index<MixingCategoryPrototype>(DefaultMixingCategory));
|
||||||
|
}
|
||||||
|
SetMixingCategory(mixingCategories, prototype, sysMan);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GuideReagentReaction(EntityPrototype prototype,
|
||||||
|
Solution solution,
|
||||||
|
IReadOnlyList<ProtoId<MixingCategoryPrototype>> categories,
|
||||||
|
IPrototypeManager protoMan,
|
||||||
|
IEntitySystemManager sysMan) : this(protoMan)
|
||||||
|
{
|
||||||
|
var icon = sysMan.GetEntitySystem<SpriteSystem>().GetPrototypeIcon(prototype).GetFrame(RsiDirection.South, 0);
|
||||||
|
var entContainer = new BoxContainer
|
||||||
|
{
|
||||||
|
Orientation = LayoutOrientation.Horizontal,
|
||||||
|
HorizontalExpand = true,
|
||||||
|
HorizontalAlignment = HAlignment.Center,
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
new TextureRect
|
||||||
|
{
|
||||||
|
Texture = icon
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var nameLabel = new RichTextLabel();
|
||||||
|
nameLabel.SetMarkup(Loc.GetString("guidebook-reagent-sources-ent-wrapper", ("name", prototype.Name)));
|
||||||
|
entContainer.AddChild(nameLabel);
|
||||||
|
ReactantsContainer.AddChild(entContainer);
|
||||||
|
|
||||||
|
var productLabel = ProductsLabel;
|
||||||
|
SetReagents(solution.Contents, ref productLabel, protoMan);
|
||||||
|
SetMixingCategory(categories, null, sysMan);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GuideReagentReaction(GasPrototype prototype,
|
||||||
|
IReadOnlyList<ProtoId<MixingCategoryPrototype>> categories,
|
||||||
|
IPrototypeManager protoMan,
|
||||||
|
IEntitySystemManager sysMan) : this(protoMan)
|
||||||
|
{
|
||||||
|
ReactantsLabel.Visible = true;
|
||||||
|
ReactantsLabel.SetMarkup(Loc.GetString("guidebook-reagent-sources-gas-wrapper",
|
||||||
|
("name", Loc.GetString(prototype.Name).ToLower())));
|
||||||
|
|
||||||
|
if (prototype.Reagent != null)
|
||||||
|
{
|
||||||
|
var quantity = new Dictionary<string, FixedPoint2>
|
||||||
|
{
|
||||||
|
{ prototype.Reagent, FixedPoint2.New(0.21f) }
|
||||||
|
};
|
||||||
|
var productLabel = ProductsLabel;
|
||||||
|
SetReagents(quantity, ref productLabel, protoMan);
|
||||||
|
}
|
||||||
|
SetMixingCategory(categories, null, sysMan);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetReagents(List<ReagentQuantity> reagents, ref RichTextLabel label, IPrototypeManager protoMan)
|
||||||
|
{
|
||||||
|
var amounts = new Dictionary<string, FixedPoint2>();
|
||||||
|
foreach (var (reagent, quantity) in reagents)
|
||||||
|
{
|
||||||
|
amounts.Add(reagent.Prototype, quantity);
|
||||||
|
}
|
||||||
|
SetReagents(amounts, ref label, protoMan);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetReagents(
|
||||||
|
Dictionary<string, ReactantPrototype> reactants,
|
||||||
|
ref RichTextLabel label,
|
||||||
|
IPrototypeManager protoMan)
|
||||||
|
{
|
||||||
|
var amounts = new Dictionary<string, FixedPoint2>();
|
||||||
|
foreach (var (reagent, reactantPrototype) in reactants)
|
||||||
|
{
|
||||||
|
amounts.Add(reagent, reactantPrototype.Amount);
|
||||||
|
}
|
||||||
|
SetReagents(amounts, ref label, protoMan);
|
||||||
|
}
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
private void SetReagents(
|
||||||
|
Dictionary<ProtoId<MixingCategoryPrototype>, ReactantPrototype> reactants,
|
||||||
|
ref RichTextLabel label,
|
||||||
|
IPrototypeManager protoMan)
|
||||||
|
{
|
||||||
|
var amounts = new Dictionary<string, FixedPoint2>();
|
||||||
|
foreach (var (reagent, reactantPrototype) in reactants)
|
||||||
|
{
|
||||||
|
amounts.Add(reagent, reactantPrototype.Amount);
|
||||||
|
}
|
||||||
|
SetReagents(amounts, ref label, protoMan);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetReagents(Dictionary<string, FixedPoint2> reagents, ref RichTextLabel label, IPrototypeManager protoMan)
|
||||||
|
{
|
||||||
|
var msg = new FormattedMessage();
|
||||||
|
var reagentCount = reagents.Count;
|
||||||
|
var i = 0;
|
||||||
|
foreach (var (product, amount) in reagents.OrderByDescending(p => p.Value))
|
||||||
|
{
|
||||||
|
msg.AddMarkup(Loc.GetString("guidebook-reagent-recipes-reagent-display",
|
||||||
|
("reagent", protoMan.Index<ReagentPrototype>(product).LocalizedName), ("ratio", amount)));
|
||||||
|
i++;
|
||||||
|
if (i < reagentCount)
|
||||||
|
msg.PushNewline();
|
||||||
|
}
|
||||||
|
msg.Pop();
|
||||||
|
label.SetMessage(msg);
|
||||||
|
label.Visible = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetMixingCategory(IReadOnlyList<ProtoId<MixingCategoryPrototype>> mixingCategories, ReactionPrototype? prototype, IEntitySystemManager sysMan)
|
||||||
|
{
|
||||||
|
var foo = new List<MixingCategoryPrototype>();
|
||||||
|
foreach (var cat in mixingCategories)
|
||||||
|
{
|
||||||
|
foo.Add(_protoMan.Index(cat));
|
||||||
|
}
|
||||||
|
SetMixingCategory(foo, prototype, sysMan);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetMixingCategory(IReadOnlyList<MixingCategoryPrototype> mixingCategories, ReactionPrototype? prototype, IEntitySystemManager sysMan)
|
||||||
|
{
|
||||||
|
if (mixingCategories.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// only use the first one for the icon.
|
||||||
|
if (mixingCategories.First() is { } primaryCategory)
|
||||||
|
{
|
||||||
|
MixTexture.Texture = sysMan.GetEntitySystem<SpriteSystem>().Frame0(primaryCategory.Icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
var mixingVerb = ContentLocalizationManager.FormatList(mixingCategories
|
||||||
|
.Select(p => Loc.GetString(p.VerbText)).ToList());
|
||||||
|
|
||||||
|
var minTemp = prototype?.MinimumTemperature ?? 0;
|
||||||
|
var maxTemp = prototype?.MaximumTemperature ?? float.PositiveInfinity;
|
||||||
|
var text = Loc.GetString("guidebook-reagent-recipes-mix-info",
|
||||||
|
("verb", mixingVerb),
|
||||||
|
("minTemp", minTemp),
|
||||||
|
("maxTemp", maxTemp),
|
||||||
|
("hasMax", !float.IsPositiveInfinity(maxTemp)));
|
||||||
|
|
||||||
|
MixLabel.SetMarkup(text);
|
||||||
|
}
|
||||||
|
|
||||||
public bool CheckMatchesSearch(string query)
|
public bool CheckMatchesSearch(string query)
|
||||||
{
|
{
|
||||||
return this.ChildrenContainText(query);
|
return this.ChildrenContainText(query);
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
using Content.Server.Kitchen.EntitySystems;
|
|
||||||
using Content.Shared.Chemistry.Components;
|
|
||||||
|
|
||||||
namespace Content.Server.Kitchen.Components
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Tag component that denotes an entity as Extractable
|
|
||||||
/// </summary>
|
|
||||||
[RegisterComponent]
|
|
||||||
[Access(typeof(ReagentGrinderSystem))]
|
|
||||||
public sealed partial class ExtractableComponent : Component
|
|
||||||
{
|
|
||||||
[DataField("juiceSolution")]
|
|
||||||
public Solution? JuiceSolution;
|
|
||||||
|
|
||||||
[DataField("grindableSolutionName")]
|
|
||||||
public string? GrindableSolution;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -9,6 +9,7 @@ using Content.Shared.Containers.ItemSlots;
|
|||||||
using Content.Shared.FixedPoint;
|
using Content.Shared.FixedPoint;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.Kitchen;
|
using Content.Shared.Kitchen;
|
||||||
|
using Content.Shared.Kitchen.Components;
|
||||||
using Content.Shared.Popups;
|
using Content.Shared.Popups;
|
||||||
using Content.Shared.Random;
|
using Content.Shared.Random;
|
||||||
using Content.Shared.Stacks;
|
using Content.Shared.Stacks;
|
||||||
|
|||||||
@@ -83,6 +83,17 @@ namespace Content.Shared.Chemistry.Reaction
|
|||||||
[DataField("priority")]
|
[DataField("priority")]
|
||||||
public int Priority;
|
public int Priority;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether or not this reaction creates a new chemical (false) or if it's a breakdown for existing chemicals (true)
|
||||||
|
/// Used in the chemistry guidebook to make divisions between recipes and reaction sources.
|
||||||
|
/// </summary>
|
||||||
|
/// <example>
|
||||||
|
/// Mixing together two reagents to get a third -> false
|
||||||
|
/// Heating a reagent to break it down into 2 different ones -> true
|
||||||
|
/// </example>
|
||||||
|
[DataField]
|
||||||
|
public bool Source;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Comparison for creating a sorted set of reactions. Determines the order in which reactions occur.
|
/// Comparison for creating a sorted set of reactions. Determines the order in which reactions occur.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
17
Content.Shared/Kitchen/Components/ExtractableComponent.cs
Normal file
17
Content.Shared/Kitchen/Components/ExtractableComponent.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using Content.Shared.Chemistry.Components;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
|
||||||
|
namespace Content.Shared.Kitchen.Components;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tag component that denotes an entity as Extractable
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent, NetworkedComponent]
|
||||||
|
public sealed partial class ExtractableComponent : Component
|
||||||
|
{
|
||||||
|
[DataField("juiceSolution")]
|
||||||
|
public Solution? JuiceSolution;
|
||||||
|
|
||||||
|
[DataField("grindableSolutionName")]
|
||||||
|
public string? GrindableSolution;
|
||||||
|
};
|
||||||
@@ -1,4 +1,8 @@
|
|||||||
# Types
|
# Types
|
||||||
|
mixing-verb-default-mix = mix
|
||||||
|
mixing-verb-default-grind = grind
|
||||||
|
mixing-verb-default-juice = juice
|
||||||
|
mixing-verb-default-condense = condense
|
||||||
mixing-verb-centrifuge = centrifugation
|
mixing-verb-centrifuge = centrifugation
|
||||||
mixing-verb-electrolysis = electrolyze
|
mixing-verb-electrolysis = electrolyze
|
||||||
mixing-verb-holy = bless
|
mixing-verb-holy = bless
|
||||||
|
|||||||
@@ -10,16 +10,18 @@
|
|||||||
guidebook-reagent-name = [bold][color={$color}]{CAPITALIZE($name)}[/color][/bold]
|
guidebook-reagent-name = [bold][color={$color}]{CAPITALIZE($name)}[/color][/bold]
|
||||||
guidebook-reagent-recipes-header = Recipe
|
guidebook-reagent-recipes-header = Recipe
|
||||||
guidebook-reagent-recipes-reagent-display = [bold]{$reagent}[/bold] \[{$ratio}\]
|
guidebook-reagent-recipes-reagent-display = [bold]{$reagent}[/bold] \[{$ratio}\]
|
||||||
guidebook-reagent-recipes-mix = Mix
|
guidebook-reagent-sources-header = Sources
|
||||||
|
guidebook-reagent-sources-ent-wrapper = [bold]{$name}[/bold] \[1\]
|
||||||
|
guidebook-reagent-sources-gas-wrapper = [bold]{$name} (gas)[/bold] \[1\]
|
||||||
guidebook-reagent-effects-header = Effects
|
guidebook-reagent-effects-header = Effects
|
||||||
guidebook-reagent-effects-metabolism-group-rate = [bold]{$group}[/bold] [color=gray]({$rate} units per second)[/color]
|
guidebook-reagent-effects-metabolism-group-rate = [bold]{$group}[/bold] [color=gray]({$rate} units per second)[/color]
|
||||||
guidebook-reagent-physical-description = [italic]Seems to be {$description}.[/italic]
|
guidebook-reagent-physical-description = [italic]Seems to be {$description}.[/italic]
|
||||||
guidebook-reagent-recipes-mix-info = {$minTemp ->
|
guidebook-reagent-recipes-mix-info = {$minTemp ->
|
||||||
[0] {$hasMax ->
|
[0] {$hasMax ->
|
||||||
[true] {$verb} below {$maxTemp}K
|
[true] {CAPITALIZE($verb)} below {$maxTemp}K
|
||||||
*[false] {$verb}
|
*[false] {CAPITALIZE($verb)}
|
||||||
}
|
}
|
||||||
*[other] {$verb} {$hasMax ->
|
*[other] {CAPITALIZE($verb)} {$hasMax ->
|
||||||
[true] between {$minTemp}K and {$maxTemp}K
|
[true] between {$minTemp}K and {$maxTemp}K
|
||||||
*[false] above {$minTemp}K
|
*[false] above {$minTemp}K
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,36 @@
|
|||||||
|
# Default Mixing
|
||||||
|
# Not actually used in reactions: only meant for guidebook display purposes.
|
||||||
|
|
||||||
|
- type: mixingCategory
|
||||||
|
id: DummyMix
|
||||||
|
verbText: mixing-verb-default-mix
|
||||||
|
icon:
|
||||||
|
sprite: Objects/Specific/Chemistry/beaker_large.rsi
|
||||||
|
state: beakerlarge
|
||||||
|
|
||||||
|
- type: mixingCategory
|
||||||
|
id: DummyGrind
|
||||||
|
verbText: mixing-verb-default-grind
|
||||||
|
icon:
|
||||||
|
sprite: Structures/Machines/juicer.rsi
|
||||||
|
state: juicer0
|
||||||
|
|
||||||
|
- type: mixingCategory
|
||||||
|
id: DummyJuice
|
||||||
|
verbText: mixing-verb-default-juice
|
||||||
|
icon:
|
||||||
|
sprite: Structures/Machines/juicer.rsi
|
||||||
|
state: juicer0
|
||||||
|
|
||||||
|
- type: mixingCategory
|
||||||
|
id: DummyCondense
|
||||||
|
verbText: mixing-verb-default-condense
|
||||||
|
icon:
|
||||||
|
sprite: Structures/Piping/Atmospherics/condenser.rsi
|
||||||
|
state: display
|
||||||
|
|
||||||
|
# Alternative Mixing Methods
|
||||||
|
|
||||||
- type: mixingCategory
|
- type: mixingCategory
|
||||||
id: Centrifuge
|
id: Centrifuge
|
||||||
verbText: mixing-verb-centrifuge
|
verbText: mixing-verb-centrifuge
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
- type: entity
|
- type: entity
|
||||||
parent: PartBase
|
parent: PartBase
|
||||||
id: PartRodMetal
|
id: PartRodMetal
|
||||||
name: metal rods
|
name: metal rod
|
||||||
suffix: Full
|
suffix: Full
|
||||||
components:
|
components:
|
||||||
- type: PhysicalComposition
|
- type: PhysicalComposition
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
- type: reaction
|
- type: reaction
|
||||||
id: BloodBreakdown
|
id: BloodBreakdown
|
||||||
|
source: true
|
||||||
requiredMixerCategories:
|
requiredMixerCategories:
|
||||||
- Centrifuge
|
- Centrifuge
|
||||||
reactants:
|
reactants:
|
||||||
@@ -14,6 +15,7 @@
|
|||||||
|
|
||||||
- type: reaction
|
- type: reaction
|
||||||
id: SlimeBloodBreakdown
|
id: SlimeBloodBreakdown
|
||||||
|
source: true
|
||||||
requiredMixerCategories:
|
requiredMixerCategories:
|
||||||
- Centrifuge
|
- Centrifuge
|
||||||
reactants:
|
reactants:
|
||||||
@@ -25,6 +27,7 @@
|
|||||||
|
|
||||||
- type: reaction
|
- type: reaction
|
||||||
id: CopperBloodBreakdown
|
id: CopperBloodBreakdown
|
||||||
|
source: true
|
||||||
requiredMixerCategories:
|
requiredMixerCategories:
|
||||||
- Centrifuge
|
- Centrifuge
|
||||||
reactants:
|
reactants:
|
||||||
@@ -39,6 +42,7 @@
|
|||||||
|
|
||||||
- type: reaction
|
- type: reaction
|
||||||
id: ZombieBloodBreakdown
|
id: ZombieBloodBreakdown
|
||||||
|
source: true
|
||||||
requiredMixerCategories:
|
requiredMixerCategories:
|
||||||
- Centrifuge
|
- Centrifuge
|
||||||
reactants:
|
reactants:
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
- type: reaction
|
- type: reaction
|
||||||
id: CelluloseBreakdown
|
id: CelluloseBreakdown
|
||||||
|
source: true
|
||||||
requiredMixerCategories:
|
requiredMixerCategories:
|
||||||
- Electrolysis
|
- Electrolysis
|
||||||
reactants:
|
reactants:
|
||||||
@@ -217,6 +218,7 @@
|
|||||||
|
|
||||||
- type: reaction
|
- type: reaction
|
||||||
id: TableSaltBreakdown
|
id: TableSaltBreakdown
|
||||||
|
source: true
|
||||||
requiredMixerCategories:
|
requiredMixerCategories:
|
||||||
- Electrolysis
|
- Electrolysis
|
||||||
reactants:
|
reactants:
|
||||||
|
|||||||
@@ -262,6 +262,7 @@
|
|||||||
|
|
||||||
- type: reaction
|
- type: reaction
|
||||||
id: EthanolBreakdown
|
id: EthanolBreakdown
|
||||||
|
source: true
|
||||||
requiredMixerCategories:
|
requiredMixerCategories:
|
||||||
- Electrolysis
|
- Electrolysis
|
||||||
reactants:
|
reactants:
|
||||||
@@ -895,6 +896,7 @@
|
|||||||
|
|
||||||
- type: reaction
|
- type: reaction
|
||||||
id: WaterBreakdown
|
id: WaterBreakdown
|
||||||
|
source: true
|
||||||
requiredMixerCategories:
|
requiredMixerCategories:
|
||||||
- Electrolysis
|
- Electrolysis
|
||||||
reactants:
|
reactants:
|
||||||
|
|||||||
@@ -300,6 +300,7 @@
|
|||||||
|
|
||||||
- type: reaction
|
- type: reaction
|
||||||
id: BananaBreakdown
|
id: BananaBreakdown
|
||||||
|
source: true
|
||||||
requiredMixerCategories:
|
requiredMixerCategories:
|
||||||
- Centrifuge
|
- Centrifuge
|
||||||
reactants:
|
reactants:
|
||||||
@@ -311,6 +312,7 @@
|
|||||||
|
|
||||||
#- type: reaction
|
#- type: reaction
|
||||||
# id: SugarBreakdown
|
# id: SugarBreakdown
|
||||||
|
# source: true
|
||||||
# minTemp: 520
|
# minTemp: 520
|
||||||
# reactants:
|
# reactants:
|
||||||
# Sugar:
|
# Sugar:
|
||||||
|
|||||||
@@ -148,6 +148,7 @@
|
|||||||
|
|
||||||
- type: reaction
|
- type: reaction
|
||||||
id: FiberBreakdown
|
id: FiberBreakdown
|
||||||
|
source: true
|
||||||
requiredMixerCategories:
|
requiredMixerCategories:
|
||||||
- Centrifuge
|
- Centrifuge
|
||||||
reactants:
|
reactants:
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
- type: reaction
|
- type: reaction
|
||||||
id: CarbonDioxideBreakdown
|
id: CarbonDioxideBreakdown
|
||||||
|
source: true
|
||||||
requiredMixerCategories:
|
requiredMixerCategories:
|
||||||
- Electrolysis
|
- Electrolysis
|
||||||
reactants:
|
reactants:
|
||||||
@@ -11,6 +12,7 @@
|
|||||||
|
|
||||||
- type: reaction
|
- type: reaction
|
||||||
id: NitrousOxideBreakdown
|
id: NitrousOxideBreakdown
|
||||||
|
source: true
|
||||||
requiredMixerCategories:
|
requiredMixerCategories:
|
||||||
- Electrolysis
|
- Electrolysis
|
||||||
reactants:
|
reactants:
|
||||||
|
|||||||
@@ -63,6 +63,7 @@
|
|||||||
|
|
||||||
- type: reaction
|
- type: reaction
|
||||||
id: WeldingFuelBreakdown
|
id: WeldingFuelBreakdown
|
||||||
|
source: true
|
||||||
requiredMixerCategories:
|
requiredMixerCategories:
|
||||||
- Centrifuge
|
- Centrifuge
|
||||||
reactants:
|
reactants:
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
@@ -35,6 +35,9 @@
|
|||||||
"name":"pipe",
|
"name":"pipe",
|
||||||
"directions":4
|
"directions":4
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name":"display"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name":"fill-1"
|
"name":"fill-1"
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user