Lathe Refactor and ECS (#11201)
* lathe and material storage refactor * materialStorage ECS it kinda sus tho * beginning the lathe shitcode dive * couple lathe visuals and lathe system * lathe changes and such * dynamic lathe databases * rewrote internal logic on to ui * da newI * material display clientside * misc ui changes * component state handling and various other things * moar * Update Content.Shared/Lathe/LatheComponent.cs Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> * first volley of sloth review * more fixes * losin' my mind * all da changes * test fix and other review Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
This commit is contained in:
@@ -102,7 +102,6 @@ namespace Content.Client.Entry
|
||||
_componentFactory.IgnoreMissingComponents();
|
||||
|
||||
// Do not add to these, they are legacy.
|
||||
_componentFactory.RegisterClass<SharedLatheComponent>();
|
||||
_componentFactory.RegisterClass<SharedSpawnPointComponent>();
|
||||
_componentFactory.RegisterClass<SharedReagentDispenserComponent>();
|
||||
_componentFactory.RegisterClass<SharedGravityGeneratorComponent>();
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
using Content.Shared.Lathe;
|
||||
using Content.Shared.Research.Prototypes;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Client.Lathe.Components
|
||||
{
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(SharedLatheDatabaseComponent))]
|
||||
public sealed class LatheDatabaseComponent : SharedLatheDatabaseComponent
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
|
||||
public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)
|
||||
{
|
||||
base.HandleComponentState(curState, nextState);
|
||||
|
||||
if (curState is not LatheDatabaseState state) return;
|
||||
|
||||
Clear();
|
||||
|
||||
foreach (var id in state.Recipes)
|
||||
{
|
||||
if (!_prototypeManager.TryIndex(id, out LatheRecipePrototype? recipe)) continue;
|
||||
AddRecipe(recipe);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
namespace Content.Client.Lathe;
|
||||
|
||||
/// <summary>
|
||||
/// Holds the idle and running state for machines to control
|
||||
/// playing animations on the client.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed class LatheVisualsComponent : Component
|
||||
{
|
||||
[DataField("idleState", required: true)]
|
||||
public string IdleState = default!;
|
||||
|
||||
[DataField("runningState", required: true)]
|
||||
public string RunningState = default!;
|
||||
|
||||
[ViewVariables]
|
||||
[DataField("ignoreColor")]
|
||||
public bool IgnoreColor;
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Content.Shared.Lathe;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Client.Lathe.Components
|
||||
{
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(SharedMaterialStorageComponent))]
|
||||
public sealed class MaterialStorageComponent : SharedMaterialStorageComponent
|
||||
{
|
||||
protected override Dictionary<string, int> Storage { get; set; } = new();
|
||||
|
||||
public event Action? OnMaterialStorageChanged;
|
||||
|
||||
public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)
|
||||
{
|
||||
base.HandleComponentState(curState, nextState);
|
||||
if (curState is not MaterialStorageState state) return;
|
||||
Storage = state.Storage;
|
||||
OnMaterialStorageChanged?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
using System;
|
||||
using Content.Shared.Lathe;
|
||||
using Content.Shared.Research.Prototypes;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Client.Lathe.Components
|
||||
{
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(SharedLatheDatabaseComponent))]
|
||||
public sealed class ProtolatheDatabaseComponent : SharedProtolatheDatabaseComponent
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when the database gets updated.
|
||||
/// </summary>
|
||||
public event Action? OnDatabaseUpdated;
|
||||
|
||||
public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)
|
||||
{
|
||||
base.HandleComponentState(curState, nextState);
|
||||
|
||||
if (curState is not ProtolatheDatabaseState state) return;
|
||||
|
||||
Clear();
|
||||
|
||||
foreach (var id in state.Recipes)
|
||||
{
|
||||
if(!_prototypeManager.TryIndex(id, out LatheRecipePrototype? recipe)) continue;
|
||||
AddRecipe(recipe);
|
||||
}
|
||||
|
||||
OnDatabaseUpdated?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,45 +2,62 @@ using Robust.Client.GameObjects;
|
||||
using Content.Shared.Lathe;
|
||||
using Content.Shared.Power;
|
||||
using Content.Client.Power;
|
||||
using Content.Shared.Research.Prototypes;
|
||||
|
||||
namespace Content.Client.Lathe
|
||||
namespace Content.Client.Lathe;
|
||||
|
||||
public sealed class LatheSystem : SharedLatheSystem
|
||||
{
|
||||
public sealed class LatheSystem : VisualizerSystem<LatheVisualsComponent>
|
||||
public override void Initialize()
|
||||
{
|
||||
protected override void OnAppearanceChange(EntityUid uid, LatheVisualsComponent component, ref AppearanceChangeEvent args)
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<LatheComponent, AppearanceChangeEvent>(OnAppearanceChange);
|
||||
}
|
||||
|
||||
private void OnAppearanceChange(EntityUid uid, LatheComponent component, ref AppearanceChangeEvent args)
|
||||
{
|
||||
if (args.Sprite == null)
|
||||
return;
|
||||
|
||||
if (args.Component.TryGetData(PowerDeviceVisuals.Powered, out bool powered) &&
|
||||
args.Sprite.LayerMapTryGet(PowerDeviceVisualLayers.Powered, out _))
|
||||
{
|
||||
if (args.Sprite == null)
|
||||
return;
|
||||
args.Sprite.LayerSetVisible(PowerDeviceVisualLayers.Powered, powered);
|
||||
}
|
||||
|
||||
if (args.Component.TryGetData(PowerDeviceVisuals.Powered, out bool powered) &&
|
||||
args.Sprite.LayerMapTryGet(PowerDeviceVisualLayers.Powered, out _))
|
||||
// Lathe specific stuff
|
||||
if (args.Component.TryGetData(LatheVisuals.IsRunning, out bool isRunning))
|
||||
{
|
||||
var state = isRunning ? component.RunningState : component.IdleState;
|
||||
args.Sprite.LayerSetAnimationTime(LatheVisualLayers.IsRunning, 0f);
|
||||
args.Sprite.LayerSetState(LatheVisualLayers.IsRunning, state);
|
||||
}
|
||||
|
||||
if (args.Component.TryGetData(LatheVisuals.IsInserting, out bool isInserting)
|
||||
&& args.Sprite.LayerMapTryGet(LatheVisualLayers.IsInserting, out var isInsertingLayer))
|
||||
{
|
||||
if (args.Component.TryGetData(LatheVisuals.InsertingColor, out Color color)
|
||||
&& !component.IgnoreColor)
|
||||
{
|
||||
args.Sprite.LayerSetVisible(PowerDeviceVisualLayers.Powered, powered);
|
||||
args.Sprite.LayerSetColor(isInsertingLayer, color);
|
||||
}
|
||||
|
||||
// Lathe specific stuff
|
||||
if (args.Component.TryGetData(LatheVisuals.IsRunning, out bool isRunning))
|
||||
{
|
||||
var state = isRunning ? component.RunningState : component.IdleState;
|
||||
args.Sprite.LayerSetAnimationTime(LatheVisualLayers.IsRunning, 0f);
|
||||
args.Sprite.LayerSetState(LatheVisualLayers.IsRunning, state);
|
||||
}
|
||||
|
||||
if (args.Component.TryGetData(LatheVisuals.IsInserting, out bool isInserting)
|
||||
&& args.Sprite.LayerMapTryGet(LatheVisualLayers.IsInserting, out var isInsertingLayer))
|
||||
{
|
||||
if (args.Component.TryGetData(LatheVisuals.InsertingColor, out Color color)
|
||||
&& !component.IgnoreColor)
|
||||
{
|
||||
args.Sprite.LayerSetColor(isInsertingLayer, color);
|
||||
}
|
||||
|
||||
args.Sprite.LayerSetAnimationTime(isInsertingLayer, 0f);
|
||||
args.Sprite.LayerSetVisible(isInsertingLayer, isInserting);
|
||||
}
|
||||
args.Sprite.LayerSetAnimationTime(isInsertingLayer, 0f);
|
||||
args.Sprite.LayerSetVisible(isInsertingLayer, isInserting);
|
||||
}
|
||||
}
|
||||
|
||||
///<remarks>
|
||||
/// Whether or not a recipe is available is not really visible to the client,
|
||||
/// so it just defaults to true.
|
||||
///</remarks>
|
||||
protected override bool HasRecipe(EntityUid uid, LatheRecipePrototype recipe, LatheComponent component)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public enum LatheVisualLayers : byte
|
||||
{
|
||||
IsRunning,
|
||||
|
||||
@@ -1,101 +1,64 @@
|
||||
using System.Collections.Generic;
|
||||
using Content.Client.Lathe.Components;
|
||||
using Content.Shared.Lathe;
|
||||
using Content.Shared.Research.Prototypes;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.ViewVariables;
|
||||
using static Content.Shared.Lathe.SharedLatheComponent;
|
||||
|
||||
namespace Content.Client.Lathe.UI
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public sealed class LatheBoundUserInterface : BoundUserInterface
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entMan = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[ViewVariables] private LatheMenu? _menu;
|
||||
[ViewVariables] private LatheQueueMenu? _queueMenu;
|
||||
|
||||
[ViewVariables]
|
||||
private LatheMenu? _menu;
|
||||
[ViewVariables]
|
||||
private LatheQueueMenu? _queueMenu;
|
||||
|
||||
public MaterialStorageComponent? Storage { get; private set; }
|
||||
public SharedLatheComponent? Lathe { get; private set; }
|
||||
public SharedLatheDatabaseComponent? Database { get; private set; }
|
||||
|
||||
[ViewVariables]
|
||||
public Queue<LatheRecipePrototype> QueuedRecipes => _queuedRecipes;
|
||||
private readonly Queue<LatheRecipePrototype> _queuedRecipes = new();
|
||||
public EntityUid Lathe;
|
||||
|
||||
public LatheBoundUserInterface(ClientUserInterfaceComponent owner, Enum uiKey) : base(owner, uiKey)
|
||||
{
|
||||
SendMessage(new LatheSyncRequestMessage());
|
||||
Lathe = owner.Owner;
|
||||
}
|
||||
|
||||
protected override void Open()
|
||||
{
|
||||
base.Open();
|
||||
|
||||
if (!_entMan.TryGetComponent(Owner.Owner, out MaterialStorageComponent? storage)
|
||||
|| !_entMan.TryGetComponent(Owner.Owner, out SharedLatheComponent? lathe)
|
||||
|| !_entMan.TryGetComponent(Owner.Owner, out SharedLatheDatabaseComponent? database)) return;
|
||||
|
||||
Storage = storage;
|
||||
Lathe = lathe;
|
||||
Database = database;
|
||||
|
||||
_menu = new LatheMenu(this);
|
||||
_queueMenu = new LatheQueueMenu(this);
|
||||
|
||||
_menu.OnClose += Close;
|
||||
|
||||
_menu.Populate();
|
||||
_menu.PopulateMaterials();
|
||||
|
||||
_menu.QueueButton.OnPressed += (_) => { _queueMenu.OpenCentered(); };
|
||||
|
||||
_menu.ServerConnectButton.OnPressed += (_) =>
|
||||
_menu.OnQueueButtonPressed += _ =>
|
||||
{
|
||||
_queueMenu.OpenCenteredLeft();
|
||||
};
|
||||
_menu.OnServerListButtonPressed += _ =>
|
||||
{
|
||||
SendMessage(new LatheServerSelectionMessage());
|
||||
};
|
||||
|
||||
_menu.ServerSyncButton.OnPressed += (_) =>
|
||||
_menu.OnServerSyncButtonPressed += _ =>
|
||||
{
|
||||
SendMessage(new LatheServerSyncMessage());
|
||||
};
|
||||
|
||||
storage.OnMaterialStorageChanged += _menu.PopulateDisabled;
|
||||
storage.OnMaterialStorageChanged += _menu.PopulateMaterials;
|
||||
_menu.RecipeQueueAction += (recipe, amount) =>
|
||||
{
|
||||
SendMessage(new LatheQueueRecipeMessage(recipe, amount));
|
||||
};
|
||||
|
||||
_menu.OpenCentered();
|
||||
}
|
||||
|
||||
public void Queue(LatheRecipePrototype recipe, int quantity = 1)
|
||||
protected override void UpdateState(BoundUserInterfaceState state)
|
||||
{
|
||||
SendMessage(new LatheQueueRecipeMessage(recipe.ID, quantity));
|
||||
}
|
||||
base.UpdateState(state);
|
||||
|
||||
protected override void ReceiveMessage(BoundUserInterfaceMessage message)
|
||||
{
|
||||
switch (message)
|
||||
switch (state)
|
||||
{
|
||||
case LatheProducingRecipeMessage msg:
|
||||
if (!_prototypeManager.TryIndex(msg.ID, out LatheRecipePrototype? recipe)) break;
|
||||
_queueMenu?.SetInfo(recipe);
|
||||
break;
|
||||
case LatheStoppedProducingRecipeMessage _:
|
||||
_queueMenu?.ClearInfo();
|
||||
break;
|
||||
case LatheFullQueueMessage msg:
|
||||
_queuedRecipes.Clear();
|
||||
foreach (var id in msg.Recipes)
|
||||
{
|
||||
if (!_prototypeManager.TryIndex(id, out LatheRecipePrototype? recipePrototype)) break;
|
||||
_queuedRecipes.Enqueue(recipePrototype);
|
||||
}
|
||||
_queueMenu?.PopulateList();
|
||||
case LatheUpdateState msg:
|
||||
if (_menu != null)
|
||||
_menu.Recipes = msg.Recipes;
|
||||
_menu?.PopulateRecipes(Owner.Owner);
|
||||
_menu?.PopulateMaterials(Lathe);
|
||||
_queueMenu?.PopulateList(msg.Queue);
|
||||
_queueMenu?.SetInfo(msg.CurrentlyProducing);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -103,7 +66,8 @@ namespace Content.Client.Lathe.UI
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
if (!disposing) return;
|
||||
if (!disposing)
|
||||
return;
|
||||
_menu?.Dispose();
|
||||
_queueMenu?.Dispose();
|
||||
}
|
||||
|
||||
@@ -1,271 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Content.Client.Lathe.Components;
|
||||
using Content.Shared.Lathe;
|
||||
using Content.Shared.Materials;
|
||||
using Content.Shared.Research.Prototypes;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Client.Utility;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Prototypes;
|
||||
using static Robust.Client.UserInterface.Controls.BoxContainer;
|
||||
|
||||
namespace Content.Client.Lathe.UI
|
||||
{
|
||||
public sealed class LatheMenu : DefaultWindow
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
|
||||
private readonly ItemList _items;
|
||||
private readonly ItemList _materials;
|
||||
private readonly LineEdit _amountLineEdit;
|
||||
private readonly LineEdit _searchBar;
|
||||
public Button QueueButton;
|
||||
public Button ServerConnectButton;
|
||||
public Button ServerSyncButton;
|
||||
|
||||
public const float RecipeTooltipDelay = 0.5f;
|
||||
|
||||
public LatheBoundUserInterface Owner { get; }
|
||||
|
||||
private readonly List<LatheRecipePrototype> _shownRecipes = new();
|
||||
|
||||
public LatheMenu(LatheBoundUserInterface owner)
|
||||
{
|
||||
SetSize = MinSize = (300, 450);
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
Owner = owner;
|
||||
|
||||
Title = Loc.GetString("lathe-menu-title"); // TODO Replace this with the name of the lathe itself
|
||||
|
||||
var vBox = new BoxContainer
|
||||
{
|
||||
Orientation = LayoutOrientation.Vertical,
|
||||
VerticalExpand = true,
|
||||
SeparationOverride = 5,
|
||||
};
|
||||
|
||||
var hBoxButtons = new BoxContainer
|
||||
{
|
||||
Orientation = LayoutOrientation.Horizontal,
|
||||
HorizontalExpand = true,
|
||||
VerticalExpand = true,
|
||||
SizeFlagsStretchRatio = 1,
|
||||
};
|
||||
|
||||
QueueButton = new Button()
|
||||
{
|
||||
Text = Loc.GetString("lathe-menu-queue"),
|
||||
TextAlign = Label.AlignMode.Center,
|
||||
SizeFlagsStretchRatio = 1,
|
||||
};
|
||||
|
||||
ServerConnectButton = new Button()
|
||||
{
|
||||
Text = Loc.GetString("lathe-menu-server-list"),
|
||||
TextAlign = Label.AlignMode.Center,
|
||||
SizeFlagsStretchRatio = 1,
|
||||
};
|
||||
|
||||
ServerSyncButton = new Button()
|
||||
{
|
||||
Text = Loc.GetString("lathe-menu-sync"),
|
||||
TextAlign = Label.AlignMode.Center,
|
||||
SizeFlagsStretchRatio = 1,
|
||||
};
|
||||
|
||||
var spacer = new Control()
|
||||
{
|
||||
HorizontalExpand = true,
|
||||
SizeFlagsStretchRatio = 3,
|
||||
};
|
||||
|
||||
var hBoxFilter = new BoxContainer
|
||||
{
|
||||
Orientation = LayoutOrientation.Horizontal,
|
||||
HorizontalExpand = true,
|
||||
VerticalExpand = true,
|
||||
SizeFlagsStretchRatio = 1
|
||||
};
|
||||
|
||||
_searchBar = new LineEdit()
|
||||
{
|
||||
PlaceHolder = Loc.GetString("lathe-menu-search-designs"),
|
||||
HorizontalExpand = true,
|
||||
SizeFlagsStretchRatio = 3
|
||||
};
|
||||
|
||||
_searchBar.OnTextChanged += Populate;
|
||||
|
||||
var filterButton = new Button()
|
||||
{
|
||||
Text = Loc.GetString("lathe-menu-search-filter"),
|
||||
TextAlign = Label.AlignMode.Center,
|
||||
SizeFlagsStretchRatio = 1,
|
||||
Disabled = true,
|
||||
};
|
||||
|
||||
_items = new ItemList()
|
||||
{
|
||||
SizeFlagsStretchRatio = 8,
|
||||
VerticalExpand = true,
|
||||
SelectMode = ItemList.ItemListSelectMode.Button,
|
||||
};
|
||||
|
||||
// This is a shitty hack, because item lists apparently don't actually support tooltips. Yay..
|
||||
_items.OnItemHover += (ev) =>
|
||||
{
|
||||
ev.ItemList.HideTooltip();
|
||||
ev.ItemList.ToolTip = ev.ItemList[ev.ItemIndex].TooltipText;
|
||||
};
|
||||
_items.TooltipDelay = RecipeTooltipDelay;
|
||||
|
||||
_items.OnItemSelected += ItemSelected;
|
||||
|
||||
_amountLineEdit = new LineEdit()
|
||||
{
|
||||
PlaceHolder = Loc.GetString("lathe-menu-search-amount"),
|
||||
Text = "1",
|
||||
HorizontalExpand = true,
|
||||
};
|
||||
|
||||
_amountLineEdit.OnTextChanged += PopulateDisabled;
|
||||
|
||||
_materials = new ItemList()
|
||||
{
|
||||
VerticalExpand = true,
|
||||
SizeFlagsStretchRatio = 3
|
||||
};
|
||||
|
||||
hBoxButtons.AddChild(spacer);
|
||||
if (Owner.Database is ProtolatheDatabaseComponent database)
|
||||
{
|
||||
hBoxButtons.AddChild(ServerConnectButton);
|
||||
hBoxButtons.AddChild(ServerSyncButton);
|
||||
database.OnDatabaseUpdated += Populate;
|
||||
}
|
||||
hBoxButtons.AddChild(QueueButton);
|
||||
|
||||
hBoxFilter.AddChild(_searchBar);
|
||||
hBoxFilter.AddChild(filterButton);
|
||||
|
||||
vBox.AddChild(hBoxButtons);
|
||||
vBox.AddChild(hBoxFilter);
|
||||
vBox.AddChild(_items);
|
||||
vBox.AddChild(_amountLineEdit);
|
||||
vBox.AddChild(_materials);
|
||||
|
||||
Contents.AddChild(vBox);
|
||||
}
|
||||
|
||||
public void ItemSelected(ItemList.ItemListSelectedEventArgs args)
|
||||
{
|
||||
args.ItemList.HideTooltip();
|
||||
args.ItemList.ToolTip = args.ItemList[args.ItemIndex].TooltipText;
|
||||
|
||||
int.TryParse(_amountLineEdit.Text, out var quantity);
|
||||
if (quantity <= 0) quantity = 1;
|
||||
Owner.Queue(_shownRecipes[args.ItemIndex], quantity);
|
||||
}
|
||||
|
||||
public void PopulateMaterials()
|
||||
{
|
||||
_materials.Clear();
|
||||
|
||||
if (Owner.Storage == null) return;
|
||||
|
||||
foreach (var (id, amount) in Owner.Storage)
|
||||
{
|
||||
if (!_prototypeManager.TryIndex(id, out MaterialPrototype? materialPrototype)) continue;
|
||||
var material = materialPrototype;
|
||||
_materials.AddItem($"{material.Name} {amount} cm³", material.Icon.Frame0(), false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disables or enables shown recipes depending on whether there are enough materials for it or not.
|
||||
/// </summary>
|
||||
public void PopulateDisabled()
|
||||
{
|
||||
int.TryParse(_amountLineEdit.Text, out var quantity);
|
||||
if (quantity <= 0) quantity = 1;
|
||||
for (var i = 0; i < _shownRecipes.Count; i++)
|
||||
{
|
||||
var prototype = _shownRecipes[i];
|
||||
_items[i].Disabled = !Owner.Lathe?.CanProduce(prototype, quantity) ?? true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="PopulateDisabled()"/>
|
||||
public void PopulateDisabled(LineEdit.LineEditEventArgs args)
|
||||
{
|
||||
PopulateDisabled();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds shown recipes to the ItemList control.
|
||||
/// </summary>
|
||||
public void PopulateList()
|
||||
{
|
||||
_items.Clear();
|
||||
foreach (var prototype in _shownRecipes)
|
||||
{
|
||||
var item = _items.AddItem(prototype.Name, prototype.Icon.Frame0());
|
||||
|
||||
StringBuilder sb = new();
|
||||
bool first = true;
|
||||
foreach (var (id, quantity) in prototype.RequiredMaterials)
|
||||
{
|
||||
if (!_prototypeManager.TryIndex<MaterialPrototype>(id, out var proto))
|
||||
continue;
|
||||
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
sb.Append("\n");
|
||||
|
||||
sb.Append(quantity.ToString());
|
||||
sb.Append(" ");
|
||||
sb.Append(proto.Name);
|
||||
}
|
||||
|
||||
item.TooltipText = sb.ToString();
|
||||
}
|
||||
|
||||
PopulateDisabled();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populates the list of recipes that will actually be shown, using the current filters.
|
||||
/// </summary>
|
||||
public void Populate()
|
||||
{
|
||||
_shownRecipes.Clear();
|
||||
|
||||
if (Owner.Database == null) return;
|
||||
|
||||
foreach (var prototype in Owner.Database)
|
||||
{
|
||||
if (_searchBar.Text.Trim().Length != 0)
|
||||
{
|
||||
if (prototype.Name.ToLowerInvariant().Contains(_searchBar.Text.Trim().ToLowerInvariant()))
|
||||
_shownRecipes.Add(prototype);
|
||||
continue;
|
||||
}
|
||||
|
||||
_shownRecipes.Add(prototype);
|
||||
}
|
||||
|
||||
PopulateList();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Populate"/>
|
||||
public void Populate(LineEdit.LineEditEventArgs args)
|
||||
{
|
||||
Populate();
|
||||
}
|
||||
}
|
||||
}
|
||||
82
Content.Client/Lathe/UI/LatheMenu.xaml
Normal file
82
Content.Client/Lathe/UI/LatheMenu.xaml
Normal file
@@ -0,0 +1,82 @@
|
||||
<DefaultWindow
|
||||
xmlns="https://spacestation14.io"
|
||||
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
Title="{Loc 'lathe-menu-title'}"
|
||||
MinSize="300 450"
|
||||
SetSize="300 450">
|
||||
<BoxContainer
|
||||
Orientation="Vertical"
|
||||
VerticalExpand="True"
|
||||
SeparationOverride="5">
|
||||
<BoxContainer
|
||||
Orientation="Horizontal"
|
||||
Align="End"
|
||||
HorizontalExpand="True"
|
||||
VerticalExpand="True"
|
||||
SizeFlagsStretchRatio="1">
|
||||
<Button
|
||||
Name="QueueButton"
|
||||
Text="{Loc 'lathe-menu-queue'}"
|
||||
TextAlign="Center"
|
||||
Mode="Press"
|
||||
SizeFlagsStretchRatio="1">
|
||||
</Button>
|
||||
<Button
|
||||
Name="ServerListButton"
|
||||
Text="{Loc 'lathe-menu-server-list'}"
|
||||
TextAlign="Center"
|
||||
Mode="Press"
|
||||
SizeFlagsStretchRatio="1">
|
||||
</Button>
|
||||
<Button
|
||||
Name="ServerSyncButton"
|
||||
Text="{Loc 'lathe-menu-sync'}"
|
||||
TextAlign="Center"
|
||||
Mode="Press"
|
||||
SizeFlagsStretchRatio="1">
|
||||
</Button>
|
||||
</BoxContainer>
|
||||
<BoxContainer
|
||||
Orientation="Horizontal"
|
||||
HorizontalExpand="True"
|
||||
VerticalExpand="True"
|
||||
SizeFlagsStretchRatio="1">
|
||||
<LineEdit
|
||||
Name="SearchBar"
|
||||
PlaceHolder="{Loc 'lathe-menu-search-designs'}"
|
||||
HorizontalExpand="True"
|
||||
SizeFlagsStretchRatio="1">
|
||||
</LineEdit>
|
||||
<Button
|
||||
Name="FilterButton"
|
||||
Text="{Loc 'lathe-menu-search-filter'}"
|
||||
TextAlign="Center"
|
||||
SizeFlagsStretchRatio="1"
|
||||
Disabled="True">
|
||||
</Button>
|
||||
</BoxContainer>
|
||||
<ScrollContainer MinHeight="225">
|
||||
<BoxContainer
|
||||
Name="RecipeList"
|
||||
Orientation="Vertical"
|
||||
SizeFlagsStretchRatio="8"
|
||||
HorizontalExpand="True"
|
||||
VerticalExpand="True">
|
||||
</BoxContainer>
|
||||
</ScrollContainer>
|
||||
<LineEdit
|
||||
Name="AmountLineEdit"
|
||||
PlaceHolder="{Loc 'lathe-menu-search-amount'}"
|
||||
Text="1"
|
||||
HorizontalExpand="True">
|
||||
</LineEdit>
|
||||
<ItemList
|
||||
Name="Materials"
|
||||
VerticalExpand="True"
|
||||
SizeFlagsStretchRatio="3">
|
||||
</ItemList>
|
||||
</BoxContainer>
|
||||
</DefaultWindow>
|
||||
|
||||
|
||||
142
Content.Client/Lathe/UI/LatheMenu.xaml.cs
Normal file
142
Content.Client/Lathe/UI/LatheMenu.xaml.cs
Normal file
@@ -0,0 +1,142 @@
|
||||
using System.Text;
|
||||
using Content.Shared.Lathe;
|
||||
using Content.Shared.Materials;
|
||||
using Content.Shared.Research.Prototypes;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Client.Lathe.UI;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class LatheMenu : DefaultWindow
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
private readonly SpriteSystem _spriteSystem;
|
||||
private readonly LatheSystem _lathe;
|
||||
|
||||
public event Action<BaseButton.ButtonEventArgs>? OnQueueButtonPressed;
|
||||
public event Action<BaseButton.ButtonEventArgs>? OnServerListButtonPressed;
|
||||
public event Action<BaseButton.ButtonEventArgs>? OnServerSyncButtonPressed;
|
||||
public event Action<string, int>? RecipeQueueAction;
|
||||
|
||||
public List<string> Recipes = new();
|
||||
private List<LatheRecipePrototype> _oldRecipesToShow = new();
|
||||
|
||||
public LatheMenu(LatheBoundUserInterface owner)
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
_spriteSystem = _entityManager.EntitySysManager.GetEntitySystem<SpriteSystem>();
|
||||
_lathe = _entityManager.EntitySysManager.GetEntitySystem<LatheSystem>();
|
||||
|
||||
Title = _entityManager.GetComponent<MetaDataComponent>(owner.Lathe).EntityName;
|
||||
|
||||
SearchBar.OnTextChanged += _ =>
|
||||
{
|
||||
PopulateRecipes(owner.Lathe);
|
||||
};
|
||||
AmountLineEdit.OnTextChanged += _ =>
|
||||
{
|
||||
PopulateRecipes(owner.Lathe);
|
||||
};
|
||||
|
||||
QueueButton.OnPressed += a => OnQueueButtonPressed?.Invoke(a);
|
||||
ServerListButton.OnPressed += a => OnServerListButtonPressed?.Invoke(a);
|
||||
|
||||
//refresh the bui state
|
||||
ServerSyncButton.OnPressed += a => OnServerSyncButtonPressed?.Invoke(a);
|
||||
|
||||
if (_entityManager.TryGetComponent<LatheComponent>(owner.Lathe, out var latheComponent))
|
||||
{
|
||||
if (latheComponent.DynamicRecipes == null)
|
||||
{
|
||||
ServerListButton.Visible = false;
|
||||
ServerSyncButton.Visible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void PopulateMaterials(EntityUid lathe)
|
||||
{
|
||||
if (!_entityManager.TryGetComponent<MaterialStorageComponent>(lathe, out var materials))
|
||||
return;
|
||||
|
||||
Materials.Clear();
|
||||
foreach (var (id, amount) in materials.Storage)
|
||||
{
|
||||
if (!_prototypeManager.TryIndex(id, out MaterialPrototype? material))
|
||||
continue;
|
||||
var mat = Loc.GetString("lathe-menu-material-display",
|
||||
("material", material.Name), ("amount", amount));
|
||||
Materials.AddItem(mat, _spriteSystem.Frame0(material.Icon), false);
|
||||
}
|
||||
PopulateRecipes(lathe);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populates the list of all the recipes
|
||||
/// </summary>
|
||||
/// <param name="lathe"></param>
|
||||
public void PopulateRecipes(EntityUid lathe)
|
||||
{
|
||||
var recipesToShow = new List<LatheRecipePrototype>();
|
||||
foreach (var recipe in Recipes)
|
||||
{
|
||||
if (!_prototypeManager.TryIndex<LatheRecipePrototype>(recipe, out var proto))
|
||||
continue;
|
||||
|
||||
if (SearchBar.Text.Trim().Length != 0)
|
||||
{
|
||||
if (proto.Name.ToLowerInvariant().Contains(SearchBar.Text.Trim().ToLowerInvariant()))
|
||||
recipesToShow.Add(proto);
|
||||
}
|
||||
else
|
||||
{
|
||||
recipesToShow.Add(proto);
|
||||
}
|
||||
}
|
||||
|
||||
if (!int.TryParse(AmountLineEdit.Text, out var quantity) || quantity <= 0)
|
||||
quantity = 1;
|
||||
|
||||
RecipeList.Children.Clear();
|
||||
_oldRecipesToShow = recipesToShow;
|
||||
foreach (var prototype in recipesToShow)
|
||||
{
|
||||
StringBuilder sb = new();
|
||||
var first = true;
|
||||
foreach (var (id, amount) in prototype.RequiredMaterials)
|
||||
{
|
||||
if (!_prototypeManager.TryIndex<MaterialPrototype>(id, out var proto))
|
||||
continue;
|
||||
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
sb.Append('\n');
|
||||
|
||||
sb.Append(amount);
|
||||
sb.Append(' ');
|
||||
sb.Append(proto.Name);
|
||||
}
|
||||
|
||||
var icon = _spriteSystem.Frame0(prototype.Icon);
|
||||
var canProduce = _lathe.CanProduce(lathe, prototype, quantity);
|
||||
|
||||
var control = new RecipeControl(prototype, sb.ToString(), canProduce, icon);
|
||||
control.OnButtonPressed += s =>
|
||||
{
|
||||
if (!int.TryParse(AmountLineEdit.Text, out var amount) || amount <= 0)
|
||||
amount = 1;
|
||||
RecipeQueueAction?.Invoke(s, amount);
|
||||
};
|
||||
RecipeList.AddChild(control);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
using Content.Shared.Research.Prototypes;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Client.Utility;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.ViewVariables;
|
||||
using static Robust.Client.UserInterface.Controls.BoxContainer;
|
||||
|
||||
namespace Content.Client.Lathe.UI
|
||||
{
|
||||
public sealed class LatheQueueMenu : DefaultWindow
|
||||
{
|
||||
public LatheBoundUserInterface Owner { get; set; }
|
||||
|
||||
[ViewVariables]
|
||||
private readonly ItemList _queueList;
|
||||
private readonly Label _nameLabel;
|
||||
private readonly Label _description;
|
||||
private readonly TextureRect _icon;
|
||||
|
||||
public LatheQueueMenu(LatheBoundUserInterface owner)
|
||||
{
|
||||
Owner = owner;
|
||||
SetSize = MinSize = (300, 450);
|
||||
Title = Loc.GetString("lathe-queue-menu-title");
|
||||
|
||||
var vBox = new BoxContainer
|
||||
{
|
||||
Orientation = LayoutOrientation.Vertical
|
||||
};
|
||||
|
||||
var hBox = new BoxContainer
|
||||
{
|
||||
Orientation = LayoutOrientation.Horizontal,
|
||||
HorizontalExpand = true,
|
||||
SizeFlagsStretchRatio = 2,
|
||||
};
|
||||
|
||||
_icon = new TextureRect()
|
||||
{
|
||||
HorizontalExpand = true,
|
||||
SizeFlagsStretchRatio = 2,
|
||||
};
|
||||
|
||||
var vBoxInfo = new BoxContainer
|
||||
{
|
||||
Orientation = LayoutOrientation.Vertical,
|
||||
VerticalExpand = true,
|
||||
SizeFlagsStretchRatio = 3,
|
||||
};
|
||||
|
||||
_nameLabel = new Label()
|
||||
{
|
||||
RectClipContent = true,
|
||||
};
|
||||
|
||||
_description = new Label()
|
||||
{
|
||||
RectClipContent = true,
|
||||
VerticalAlignment = VAlignment.Stretch,
|
||||
VerticalExpand = true
|
||||
|
||||
};
|
||||
|
||||
_queueList = new ItemList()
|
||||
{
|
||||
VerticalExpand = true,
|
||||
SizeFlagsStretchRatio = 3,
|
||||
SelectMode = ItemList.ItemListSelectMode.None
|
||||
};
|
||||
|
||||
vBoxInfo.AddChild(_nameLabel);
|
||||
vBoxInfo.AddChild(_description);
|
||||
|
||||
hBox.AddChild(_icon);
|
||||
hBox.AddChild(vBoxInfo);
|
||||
|
||||
vBox.AddChild(hBox);
|
||||
vBox.AddChild(_queueList);
|
||||
|
||||
Contents.AddChild(vBox);
|
||||
|
||||
ClearInfo();
|
||||
}
|
||||
|
||||
public void SetInfo(LatheRecipePrototype recipe)
|
||||
{
|
||||
_icon.Texture = recipe.Icon.Frame0();
|
||||
if (recipe.Name != null)
|
||||
_nameLabel.Text = recipe.Name;
|
||||
if (recipe.Description != null)
|
||||
_description.Text = recipe.Description;
|
||||
}
|
||||
|
||||
public void ClearInfo()
|
||||
{
|
||||
_icon.Texture = Texture.Transparent;
|
||||
_nameLabel.Text = "-------";
|
||||
_description.Text = Loc.GetString("lathe-queue-menu-not-producing-text");
|
||||
}
|
||||
|
||||
public void PopulateList()
|
||||
{
|
||||
_queueList.Clear();
|
||||
var idx = 1;
|
||||
foreach (var recipe in Owner.QueuedRecipes)
|
||||
{
|
||||
_queueList.AddItem($"{idx}. {recipe.Name}", recipe.Icon.Frame0());
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
42
Content.Client/Lathe/UI/LatheQueueMenu.xaml
Normal file
42
Content.Client/Lathe/UI/LatheQueueMenu.xaml
Normal file
@@ -0,0 +1,42 @@
|
||||
<DefaultWindow
|
||||
xmlns="https://spacestation14.io"
|
||||
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
|
||||
Title="{Loc 'lathe-queue-menu-title'}"
|
||||
MinSize="300 450"
|
||||
SetSize="300 450">
|
||||
<BoxContainer Orientation="Vertical">
|
||||
<BoxContainer
|
||||
Orientation="Horizontal"
|
||||
HorizontalExpand="True"
|
||||
SizeFlagsStretchRatio="2">
|
||||
<TextureRect
|
||||
Name="Icon"
|
||||
HorizontalExpand="True"
|
||||
SizeFlagsStretchRatio="2">
|
||||
</TextureRect>
|
||||
<BoxContainer
|
||||
Orientation="Vertical"
|
||||
VerticalExpand="True"
|
||||
SizeFlagsStretchRatio="3">
|
||||
<Label
|
||||
Name="NameLabel"
|
||||
RectClipContent="True">
|
||||
</Label>
|
||||
<Label
|
||||
Name="Description"
|
||||
RectClipContent="True"
|
||||
VerticalAlignment="Stretch"
|
||||
VerticalExpand="True">
|
||||
</Label>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
<ItemList
|
||||
Name="QueueList"
|
||||
VerticalExpand="True"
|
||||
SizeFlagsStretchRatio="3"
|
||||
SelectMode="None">
|
||||
</ItemList>
|
||||
</BoxContainer>
|
||||
</DefaultWindow>
|
||||
|
||||
|
||||
52
Content.Client/Lathe/UI/LatheQueueMenu.xaml.cs
Normal file
52
Content.Client/Lathe/UI/LatheQueueMenu.xaml.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using Content.Shared.Research.Prototypes;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
|
||||
namespace Content.Client.Lathe.UI
|
||||
{
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class LatheQueueMenu : DefaultWindow
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
private readonly SpriteSystem _spriteSystem;
|
||||
|
||||
public LatheQueueMenu(LatheBoundUserInterface owner)
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
IoCManager.InjectDependencies(this);
|
||||
_spriteSystem = _entityManager.EntitySysManager.GetEntitySystem<SpriteSystem>();
|
||||
|
||||
SetInfo(null);
|
||||
}
|
||||
|
||||
public void SetInfo(LatheRecipePrototype? recipe)
|
||||
{
|
||||
if (recipe != null)
|
||||
{
|
||||
Icon.Texture = _spriteSystem.Frame0(recipe.Icon);
|
||||
NameLabel.Text = recipe.Name;
|
||||
Description.Text = recipe.Description;
|
||||
}
|
||||
else
|
||||
{
|
||||
Icon.Texture = Texture.Transparent;
|
||||
NameLabel.Text = string.Empty;
|
||||
Description.Text = Loc.GetString("lathe-queue-menu-not-producing-text");
|
||||
}
|
||||
}
|
||||
|
||||
public void PopulateList(List<LatheRecipePrototype> queue)
|
||||
{
|
||||
QueueList.Clear();
|
||||
var idx = 1;
|
||||
foreach (var recipe in queue)
|
||||
{
|
||||
QueueList.AddItem($"{idx}. {recipe.Name}", _spriteSystem.Frame0(recipe.Icon));
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
15
Content.Client/Lathe/UI/RecipeControl.xaml
Normal file
15
Content.Client/Lathe/UI/RecipeControl.xaml
Normal file
@@ -0,0 +1,15 @@
|
||||
<Control xmlns="https://spacestation14.io">
|
||||
<Button
|
||||
Name="Button"
|
||||
HorizontalExpand="True"
|
||||
TooltipDelay="0.5">
|
||||
<BoxContainer Orientation="Horizontal">
|
||||
<TextureRect
|
||||
Name="RecipeTexture"
|
||||
Margin="0,0,4,0"
|
||||
MinSize="32 32"
|
||||
Stretch="KeepAspectCentered" />
|
||||
<Label Name="RecipeName" HorizontalExpand="True" />
|
||||
</BoxContainer>
|
||||
</Button>
|
||||
</Control>
|
||||
28
Content.Client/Lathe/UI/RecipeControl.xaml.cs
Normal file
28
Content.Client/Lathe/UI/RecipeControl.xaml.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using Content.Shared.Research.Prototypes;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
|
||||
namespace Content.Client.Lathe.UI;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class RecipeControl : Control
|
||||
{
|
||||
public Action<string>? OnButtonPressed;
|
||||
|
||||
public RecipeControl(LatheRecipePrototype recipe, string tooltip, bool canProduce, Texture? texture = null)
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
|
||||
RecipeName.Text = recipe.Name;
|
||||
RecipeTexture.Texture = texture;
|
||||
Button.ToolTip = tooltip;
|
||||
Button.Disabled = !canProduce;
|
||||
|
||||
Button.OnPressed += (_) =>
|
||||
{
|
||||
OnButtonPressed?.Invoke(recipe.ID);
|
||||
};
|
||||
}
|
||||
}
|
||||
16
Content.Client/Materials/MaterialStorageSystem.cs
Normal file
16
Content.Client/Materials/MaterialStorageSystem.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using Content.Shared.Materials;
|
||||
using Robust.Client.GameObjects;
|
||||
|
||||
namespace Content.Client.Materials;
|
||||
|
||||
/// <summary>
|
||||
/// This handles...
|
||||
/// </summary>
|
||||
public sealed class MaterialStorageSystem : SharedMaterialStorageSystem
|
||||
{
|
||||
[Dependency] private readonly TransformSystem _transform = default!;
|
||||
protected override void OnFinishInsertMaterialEntity(EntityUid toInsert, MaterialStorageComponent component)
|
||||
{
|
||||
_transform.DetachParentToNull(Transform(toInsert));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user