Skip to content

Commit

Permalink
Merge branch 'master' into teach-lesson
Browse files Browse the repository at this point in the history
  • Loading branch information
sleepyyapril authored Jan 25, 2025
2 parents 57d867c + 3417f35 commit 3055e60
Show file tree
Hide file tree
Showing 399 changed files with 8,481 additions and 484 deletions.
6 changes: 1 addition & 5 deletions Content.Client/Chemistry/UI/ChemMasterBoundUserInterface.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ protected override void Open()
// Setup static button actions.
_window.InputEjectButton.OnPressed += _ => SendMessage(
new ItemSlotButtonPressedEvent(SharedChemMaster.InputSlotName));
_window.OutputEjectButton.OnPressed += _ => SendMessage(
new ItemSlotButtonPressedEvent(SharedChemMaster.OutputSlotName));
_window.BufferTransferButton.OnPressed += _ => SendMessage(
new ChemMasterSetModeMessage(ChemMasterMode.Transfer));
_window.BufferDiscardButton.OnPressed += _ => SendMessage(
Expand All @@ -49,11 +47,9 @@ protected override void Open()
_window.PillTypeButtons[i].OnPressed += _ => SendMessage(new ChemMasterSetPillTypeMessage(pillType));
}

_window.OnReagentButtonPressed += (_, button, amount) => SendMessage(new ChemMasterReagentAmountButtonMessage(button.Id, amount, button.IsBuffer));
_window.OnReagentButtonPressed += (_, button, amount, isOutput) => SendMessage(new ChemMasterReagentAmountButtonMessage(button.Id, amount, button.IsBuffer, isOutput));
_window.OnSortMethodChanged += sortMethod => SendMessage(new ChemMasterSortMethodUpdated(sortMethod));
_window.OnTransferAmountChanged += amount => SendMessage(new ChemMasterTransferringAmountUpdated(amount));


}

/// <summary>
Expand Down
237 changes: 124 additions & 113 deletions Content.Client/Chemistry/UI/ChemMasterWindow.xaml

Large diffs are not rendered by default.

229 changes: 173 additions & 56 deletions Content.Client/Chemistry/UI/ChemMasterWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,18 @@ namespace Content.Client.Chemistry.UI
public sealed partial class ChemMasterWindow : FancyWindow
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
public event Action<BaseButton.ButtonEventArgs, ReagentButton, int>? OnReagentButtonPressed;
public event Action<BaseButton.ButtonEventArgs, ReagentButton, int, bool>? OnReagentButtonPressed;
public event Action<int>? OnAmountButtonPressed;
public event Action<int>? OnSortMethodChanged;
public event Action<int>? OnTransferAmountChanged;
public readonly Button[] PillTypeButtons;

private Dictionary<string, ReagentCached> _reagents;
private const string TransferringAmountColor = "#ffa500";
private const string TransferringAmountColor = "#ffffff";
private ReagentSortMethod _currentSortMethod = ReagentSortMethod.Alphabetical;
private ChemMasterBoundUserInterfaceState? _lastState;
private string _lastAmountText = "50";
private int _transferAmount = 50;

private bool _isOutput = false;

private const string PillsRsiPath = "/Textures/Objects/Specific/Chemistry/pills.rsi";

Expand All @@ -49,12 +49,9 @@ public ChemMasterWindow()
IoCManager.InjectDependencies(this);

_reagents = new();

InputAmountLineEdit.OnTextEntered += SetAmount;
InputAmountLineEdit.OnFocusExit += SetAmount;

OutputAmountLineEdit.OnTextEntered += SetAmount;
OutputAmountLineEdit.OnFocusExit += SetAmount;
AmountLabel.HorizontalAlignment = HAlignment.Center;
AmountLineEdit.OnTextEntered += SetAmount;
AmountLineEdit.OnFocusExit += SetAmount;

// Pill type selection buttons, in total there are 20 pills.
// Pill rsi file should have states named as pill1, pill2, and so on.
Expand Down Expand Up @@ -109,12 +106,63 @@ public ChemMasterWindow()
SortMethod.AddItem(
Loc.GetString("chem-master-window-sort-method-Alphabetical-text"),
(int) ReagentSortMethod.Alphabetical);
SortMethod.AddItem(Loc.GetString("chem-master-window-sort-method-Amount-text"), (int) ReagentSortMethod.Amount);
SortMethod.AddItem(Loc.GetString("chem-master-window-sort-method-Time-text"), (int) ReagentSortMethod.Time);

SortMethod.AddItem(
Loc.GetString("chem-master-window-sort-method-Amount-text"),
(int) ReagentSortMethod.Amount);

SortMethod.AddItem(
Loc.GetString("chem-master-window-sort-method-Time-text"),
(int) ReagentSortMethod.Time);

SortMethod.OnItemSelected += HandleChildPressed;

PillSortMethod.AddItem(
Loc.GetString(
"chem-master-window-sort-method-Alphabetical-text"),
(int) ReagentSortMethod.Alphabetical);
PillSortMethod.AddItem(Loc.GetString(
"chem-master-window-sort-method-Amount-text"),
(int) ReagentSortMethod.Amount);
PillSortMethod.AddItem(
Loc.GetString("chem-master-window-sort-method-Time-text"),
(int) ReagentSortMethod.Time);

PillSortMethod.OnItemSelected += HandleChildPressed;

BufferTransferButton.OnPressed += HandleDiscardTransferPress;
BufferDiscardButton.OnPressed += HandleDiscardTransferPress;

var amounts = new List<int>()
{
1, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100, 125, 150, 175, 200, 225, 250, 275, 300, 500
};

for (int i = 0; i < amounts.Count; i++)
{
var styleClass = StyleBase.ButtonOpenBoth;
var amount = amounts[i];
var columns = AmountButtons.Columns;

if (i == 0 || i % columns == 0)
styleClass = StyleBase.ButtonOpenRight;

if ((i + 1) % columns == 0)
styleClass = StyleBase.ButtonOpenLeft;

var button = new Button()
{
Text = amount.ToString(),
MinSize = new(10, 10),
StyleClasses = { styleClass },
HorizontalExpand = true
};

button.OnPressed += _ => OnAmountButtonPressed?.Invoke(amount);
AmountButtons.AddChild(button);
}

OnAmountButtonPressed += amount => SetAmountText(amount.ToString());
}

private void HandleDiscardTransferPress(BaseButton.ButtonEventArgs args)
Expand All @@ -137,6 +185,8 @@ private void HandleSortMethodChange(int newSortMethod)

_currentSortMethod = (ReagentSortMethod) newSortMethod;
SortMethod.SelectId(newSortMethod);
PillSortMethod.SelectId(newSortMethod);

SortUpdated();
}

Expand All @@ -158,12 +208,10 @@ private bool ValidateAmount(string newText)
{
if (string.IsNullOrWhiteSpace(newText) || !int.TryParse(newText, out int amount))
{
InputAmountLineEdit.SetText(string.Empty);
OutputAmountLineEdit.SetText(string.Empty);
AmountLineEdit.SetText(string.Empty);
return false;
}

_lastAmountText = newText;
_transferAmount = amount;
OnTransferAmountChanged?.Invoke(amount);
return true;
Expand All @@ -174,29 +222,23 @@ private void SetAmount(LineEdit.LineEditEventArgs args) =>

private void SetAmountText(string newText)
{
if (newText == _lastAmountText)
return;

if (!ValidateAmount(newText))
if (newText == _transferAmount.ToString() || !ValidateAmount(newText))
return;

var localizedAmount = Loc.GetString(
"chem-master-window-transferring-label",
("quantity", newText),
("color", TransferringAmountColor));

InputAmountLabel.Text = localizedAmount;
OutputAmountLabel.Text = localizedAmount;

InputAmountLineEdit.SetText(string.Empty);
OutputAmountLineEdit.SetText(string.Empty);
AmountLabel.Text = localizedAmount;
AmountLineEdit.SetText(string.Empty);
}

private ReagentButton MakeReagentButton(string text, ReagentId id, bool isBuffer)
{
var reagentTransferButton = new ReagentButton(text, id, isBuffer);
reagentTransferButton.OnPressed += args
=> OnReagentButtonPressed?.Invoke(args, reagentTransferButton, _transferAmount);
=> OnReagentButtonPressed?.Invoke(args, reagentTransferButton, _transferAmount, Tabs.CurrentTab == 1);
return reagentTransferButton;
}
/// <summary>
Expand Down Expand Up @@ -237,60 +279,49 @@ public void UpdateState(BoundUserInterfaceState state)
HandleSortMethodChange(castState.SortMethod);
SetAmountText(castState.TransferringAmount.ToString());

BufferCurrentVolume.Text = $" {castState.BufferCurrentVolume?.Int() ?? 0}u";
BufferCurrentVolume.Text = $" {castState.PillBufferCurrentVolume?.Int() ?? 0}u";

InputEjectButton.Disabled = castState.InputContainerInfo is null;
OutputEjectButton.Disabled = castState.OutputContainerInfo is null;
CreateBottleButton.Disabled = castState.OutputContainerInfo?.Reagents == null;
CreatePillButton.Disabled = castState.OutputContainerInfo?.Entities == null;
InputEjectButton.Disabled = castState.ContainerInfo is null;
CreateBottleButton.Disabled = castState.PillBufferReagents.Count == 0;
CreatePillButton.Disabled = castState.PillBufferReagents.Count == 0;

UpdateDosageFields(castState);
}

private FixedPoint2 CurrentStateBufferVolume(ChemMasterBoundUserInterfaceState state) =>
(Tabs.CurrentTab == 0 ? state.BufferCurrentVolume : state.PillBufferCurrentVolume) ?? 0;

//assign default values for pill and bottle fields.
private void UpdateDosageFields(ChemMasterBoundUserInterfaceState castState)
{
var output = castState.OutputContainerInfo;
var remainingCapacity = output is null ? 0 : (output.MaxVolume - output.CurrentVolume).Int();
var holdsReagents = output?.Reagents != null;
var pillNumberMax = holdsReagents ? 0 : remainingCapacity;
var bottleAmountMax = holdsReagents ? remainingCapacity : 0;
var bufferVolume = castState.BufferCurrentVolume?.Int() ?? 0;

PillDosage.Value = (int)Math.Min(bufferVolume, castState.PillDosageLimit);
var bufferVolume = castState.PillBufferCurrentVolume?.Int() ?? 0;
PillDosage.Value = (int) Math.Min(bufferVolume, castState.PillDosageLimit);

PillTypeButtons[castState.SelectedPillType].Pressed = true;
PillNumber.IsValid = x => x >= 0 && x <= pillNumberMax;
PillNumber.IsValid = x => x >= 0;
PillDosage.IsValid = x => x > 0 && x <= castState.PillDosageLimit;
BottleDosage.IsValid = x => x >= 0 && x <= bottleAmountMax;

if (PillNumber.Value > pillNumberMax)
PillNumber.Value = pillNumberMax;
if (BottleDosage.Value > bottleAmountMax)
BottleDosage.Value = bottleAmountMax;
BottleDosage.IsValid = x => x >= 0;

// Avoid division by zero
if (PillDosage.Value > 0)
{
PillNumber.Value = Math.Min(bufferVolume / PillDosage.Value, pillNumberMax);
}
PillNumber.Value = bufferVolume / PillDosage.Value;
else
{
PillNumber.Value = 0;
}

BottleDosage.Value = Math.Min(bottleAmountMax, bufferVolume);
BottleDosage.Value = bufferVolume;
}
/// <summary>
/// Generate a product label based on reagents in the buffer.
/// </summary>
/// <param name="state">State data sent by the server.</param>
private string GenerateLabel(ChemMasterBoundUserInterfaceState state)
{
if (state.BufferCurrentVolume == 0)
if (CurrentStateBufferVolume(state) == 0)
return "";

var reagent = state.BufferReagents.OrderBy(r => r.Quantity).First().Reagent;
var buffer = Tabs.CurrentTab == 0 ? state.BufferReagents : state.PillBufferReagents;
var reagent = buffer.OrderBy(r => r.Quantity).First().Reagent;

_prototypeManager.TryIndex(reagent.Prototype, out ReagentPrototype? proto);
return proto?.LocalizedName ?? "";
}
Expand All @@ -304,15 +335,21 @@ private void UpdatePanelInfo(ChemMasterBoundUserInterfaceState state)
BufferTransferButton.Pressed = state.Mode == ChemMasterMode.Transfer;
BufferDiscardButton.Pressed = state.Mode == ChemMasterMode.Discard;

BuildContainerUI(InputContainerInfo, state.InputContainerInfo, true);
BuildContainerUI(OutputContainerInfo, state.OutputContainerInfo, false);
PillBufferTransferButton.Pressed = state.Mode == ChemMasterMode.Transfer;
PillBufferDiscardButton.Pressed = state.Mode == ChemMasterMode.Discard;

BuildContainerUI(ContainerInfoContainer, state.ContainerInfo, true);
BuildBufferInfo(state);
BuildPillBufferInfo(state);
}

private void BuildBufferInfo(ChemMasterBoundUserInterfaceState state)
{
BufferInfo.Children.Clear();

if (!state.BufferReagents.Any())
{
BufferInfo.Children.Add(new Label { Text = Loc.GetString("chem-master-window-buffer-empty-text") });

return;
}

Expand Down Expand Up @@ -386,6 +423,86 @@ private void UpdatePanelInfo(ChemMasterBoundUserInterfaceState state)
}
}

private void BuildPillBufferInfo(ChemMasterBoundUserInterfaceState state)
{
PillBufferInfo.Children.Clear();

if (!state.PillBufferReagents.Any())
{
PillBufferInfo.Children.Add(new Label { Text = Loc.GetString("chem-master-window-buffer-empty-text") });
return;
}

var bufferHBox = new BoxContainer
{
Orientation = LayoutOrientation.Horizontal
};
PillBufferInfo.AddChild(bufferHBox);

var bufferLabel = new Label { Text = $"{Loc.GetString("chem-master-window-buffer-label")} " };
bufferHBox.AddChild(bufferLabel);
var bufferVol = new Label
{
Text = $"{state.PillBufferCurrentVolume}u",
StyleClasses = { StyleNano.StyleClassLabelSecondaryColor }
};
bufferHBox.AddChild(bufferVol);

// initialises rowCount to allow for striped rows
var rowCount = 0;
var bufferReagents = state.PillBufferReagents.OrderBy(x => x.Reagent.Prototype);

if (_currentSortMethod == ReagentSortMethod.Amount)
bufferReagents = bufferReagents.OrderByDescending(x => x.Quantity);

if (_currentSortMethod == ReagentSortMethod.Time)
{
bufferReagents = bufferReagents.OrderByDescending(
x =>
{
var exists = _reagents.TryGetValue(x.Reagent.Prototype, out var reagent);
return exists && reagent != null ? reagent.TimeAdded : DateTimeOffset.UtcNow;
});
}

var bufferAsNames = bufferReagents.Select(r => r.Reagent.Prototype).ToHashSet();
var hashSetCachedReagents = _reagents.Keys.ToHashSet();
hashSetCachedReagents.ExceptWith(bufferAsNames);

foreach (var missing in hashSetCachedReagents)
_reagents.Remove(missing);

foreach (var (reagent, quantity) in bufferReagents)
{
var reagentId = reagent;
_prototypeManager.TryIndex(reagentId.Prototype, out ReagentPrototype? proto);
var name = proto?.LocalizedName ?? Loc.GetString("chem-master-window-unknown-reagent-text");
var reagentColor = proto?.SubstanceColor ?? default(Color);
PillBufferInfo.Children.Add(BuildReagentRow(reagentColor, rowCount++, name, reagentId, quantity, true, true));

var exists = _reagents.TryGetValue(reagent.Prototype, out var reagentCached);

if (!exists)
{
reagentCached = new()
{
Id = reagentId,
Quantity = quantity,
TimeAdded = reagentCached?.TimeAdded ?? DateTimeOffset.UtcNow
};

_reagents.Add(reagentId.Prototype, reagentCached);
}
else
{
reagentCached!.Quantity = quantity;
reagentCached!.Id = reagentId;

_reagents[reagentId.Prototype] = reagentCached;
}
}
}

private void BuildContainerUI(Control control, ContainerInfo? info, bool addReagentButtons)
{
control.Children.Clear();
Expand Down
3 changes: 2 additions & 1 deletion Content.Client/DoAfter/DoAfterOverlay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,8 @@ protected override void Draw(in OverlayDrawArgs args)
var alpha = 1f;
if (doAfter.Args.Hidden)
{
if (uid != localEnt)
// Goobstation - Show doAfter progress bar to another entity
if (uid != localEnt && localEnt != doAfter.Args.ShowTo)
continue;

// Hints to the local player that this do-after is not visible to other players.
Expand Down
Loading

0 comments on commit 3055e60

Please sign in to comment.