Skip to content

Commit

Permalink
Add support for printing reagents in lathes (space-wizards#30476)
Browse files Browse the repository at this point in the history
* Add support for reagents in lathes

* missing locale
  • Loading branch information
EmoGarbage404 authored and themias committed Aug 9, 2024
1 parent 88d257a commit 405bc55
Show file tree
Hide file tree
Showing 17 changed files with 234 additions and 134 deletions.
8 changes: 3 additions & 5 deletions Content.Client/Lathe/UI/LatheMenu.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,9 @@
Margin="5 0 0 0"
Text="{Loc 'lathe-menu-fabricating-message'}">
</Label>
<EntityPrototypeView
Name="FabricatingEntityProto"
HorizontalAlignment="Left"
Margin="100 0 0 0"
/>
<BoxContainer Name="FabricatingDisplayContainer"
HorizontalAlignment="Left"
Margin="100 0 0 0"/>
<Label
Name="NameLabel"
RectClipContent="True"
Expand Down
56 changes: 33 additions & 23 deletions Content.Client/Lathe/UI/LatheMenu.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
using System.Buffers;
using System.Linq;
using System.Text;
using Content.Client.Materials;
using Content.Shared.Lathe;
using Content.Shared.Lathe.Prototypes;
using Content.Shared.Materials;
using Content.Shared.Research.Prototypes;
using Robust.Client.AutoGenerated;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
using Robust.Client.ResourceManagement;
using Robust.Client.Graphics;
using Robust.Shared.Prototypes;

namespace Content.Client.Lathe.UI;
Expand Down Expand Up @@ -92,7 +89,7 @@ public void PopulateRecipes()

if (SearchBar.Text.Trim().Length != 0)
{
if (proto.Name.ToLowerInvariant().Contains(SearchBar.Text.Trim().ToLowerInvariant()))
if (_lathe.GetRecipeName(recipe).ToLowerInvariant().Contains(SearchBar.Text.Trim().ToLowerInvariant()))
recipesToShow.Add(proto);
}
else
Expand All @@ -104,19 +101,15 @@ public void PopulateRecipes()
if (!int.TryParse(AmountLineEdit.Text, out var quantity) || quantity <= 0)
quantity = 1;

var sortedRecipesToShow = recipesToShow.OrderBy(p => p.Name);
var sortedRecipesToShow = recipesToShow.OrderBy(_lathe.GetRecipeName);
RecipeList.Children.Clear();
_entityManager.TryGetComponent(Entity, out LatheComponent? lathe);

foreach (var prototype in sortedRecipesToShow)
{
EntityPrototype? recipeProto = null;
if (_prototypeManager.TryIndex(prototype.Result, out EntityPrototype? entityProto))
recipeProto = entityProto;

var canProduce = _lathe.CanProduce(Entity, prototype, quantity, component: lathe);

var control = new RecipeControl(prototype, () => GenerateTooltipText(prototype), canProduce, recipeProto);
var control = new RecipeControl(_lathe, prototype, () => GenerateTooltipText(prototype), canProduce, GetRecipeDisplayControl(prototype));
control.OnButtonPressed += s =>
{
if (!int.TryParse(AmountLineEdit.Text, out var amount) || amount <= 0)
Expand All @@ -132,9 +125,9 @@ private string GenerateTooltipText(LatheRecipePrototype prototype)
StringBuilder sb = new();
var multiplier = _entityManager.GetComponent<LatheComponent>(Entity).MaterialUseMultiplier;

foreach (var (id, amount) in prototype.RequiredMaterials)
foreach (var (id, amount) in prototype.Materials)
{
if (!_prototypeManager.TryIndex<MaterialPrototype>(id, out var proto))
if (!_prototypeManager.TryIndex(id, out var proto))
continue;

var adjustedAmount = SharedLatheSystem.AdjustMaterial(amount, prototype.ApplyMaterialDiscount, multiplier);
Expand Down Expand Up @@ -163,8 +156,9 @@ private string GenerateTooltipText(LatheRecipePrototype prototype)
sb.AppendLine(tooltipText);
}

if (!string.IsNullOrWhiteSpace(prototype.Description))
sb.AppendLine(Loc.GetString("lathe-menu-description-display", ("description", prototype.Description)));
var desc = _lathe.GetRecipeDescription(prototype);
if (!string.IsNullOrWhiteSpace(desc))
sb.AppendLine(Loc.GetString("lathe-menu-description-display", ("description", desc)));

// Remove last newline
if (sb.Length > 0)
Expand Down Expand Up @@ -222,13 +216,10 @@ public void PopulateQueueList(List<LatheRecipePrototype> queue)
var queuedRecipeBox = new BoxContainer();
queuedRecipeBox.Orientation = BoxContainer.LayoutOrientation.Horizontal;

var queuedRecipeProto = new EntityPrototypeView();
queuedRecipeBox.AddChild(queuedRecipeProto);
if (_prototypeManager.TryIndex(recipe.Result, out EntityPrototype? entityProto) && entityProto != null)
queuedRecipeProto.SetPrototype(entityProto);
queuedRecipeBox.AddChild(GetRecipeDisplayControl(recipe));

var queuedRecipeLabel = new Label();
queuedRecipeLabel.Text = $"{idx}. {recipe.Name}";
queuedRecipeLabel.Text = $"{idx}. {_lathe.GetRecipeName(recipe)}";
queuedRecipeBox.AddChild(queuedRecipeLabel);
QueueList.AddChild(queuedRecipeBox);
idx++;
Expand All @@ -241,10 +232,29 @@ public void SetQueueInfo(LatheRecipePrototype? recipe)
if (recipe == null)
return;

if (_prototypeManager.TryIndex(recipe.Result, out EntityPrototype? entityProto) && entityProto != null)
FabricatingEntityProto.SetPrototype(entityProto);
FabricatingDisplayContainer.Children.Clear();
FabricatingDisplayContainer.AddChild(GetRecipeDisplayControl(recipe));

NameLabel.Text = _lathe.GetRecipeName(recipe);
}

public Control GetRecipeDisplayControl(LatheRecipePrototype recipe)
{
if (recipe.Icon != null)
{
var textRect = new TextureRect();
textRect.Texture = _spriteSystem.Frame0(recipe.Icon);
return textRect;
}

if (recipe.Result is { } result)
{
var entProtoView = new EntityPrototypeView();
entProtoView.SetPrototype(result);
return entProtoView;
}

NameLabel.Text = $"{recipe.Name}";
return new Control();
}

private void OnItemSelected(OptionButton.ItemSelectedEventArgs obj)
Expand Down
4 changes: 2 additions & 2 deletions Content.Client/Lathe/UI/RecipeControl.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
Margin="0"
StyleClasses="ButtonSquare">
<BoxContainer Orientation="Horizontal">
<EntityPrototypeView
Name="RecipePrototype"
<BoxContainer
Name="RecipeDisplayContainer"
Margin="0 0 4 0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Expand Down
10 changes: 3 additions & 7 deletions Content.Client/Lathe/UI/RecipeControl.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
using Content.Shared.Research.Prototypes;
using Robust.Client.AutoGenerated;
using Robust.Client.Graphics;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Prototypes;

namespace Content.Client.Lathe.UI;

Expand All @@ -14,13 +11,12 @@ public sealed partial class RecipeControl : Control
public Action<string>? OnButtonPressed;
public Func<string> TooltipTextSupplier;

public RecipeControl(LatheRecipePrototype recipe, Func<string> tooltipTextSupplier, bool canProduce, EntityPrototype? entityPrototype = null)
public RecipeControl(LatheSystem latheSystem, LatheRecipePrototype recipe, Func<string> tooltipTextSupplier, bool canProduce, Control displayControl)
{
RobustXamlLoader.Load(this);

RecipeName.Text = recipe.Name;
if (entityPrototype != null)
RecipePrototype.SetPrototype(entityPrototype);
RecipeName.Text = latheSystem.GetRecipeName(recipe);
RecipeDisplayContainer.AddChild(displayControl);
Button.Disabled = !canProduce;
TooltipTextSupplier = tooltipTextSupplier;
Button.TooltipSupplier = SupplyTooltip;
Expand Down
6 changes: 3 additions & 3 deletions Content.IntegrationTests/Tests/MaterialArbitrageTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ public async Task NoMaterialArbitrage()
{
foreach (var recipe in recipes)
{
foreach (var (matId, amount) in recipe.RequiredMaterials)
foreach (var (matId, amount) in recipe.Materials)
{
var actualAmount = SharedLatheSystem.AdjustMaterial(amount, recipe.ApplyMaterialDiscount, multiplier);
if (spawnedMats.TryGetValue(matId, out var numSpawned))
Expand Down Expand Up @@ -273,7 +273,7 @@ public async Task NoMaterialArbitrage()
{
foreach (var recipe in recipes)
{
foreach (var (matId, amount) in recipe.RequiredMaterials)
foreach (var (matId, amount) in recipe.Materials)
{
var actualAmount = SharedLatheSystem.AdjustMaterial(amount, recipe.ApplyMaterialDiscount, multiplier);
if (deconstructedMats.TryGetValue(matId, out var numSpawned))
Expand Down Expand Up @@ -328,7 +328,7 @@ public async Task NoMaterialArbitrage()
{
foreach (var recipe in recipes)
{
foreach (var (matId, amount) in recipe.RequiredMaterials)
foreach (var (matId, amount) in recipe.Materials)
{
var actualAmount = SharedLatheSystem.AdjustMaterial(amount, recipe.ApplyMaterialDiscount, multiplier);
if (compositionComponent.MaterialComposition.TryGetValue(matId, out var numSpawned))
Expand Down
21 changes: 21 additions & 0 deletions Content.Server/Cargo/Systems/PricingSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
using System.Linq;
using Content.Shared.Research.Prototypes;

namespace Content.Server.Cargo.Systems;

Expand Down Expand Up @@ -158,6 +159,26 @@ private double GetMaterialPrice(PhysicalCompositionComponent component)
return price;
}

public double GetLatheRecipePrice(LatheRecipePrototype recipe)
{
var price = 0.0;

if (recipe.Result is { } result)
{
price += GetEstimatedPrice(_prototypeManager.Index(result));
}

if (recipe.ResultReagents is { } resultReagents)
{
foreach (var (reagent, amount) in resultReagents)
{
price += (_prototypeManager.Index(reagent).PricePerUnit * amount).Double();
}
}

return price;
}

/// <summary>
/// Get a rough price for an entityprototype. Does not consider contained entities.
/// </summary>
Expand Down
50 changes: 42 additions & 8 deletions Content.Server/Lathe/LatheSystem.cs
Original file line number Diff line number Diff line change
@@ -1,23 +1,29 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Content.Server.Administration.Logs;
using Content.Server.Atmos;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Fluids.EntitySystems;
using Content.Server.Lathe.Components;
using Content.Server.Materials;
using Content.Server.Popups;
using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems;
using Content.Server.Stack;
using Content.Shared.Atmos;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.UserInterface;
using Content.Shared.Database;
using Content.Shared.Emag.Components;
using Content.Shared.Examine;
using Content.Shared.Lathe;
using Content.Shared.Materials;
using Content.Shared.ReagentSpeed;
using Content.Shared.Research.Components;
using Content.Shared.Research.Prototypes;
using JetBrains.Annotations;
using Robust.Server.Containers;
using Robust.Server.GameObjects;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Prototypes;
Expand All @@ -34,9 +40,13 @@ public sealed class LatheSystem : SharedLatheSystem
[Dependency] private readonly AtmosphereSystem _atmosphere = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly ContainerSystem _container = default!;
[Dependency] private readonly UserInterfaceSystem _uiSys = default!;
[Dependency] private readonly MaterialStorageSystem _materialStorage = default!;
[Dependency] private readonly PopupSystem _popup = default!;
[Dependency] private readonly PuddleSystem _puddle = default!;
[Dependency] private readonly ReagentSpeedSystem _reagentSpeed = default!;
[Dependency] private readonly SharedSolutionContainerSystem _solution = default!;
[Dependency] private readonly StackSystem _stack = default!;
[Dependency] private readonly TransformSystem _transform = default!;

Expand All @@ -63,7 +73,6 @@ public override void Initialize()
SubscribeLocalEvent<EmagLatheRecipesComponent, LatheGetRecipesEvent>(GetEmagLatheRecipes);
SubscribeLocalEvent<LatheHeatProducingComponent, LatheStartPrintingEvent>(OnHeatStartPrinting);
}

public override void Update(float frameTime)
{
var query = EntityQueryEnumerator<LatheProducingComponent, LatheComponent>();
Expand Down Expand Up @@ -119,7 +128,7 @@ private void OnGetWhitelist(EntityUid uid, LatheComponent component, ref GetMate
{
if (!_proto.TryIndex(id, out var proto))
continue;
foreach (var (mat, _) in proto.RequiredMaterials)
foreach (var (mat, _) in proto.Materials)
{
if (!materialWhitelist.Contains(mat))
{
Expand Down Expand Up @@ -165,7 +174,7 @@ public bool TryAddToQueue(EntityUid uid, LatheRecipePrototype recipe, LatheCompo
if (!CanProduce(uid, recipe, 1, component))
return false;

foreach (var (mat, amount) in recipe.RequiredMaterials)
foreach (var (mat, amount) in recipe.Materials)
{
var adjustedAmount = recipe.ApplyMaterialDiscount
? (int) (-amount * component.MaterialUseMultiplier)
Expand Down Expand Up @@ -211,8 +220,31 @@ public void FinishProducing(EntityUid uid, LatheComponent? comp = null, LathePro

if (comp.CurrentRecipe != null)
{
var result = Spawn(comp.CurrentRecipe.Result, Transform(uid).Coordinates);
_stack.TryMergeToContacts(result);
if (comp.CurrentRecipe.Result is { } resultProto)
{
var result = Spawn(resultProto, Transform(uid).Coordinates);
_stack.TryMergeToContacts(result);
}

if (comp.CurrentRecipe.ResultReagents is { } resultReagents &&
comp.ReagentOutputSlotId is { } slotId)
{
var toAdd = new Solution(
resultReagents.Select(p => new ReagentQuantity(p.Key.Id, p.Value, null)));

// dispense it in the container if we have it and dump it if we don't
if (_container.TryGetContainer(uid, slotId, out var container) &&
container.ContainedEntities.Count == 1 &&
_solution.TryGetFitsInDispenser(container.ContainedEntities.First(), out var solution, out _))
{
_solution.AddSolution(solution.Value, toAdd);
}
else
{
_popup.PopupEntity(Loc.GetString("lathe-reagent-dispense-no-container", ("name", uid)), uid);
_puddle.TrySpillAt(uid, toAdd, out _);
}
}
}

comp.CurrentRecipe = null;
Expand Down Expand Up @@ -327,6 +359,7 @@ protected override bool HasRecipe(EntityUid uid, LatheRecipePrototype recipe, La
{
return GetAvailableRecipes(uid, component).Contains(recipe.ID);
}

#region UI Messages

private void OnLatheQueueRecipeMessage(EntityUid uid, LatheComponent component, LatheQueueRecipeMessage args)
Expand All @@ -343,8 +376,9 @@ private void OnLatheQueueRecipeMessage(EntityUid uid, LatheComponent component,
}
if (count > 0)
{
_adminLogger.Add(LogType.Action, LogImpact.Low,
$"{ToPrettyString(args.Actor):player} queued {count} {recipe.Name} at {ToPrettyString(uid):lathe}");
_adminLogger.Add(LogType.Action,
LogImpact.Low,
$"{ToPrettyString(args.Actor):player} queued {count} {GetRecipeName(recipe)} at {ToPrettyString(uid):lathe}");
}
}
TryStartProducing(uid, component);
Expand Down
7 changes: 3 additions & 4 deletions Content.Server/UserInterface/StatValuesCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
using Content.Server.Power.Components;
using Content.Shared.Administration;
using Content.Shared.Item;
using Content.Shared.Materials;
using Content.Shared.Research.Prototypes;
using Content.Shared.UserInterface;
using Content.Shared.Weapons.Melee;
Expand Down Expand Up @@ -224,13 +223,13 @@ private StatValuesEuiMessage GetLatheMessage()
{
var cost = 0.0;

foreach (var (material, count) in proto.RequiredMaterials)
foreach (var (material, count) in proto.Materials)
{
var materialPrice = _proto.Index<MaterialPrototype>(material).Price;
var materialPrice = _proto.Index(material).Price;
cost += materialPrice * count;
}

var sell = priceSystem.GetEstimatedPrice(_proto.Index<EntityPrototype>(proto.Result));
var sell = priceSystem.GetLatheRecipePrice(proto);

values.Add(new[]
{
Expand Down
Loading

0 comments on commit 405bc55

Please sign in to comment.