| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- using System.Linq;
- using System.Numerics;
- using Content.Shared.VendingMachines;
- using Robust.Client.AutoGenerated;
- using Robust.Client.UserInterface.Controls;
- using Robust.Client.UserInterface.XAML;
- using Robust.Shared.Prototypes;
- using FancyWindow = Content.Client.UserInterface.Controls.FancyWindow;
- using Robust.Client.UserInterface;
- using Content.Client.UserInterface.Controls;
- using Content.Shared.IdentityManagement;
- using Robust.Client.Graphics;
- namespace Content.Client.VendingMachines.UI
- {
- [GenerateTypedNameReferences]
- public sealed partial class VendingMachineMenu : FancyWindow
- {
- [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
- [Dependency] private readonly IEntityManager _entityManager = default!;
- private readonly Dictionary<EntProtoId, EntityUid> _dummies = [];
- private readonly Dictionary<EntProtoId, (ListContainerButton Button, VendingMachineItem Item)> _listItems = new();
- private readonly Dictionary<EntProtoId, uint> _amounts = new();
- /// <summary>
- /// Whether the vending machine is able to be interacted with or not.
- /// </summary>
- private bool _enabled;
- public event Action<GUIBoundKeyEventArgs, ListData>? OnItemSelected;
- public VendingMachineMenu()
- {
- MinSize = SetSize = new Vector2(250, 150);
- RobustXamlLoader.Load(this);
- IoCManager.InjectDependencies(this);
- VendingContents.SearchBar = SearchBar;
- VendingContents.DataFilterCondition += DataFilterCondition;
- VendingContents.GenerateItem += GenerateButton;
- VendingContents.ItemKeyBindDown += (args, data) => OnItemSelected?.Invoke(args, data);
- }
- protected override void Dispose(bool disposing)
- {
- base.Dispose(disposing);
- // Don't clean up dummies during disposal or we'll just have to spawn them again
- if (!disposing)
- return;
- // Delete any dummy items we spawned
- foreach (var entity in _dummies.Values)
- {
- _entityManager.QueueDeleteEntity(entity);
- }
- _dummies.Clear();
- }
- private bool DataFilterCondition(string filter, ListData data)
- {
- if (data is not VendorItemsListData { ItemText: var text })
- return false;
- if (string.IsNullOrEmpty(filter))
- return true;
- return text.Contains(filter, StringComparison.CurrentCultureIgnoreCase);
- }
- private void GenerateButton(ListData data, ListContainerButton button)
- {
- if (data is not VendorItemsListData { ItemProtoID: var protoID, ItemText: var text })
- return;
- var item = new VendingMachineItem(protoID, text);
- _listItems[protoID] = (button, item);
- button.AddChild(item);
- button.AddStyleClass("ButtonSquare");
- button.Disabled = !_enabled || _amounts[protoID] == 0;
- }
- /// <summary>
- /// Populates the list of available items on the vending machine interface
- /// and sets icons based on their prototypes
- /// </summary>
- public void Populate(List<VendingMachineInventoryEntry> inventory, bool enabled)
- {
- _enabled = enabled;
- _listItems.Clear();
- _amounts.Clear();
- if (inventory.Count == 0 && VendingContents.Visible)
- {
- SearchBar.Visible = false;
- VendingContents.Visible = false;
- var outOfStockLabel = new Label()
- {
- Text = Loc.GetString("vending-machine-component-try-eject-out-of-stock"),
- Margin = new Thickness(4, 4),
- HorizontalExpand = true,
- VerticalAlignment = VAlignment.Stretch,
- HorizontalAlignment = HAlignment.Center
- };
- MainContainer.AddChild(outOfStockLabel);
- SetSizeAfterUpdate(outOfStockLabel.Text.Length, 0);
- return;
- }
- var longestEntry = string.Empty;
- var listData = new List<VendorItemsListData>();
- for (var i = 0; i < inventory.Count; i++)
- {
- var entry = inventory[i];
- if (!_prototypeManager.TryIndex(entry.ID, out var prototype))
- {
- _amounts[entry.ID] = 0;
- continue;
- }
- if (!_dummies.TryGetValue(entry.ID, out var dummy))
- {
- dummy = _entityManager.Spawn(entry.ID);
- _dummies.Add(entry.ID, dummy);
- }
- var itemName = Identity.Name(dummy, _entityManager);
- var itemText = $"{itemName} [{entry.Amount}]";
- _amounts[entry.ID] = entry.Amount;
- if (itemText.Length > longestEntry.Length)
- longestEntry = itemText;
- listData.Add(new VendorItemsListData(prototype.ID, i)
- {
- ItemText = itemText,
- });
- }
- VendingContents.PopulateList(listData);
- SetSizeAfterUpdate(longestEntry.Length, inventory.Count);
- }
- /// <summary>
- /// Updates text entries for vending data in place without modifying the list controls.
- /// </summary>
- public void UpdateAmounts(List<VendingMachineInventoryEntry> cachedInventory, bool enabled)
- {
- _enabled = enabled;
- foreach (var proto in _dummies.Keys)
- {
- if (!_listItems.TryGetValue(proto, out var button))
- continue;
- var dummy = _dummies[proto];
- var amount = cachedInventory.First(o => o.ID == proto).Amount;
- // Could be better? Problem is all inventory entries get squashed.
- var text = GetItemText(dummy, amount);
- button.Item.SetText(text);
- button.Button.Disabled = !enabled || amount == 0;
- }
- }
- private string GetItemText(EntityUid dummy, uint amount)
- {
- var itemName = Identity.Name(dummy, _entityManager);
- return $"{itemName} [{amount}]";
- }
- private void SetSizeAfterUpdate(int longestEntryLength, int contentCount)
- {
- SetSize = new Vector2(Math.Clamp((longestEntryLength + 2) * 12, 250, 400),
- Math.Clamp(contentCount * 50, 150, 350));
- }
- }
- public record VendorItemsListData(EntProtoId ItemProtoID, int ItemIndex) : ListData
- {
- public string ItemText = string.Empty;
- }
- }
|