Implement SmartFridge functionality (#38648)

* Add SmartFridge

* my nit so pick

* my access so expanded and my whitelist so both

* list -> hashset
This commit is contained in:
pathetic meowmeow
2025-07-20 23:21:28 -04:00
committed by GitHub
parent 99b431cafd
commit d2ddbcbcda
17 changed files with 719 additions and 71 deletions

View File

@@ -0,0 +1,43 @@
using Content.Client.UserInterface.Controls;
using Content.Shared.SmartFridge;
using Robust.Client.UserInterface;
using Robust.Shared.Input;
namespace Content.Client.SmartFridge;
public sealed class SmartFridgeBoundUserInterface : BoundUserInterface
{
private SmartFridgeMenu? _menu;
public SmartFridgeBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
{
}
protected override void Open()
{
base.Open();
_menu = this.CreateWindow<SmartFridgeMenu>();
_menu.OnItemSelected += OnItemSelected;
Refresh();
}
public void Refresh()
{
if (_menu is not {} menu || !EntMan.TryGetComponent(Owner, out SmartFridgeComponent? fridge))
return;
menu.SetFlavorText(Loc.GetString(fridge.FlavorText));
menu.Populate((Owner, fridge));
}
private void OnItemSelected(GUIBoundKeyEventArgs args, ListData data)
{
if (args.Function != EngineKeyFunctions.UIClick)
return;
if (data is not SmartFridgeListData entry)
return;
SendPredictedMessage(new SmartFridgeDispenseItemMessage(entry.Entry));
}
}

View File

@@ -0,0 +1,16 @@
<BoxContainer xmlns="https://spacestation14.io"
Orientation="Horizontal"
HorizontalExpand="True"
SeparationOverride="4">
<SpriteView
Name="EntityView"
Margin="4 0 0 0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
MinSize="32 32"
/>
<Label Name="NameLabel"
SizeFlagsStretchRatio="3"
HorizontalExpand="True"
ClipText="True"/>
</BoxContainer>

View File

@@ -0,0 +1,18 @@
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Prototypes;
namespace Content.Client.SmartFridge;
[GenerateTypedNameReferences]
public sealed partial class SmartFridgeItem : BoxContainer
{
public SmartFridgeItem(EntityUid uid, string text)
{
RobustXamlLoader.Load(this);
EntityView.SetEntity(uid);
NameLabel.Text = text;
}
}

View File

@@ -0,0 +1,24 @@
<controls:FancyWindow
xmlns="https://spacestation14.io"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
xmlns:co="clr-namespace:Content.Client.UserInterface.Controls"
MinHeight="450"
MinWidth="350"
Title="{Loc 'smart-fridge-component-title'}">
<BoxContainer Name="MainContainer" Orientation="Vertical">
<LineEdit Name="SearchBar" PlaceHolder="{Loc 'smart-fridge-component-search-filter'}" HorizontalExpand="True" Margin ="4 4"/>
<co:SearchListContainer Name="VendingContents" VerticalExpand="True" Margin="4 4"/>
<!-- Footer -->
<BoxContainer Orientation="Vertical">
<PanelContainer StyleClasses="LowDivider" />
<BoxContainer Orientation="Horizontal" Margin="10 2 5 0" VerticalAlignment="Bottom">
<Label Name="LeftFlavorLabel" StyleClasses="WindowFooterText" />
<Label Text="{Loc 'vending-machine-flavor-right'}" StyleClasses="WindowFooterText"
HorizontalAlignment="Right" HorizontalExpand="True" Margin="0 0 5 0" />
<TextureRect StyleClasses="NTLogoDark" Stretch="KeepAspectCentered"
VerticalAlignment="Center" HorizontalAlignment="Right" SetSize="19 19"/>
</BoxContainer>
</BoxContainer>
</BoxContainer>
</controls:FancyWindow>

View File

@@ -0,0 +1,81 @@
using System.Linq;
using System.Numerics;
using Content.Client.UserInterface.Controls;
using Content.Shared.SmartFridge;
using Robust.Client.AutoGenerated;
using Robust.Client.Graphics;
using Robust.Client.UserInterface.XAML;
using Robust.Client.UserInterface;
namespace Content.Client.SmartFridge;
public record SmartFridgeListData(EntityUid Representative, SmartFridgeEntry Entry, int Amount) : ListData;
[GenerateTypedNameReferences]
public sealed partial class SmartFridgeMenu : FancyWindow
{
[Dependency] private readonly IEntityManager _entityManager = default!;
public event Action<GUIBoundKeyEventArgs, ListData>? OnItemSelected;
private readonly StyleBoxFlat _styleBox = new() { BackgroundColor = new Color(70, 73, 102) };
public SmartFridgeMenu()
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
VendingContents.SearchBar = SearchBar;
VendingContents.DataFilterCondition += DataFilterCondition;
VendingContents.GenerateItem += GenerateButton;
VendingContents.ItemKeyBindDown += (args, data) => OnItemSelected?.Invoke(args, data);
}
private bool DataFilterCondition(string filter, ListData data)
{
if (data is not SmartFridgeListData entry)
return false;
if (string.IsNullOrEmpty(filter))
return true;
return entry.Entry.Name.Contains(filter, StringComparison.CurrentCultureIgnoreCase);
}
private void GenerateButton(ListData data, ListContainerButton button)
{
if (data is not SmartFridgeListData entry)
return;
var label = Loc.GetString("smart-fridge-list-item", ("item", entry.Entry.Name), ("amount", entry.Amount));
button.AddChild(new SmartFridgeItem(entry.Representative, label));
button.ToolTip = label;
button.StyleBoxOverride = _styleBox;
}
public void Populate(Entity<SmartFridgeComponent> ent)
{
var listData = new List<ListData>();
foreach (var item in ent.Comp.Entries)
{
if (!ent.Comp.ContainedEntries.TryGetValue(item, out var items) || items.Count == 0)
{
listData.Add(new SmartFridgeListData(EntityUid.Invalid, item, 0));
}
else
{
var representative = _entityManager.GetEntity(items.First());
listData.Add(new SmartFridgeListData(representative, item, items.Count));
}
}
VendingContents.PopulateList(listData);
}
public void SetFlavorText(string flavor)
{
LeftFlavorLabel.Text = flavor;
}
}

View File

@@ -0,0 +1,24 @@
using Content.Shared.SmartFridge;
using Robust.Shared.Analyzers;
namespace Content.Client.SmartFridge;
public sealed class SmartFridgeUISystem : EntitySystem
{
[Dependency] private readonly SharedUserInterfaceSystem _uiSystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<SmartFridgeComponent, AfterAutoHandleStateEvent>(OnSmartFridgeAfterState);
}
private void OnSmartFridgeAfterState(Entity<SmartFridgeComponent> ent, ref AfterAutoHandleStateEvent args)
{
if (!_uiSystem.TryGetOpenUi<SmartFridgeBoundUserInterface>(ent.Owner, SmartFridgeUiKey.Key, out var bui))
return;
bui.Refresh();
}
}