Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

uplink and store freshening #26444

Merged
merged 5 commits into from
Apr 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions Content.Client/Store/Ui/StoreBoundUserInterface.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public sealed class StoreBoundUserInterface : BoundUserInterface
private string _windowName = Loc.GetString("store-ui-default-title");

[ViewVariables]
private string _search = "";
private string _search = string.Empty;

[ViewVariables]
private HashSet<ListingData> _listings = new();
Expand All @@ -41,19 +41,14 @@ protected override void Open()
_menu.OnCategoryButtonPressed += (_, category) =>
{
_menu.CurrentCategory = category;
SendMessage(new StoreRequestUpdateInterfaceMessage());
_menu?.UpdateListing();
};

_menu.OnWithdrawAttempt += (_, type, amount) =>
{
SendMessage(new StoreRequestWithdrawMessage(type, amount));
};

_menu.OnRefreshButtonPressed += (_) =>
{
SendMessage(new StoreRequestUpdateInterfaceMessage());
};

_menu.SearchTextUpdated += (_, search) =>
{
_search = search.Trim().ToLowerInvariant();
Expand Down
1 change: 1 addition & 0 deletions Content.Client/Store/Ui/StoreListingControl.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
Margin="0,0,4,0"
MinSize="48 48"
Stretch="KeepAspectCentered" />
<Control MinWidth="5"/>
<RichTextLabel Name="StoreItemDescription" />
</BoxContainer>
</BoxContainer>
Expand Down
80 changes: 73 additions & 7 deletions Content.Client/Store/Ui/StoreListingControl.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,25 +1,91 @@
using Content.Client.GameTicking.Managers;
using Content.Shared.Store;
using Robust.Client.AutoGenerated;
using Robust.Client.Graphics;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Graphics;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;

namespace Content.Client.Store.Ui;

[GenerateTypedNameReferences]
public sealed partial class StoreListingControl : Control
{
public StoreListingControl(string itemName, string itemDescription,
string price, bool canBuy, Texture? texture = null)
[Dependency] private readonly IPrototypeManager _prototype = default!;
[Dependency] private readonly IEntityManager _entity = default!;
[Dependency] private readonly IGameTiming _timing = default!;
private readonly ClientGameTicker _ticker;

private readonly ListingData _data;

private readonly bool _hasBalance;
private readonly string _price;
public StoreListingControl(ListingData data, string price, bool hasBalance, Texture? texture = null)
{
IoCManager.InjectDependencies(this);
RobustXamlLoader.Load(this);

StoreItemName.Text = itemName;
StoreItemDescription.SetMessage(itemDescription);
_ticker = _entity.System<ClientGameTicker>();

_data = data;
_hasBalance = hasBalance;
_price = price;

StoreItemBuyButton.Text = price;
StoreItemBuyButton.Disabled = !canBuy;
StoreItemName.Text = ListingLocalisationHelpers.GetLocalisedNameOrEntityName(_data, _prototype);
StoreItemDescription.SetMessage(ListingLocalisationHelpers.GetLocalisedDescriptionOrEntityDescription(_data, _prototype));

UpdateBuyButtonText();
StoreItemBuyButton.Disabled = !CanBuy();

StoreItemTexture.Texture = texture;
}

private bool CanBuy()
{
if (!_hasBalance)
return false;

var stationTime = _timing.CurTime.Subtract(_ticker.RoundStartTimeSpan);
if (_data.RestockTime > stationTime)
return false;

return true;
}

private void UpdateBuyButtonText()
{
var stationTime = _timing.CurTime.Subtract(_ticker.RoundStartTimeSpan);
if (_data.RestockTime > stationTime)
{
var timeLeftToBuy = stationTime - _data.RestockTime;
StoreItemBuyButton.Text = timeLeftToBuy.Duration().ToString(@"mm\:ss");
}
else
{
StoreItemBuyButton.Text = _price;
}
}

private void UpdateName()
{
var name = ListingLocalisationHelpers.GetLocalisedNameOrEntityName(_data, _prototype);

var stationTime = _timing.CurTime.Subtract(_ticker.RoundStartTimeSpan);
if (_data.RestockTime > stationTime)
{
name += Loc.GetString("store-ui-button-out-of-stock");
}

StoreItemName.Text = name;
}

protected override void FrameUpdate(FrameEventArgs args)
{
base.FrameUpdate(args);

UpdateBuyButtonText();
UpdateName();
StoreItemBuyButton.Disabled = !CanBuy();
}
}
5 changes: 0 additions & 5 deletions Content.Client/Store/Ui/StoreMenu.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,6 @@
HorizontalAlignment="Left"
Access="Public"
HorizontalExpand="True" />
<Button
Name="RefreshButton"
MinWidth="64"
HorizontalAlignment="Right"
Text="Refresh" />
<Button
Name="WithdrawButton"
MinWidth="64"
Expand Down
76 changes: 24 additions & 52 deletions Content.Client/Store/Ui/StoreMenu.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System.Linq;
using Content.Client.Actions;
using Content.Client.GameTicking.Managers;
using Content.Client.Message;
using Content.Shared.FixedPoint;
using Content.Shared.Store;
Expand All @@ -11,7 +10,6 @@
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;

namespace Content.Client.Store.Ui;

Expand All @@ -20,44 +18,39 @@ public sealed partial class StoreMenu : DefaultWindow
{
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly IEntitySystemManager _entitySystem = default!;
private readonly ClientGameTicker _gameTicker;

private StoreWithdrawWindow? _withdrawWindow;

public event EventHandler<string>? SearchTextUpdated;
public event Action<BaseButton.ButtonEventArgs, ListingData>? OnListingButtonPressed;
public event Action<BaseButton.ButtonEventArgs, string>? OnCategoryButtonPressed;
public event Action<BaseButton.ButtonEventArgs, string, int>? OnWithdrawAttempt;
public event Action<BaseButton.ButtonEventArgs>? OnRefreshButtonPressed;
public event Action<BaseButton.ButtonEventArgs>? OnRefundAttempt;

public Dictionary<string, FixedPoint2> Balance = new();
public Dictionary<ProtoId<CurrencyPrototype>, FixedPoint2> Balance = new();
public string CurrentCategory = string.Empty;

private List<ListingData> _cachedListings = new();

public StoreMenu(string name)
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);

_gameTicker = _entitySystem.GetEntitySystem<ClientGameTicker>();

WithdrawButton.OnButtonDown += OnWithdrawButtonDown;
RefreshButton.OnButtonDown += OnRefreshButtonDown;
RefundButton.OnButtonDown += OnRefundButtonDown;
SearchBar.OnTextChanged += _ => SearchTextUpdated?.Invoke(this, SearchBar.Text);

if (Window != null)
Window.Title = name;
}

public void UpdateBalance(Dictionary<string, FixedPoint2> balance)
public void UpdateBalance(Dictionary<ProtoId<CurrencyPrototype>, FixedPoint2> balance)
{
Balance = balance;

var currency = balance.ToDictionary(type =>
(type.Key, type.Value), type => _prototypeManager.Index<CurrencyPrototype>(type.Key));
(type.Key, type.Value), type => _prototypeManager.Index(type.Key));

var balanceStr = string.Empty;
foreach (var ((_, amount), proto) in currency)
Expand All @@ -80,7 +73,13 @@ public void UpdateBalance(Dictionary<string, FixedPoint2> balance)

public void UpdateListing(List<ListingData> listings)
{
var sorted = listings.OrderBy(l => l.Priority).ThenBy(l => l.Cost.Values.Sum());
_cachedListings = listings;
UpdateListing();
}

public void UpdateListing()
{
var sorted = _cachedListings.OrderBy(l => l.Priority).ThenBy(l => l.Cost.Values.Sum());

// should probably chunk these out instead. to-do if this clogs the internet tubes.
// maybe read clients prototypes instead?
Expand All @@ -96,12 +95,6 @@ public void SetFooterVisibility(bool visible)
TraitorFooter.Visible = visible;
}


private void OnRefreshButtonDown(BaseButton.ButtonEventArgs args)
{
OnRefreshButtonPressed?.Invoke(args);
}

private void OnWithdrawButtonDown(BaseButton.ButtonEventArgs args)
{
// check if window is already open
Expand Down Expand Up @@ -129,10 +122,8 @@ private void AddListingGui(ListingData listing)
if (!listing.Categories.Contains(CurrentCategory))
return;

var listingName = ListingLocalisationHelpers.GetLocalisedNameOrEntityName(listing, _prototypeManager);
var listingDesc = ListingLocalisationHelpers.GetLocalisedDescriptionOrEntityDescription(listing, _prototypeManager);
var listingPrice = listing.Cost;
var canBuy = CanBuyListing(Balance, listingPrice);
var hasBalance = HasListingPrice(Balance, listingPrice);

var spriteSys = _entityManager.EntitySysManager.GetEntitySystem<SpriteSystem>();

Expand All @@ -154,39 +145,15 @@ private void AddListingGui(ListingData listing)
texture = spriteSys.Frame0(action.Icon);
}
}
var listingInStock = ListingInStock(listing);
if (listingInStock != GetListingPriceString(listing))
{
listingName += " (Out of stock)";
canBuy = false;
}

var newListing = new StoreListingControl(listingName, listingDesc, listingInStock, canBuy, texture);
var newListing = new StoreListingControl(listing, GetListingPriceString(listing), hasBalance, texture);
newListing.StoreItemBuyButton.OnButtonDown += args
=> OnListingButtonPressed?.Invoke(args, listing);

StoreListingsContainer.AddChild(newListing);
}

/// <summary>
/// Return time until available or the cost.
/// </summary>
/// <param name="listing"></param>
/// <returns></returns>
public string ListingInStock(ListingData listing)
{
var stationTime = _gameTiming.CurTime.Subtract(_gameTicker.RoundStartTimeSpan);

TimeSpan restockTimeSpan = TimeSpan.FromMinutes(listing.RestockTime);
if (restockTimeSpan > stationTime)
{
var timeLeftToBuy = stationTime - restockTimeSpan;
return timeLeftToBuy.Duration().ToString(@"mm\:ss");
}

return GetListingPriceString(listing);
}
public bool CanBuyListing(Dictionary<string, FixedPoint2> currency, Dictionary<string, FixedPoint2> price)
public bool HasListingPrice(Dictionary<ProtoId<CurrencyPrototype>, FixedPoint2> currency, Dictionary<ProtoId<CurrencyPrototype>, FixedPoint2> price)
{
foreach (var type in price)
{
Expand All @@ -208,7 +175,7 @@ public string GetListingPriceString(ListingData listing)
{
foreach (var (type, amount) in listing.Cost)
{
var currency = _prototypeManager.Index<CurrencyPrototype>(type);
var currency = _prototypeManager.Index(type);
text += Loc.GetString("store-ui-price-display", ("amount", amount),
("currency", Loc.GetString(currency.DisplayName, ("amount", amount))));
}
Expand All @@ -229,7 +196,7 @@ public void PopulateStoreCategoryButtons(HashSet<ListingData> listings)
{
foreach (var cat in listing.Categories)
{
var proto = _prototypeManager.Index<StoreCategoryPrototype>(cat);
var proto = _prototypeManager.Index(cat);
if (!allCategories.Contains(proto))
allCategories.Add(proto);
}
Expand All @@ -248,12 +215,17 @@ public void PopulateStoreCategoryButtons(HashSet<ListingData> listings)
if (allCategories.Count < 1)
return;

var group = new ButtonGroup();
foreach (var proto in allCategories)
{
var catButton = new StoreCategoryButton
{
Text = Loc.GetString(proto.Name),
Id = proto.ID
Id = proto.ID,
Pressed = proto.ID == CurrentCategory,
Group = group,
ToggleMode = true,
StyleClasses = { "OpenBoth" }
};

catButton.OnPressed += args => OnCategoryButtonPressed?.Invoke(args, catButton.Id);
Expand All @@ -269,7 +241,7 @@ public override void Close()

public void UpdateRefund(bool allowRefund)
{
RefundButton.Disabled = !allowRefund;
RefundButton.Visible = allowRefund;
}

private sealed class StoreCategoryButton : Button
Expand Down
4 changes: 2 additions & 2 deletions Content.Client/Store/Ui/StoreWithdrawWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ public StoreWithdrawWindow()
IoCManager.InjectDependencies(this);
}

public void CreateCurrencyButtons(Dictionary<string, FixedPoint2> balance)
public void CreateCurrencyButtons(Dictionary<ProtoId<CurrencyPrototype>, FixedPoint2> balance)
{
_validCurrencies.Clear();
foreach (var currency in balance)
{
if (!_prototypeManager.TryIndex<CurrencyPrototype>(currency.Key, out var proto))
if (!_prototypeManager.TryIndex(currency.Key, out var proto))
continue;

_validCurrencies.Add(currency.Value, proto);
Expand Down
7 changes: 3 additions & 4 deletions Content.Server/Store/Systems/StoreSystem.Ui.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using Content.Server.Stack;
using Content.Server.Store.Components;
using Content.Shared.Actions;
using Content.Shared.Administration.Logs;
using Content.Shared.Database;
using Content.Shared.FixedPoint;
using Content.Shared.Hands.EntitySystems;
Expand Down Expand Up @@ -99,13 +98,13 @@ public void UpdateUserInterface(EntityUid? user, EntityUid store, StoreComponent
}

//dictionary for all currencies, including 0 values for currencies on the whitelist
Dictionary<string, FixedPoint2> allCurrency = new();
Dictionary<ProtoId<CurrencyPrototype>, FixedPoint2> allCurrency = new();
foreach (var supported in component.CurrencyWhitelist)
{
allCurrency.Add(supported, FixedPoint2.Zero);

if (component.Balance.ContainsKey(supported))
allCurrency[supported] = component.Balance[supported];
if (component.Balance.TryGetValue(supported, out var value))
allCurrency[supported] = value;
}

// TODO: if multiple users are supposed to be able to interact with a single BUI & see different
Expand Down
Loading
Loading