Skip to content

Commit

Permalink
Add Components, Systems, Events, and UI for Changing Reagent Whitelist
Browse files Browse the repository at this point in the history
  • Loading branch information
blueDev2 committed May 26, 2024
1 parent f20009d commit 9bd9255
Show file tree
Hide file tree
Showing 8 changed files with 285 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using Content.Shared._NF.Chemistry.Events;
using Content.Shared.Chemistry;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.FixedPoint;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Shared.Prototypes;

namespace Content.Client._NF.Chemistry.UI
{
[UsedImplicitly]
public sealed class ChangeReagentWhitelistBoundUserInterface : BoundUserInterface
{
private ChangeReagentWhitelistWindow? _window;
public ChangeReagentWhitelistBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
{
}

protected override void Open()
{
base.Open();
_window = new ChangeReagentWhitelistWindow(this);

_window.OnClose += Close;
_window.OpenCentered();
}

protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (!disposing) return;
_window?.Dispose();
}
public void ChangeReagentWhitelist(ProtoId<ReagentPrototype> newReagentProto)
{
SendMessage(new ReagentWhitelistChangeMessage(newReagentProto));
}
}
}
10 changes: 10 additions & 0 deletions Content.Client/_NF/Chemistry/UI/ChangeReagentWhitelistWindow.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<DefaultWindow
SetSize="250 300"
Margin="4 0"
xmlns="https://spacestation14.io">
<BoxContainer Orientation="Vertical">
<LineEdit Name="SearchBar" PlaceHolder="{Loc 'admin-add-reagent-window-search-placeholder'}" HorizontalExpand="True" Margin ="0 4"/>
<ItemList Name="ReagentList" SelectMode="Single" VerticalExpand="True" Margin ="0 4"/>
<Button Name="AddButton" HorizontalExpand="True" Margin ="0 4" />
</BoxContainer>
</DefaultWindow>
128 changes: 128 additions & 0 deletions Content.Client/_NF/Chemistry/UI/ChangeReagentWhitelistWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
using Content.Shared._NF.Chemistry.Components;
using Content.Shared._NF.Chemistry.Events;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Reagent;
using FastAccessors;
using Microsoft.CodeAnalysis;
using Robust.Client.AutoGenerated;
using Robust.Client.Console;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Prototypes;

namespace Content.Client._NF.Chemistry.UI;

/// <summary>
/// A window that allows you to change the whitelist of the associated injector
/// </summary>
[GenerateTypedNameReferences]
public sealed partial class ChangeReagentWhitelistWindow : DefaultWindow
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;

private readonly EntityUid _injectorEntity;
private readonly ChangeReagentWhitelistBoundUserInterface _owner;
private ReagentPrototype? _selectedReagent;

public ChangeReagentWhitelistWindow(ChangeReagentWhitelistBoundUserInterface owner)
{
IoCManager.InjectDependencies(this);
RobustXamlLoader.Load(this);

_injectorEntity = owner.Owner;
_owner = owner;

// For debuging purposes only, replace before merging
Title = "Reagent Filter";

ReagentList.OnItemSelected += ReagentListSelected;
ReagentList.OnItemDeselected += ReagentListDeselected;
SearchBar.OnTextChanged += (_) => UpdateReagentPrototypes(SearchBar.Text);
AddButton.OnPressed += ChangeWhitelistedReagent;

UpdateReagentPrototypes();
UpdateAddButton();
}

/// <summary>
/// Execute a console command that asks the server to add the selected reagent.
/// </summary>
private void ChangeWhitelistedReagent(BaseButton.ButtonEventArgs obj)
{
if (_selectedReagent == null)
return;

_owner.ChangeReagentWhitelist(_selectedReagent);

}

private void ReagentListSelected(ItemList.ItemListSelectedEventArgs obj)
{
_selectedReagent = (ReagentPrototype) obj.ItemList[obj.ItemIndex].Metadata!;
UpdateAddButton();
}

private void ReagentListDeselected(ItemList.ItemListDeselectedEventArgs obj)
{
_selectedReagent = null;
UpdateAddButton();
}

/// <summary>
/// Set the Text and enabled/disabled status of the button that actually adds the reagent.
/// </summary>
private void UpdateAddButton()
{
AddButton.Disabled = true;
if (_selectedReagent == null)
{
AddButton.Text = Loc.GetString("admin-add-reagent-window-add-invalid-reagent");
return;
}

AddButton.Text = Loc.GetString("admin-add-reagent-window-add",
("reagent", _selectedReagent.ID));

AddButton.Disabled = false;
}

/// <summary>
/// Get a list of all applicable reagent prototypes and show them in an item list.
/// </summary>
private void UpdateReagentPrototypes(string? filter = null)
{
ReagentList.Clear();

List<string> allowedReagentGroups = new();
if (_entityManager.TryGetComponent<ReagentWhitelistChangeComponent>(_injectorEntity, out var reagentWhitelistChangeComp))
{
allowedReagentGroups = reagentWhitelistChangeComp.AllowedReagentGroups;
}


foreach (var reagent in _prototypeManager.EnumeratePrototypes<ReagentPrototype>())
{
if (!string.IsNullOrEmpty(filter) &&
!reagent.ID.ToLowerInvariant().Contains(filter.Trim().ToLowerInvariant()))
{
continue;
}

if (!allowedReagentGroups.Contains(reagent.Group))
{
continue;
}

ItemList.Item regentItem = new(ReagentList)
{
Metadata = reagent,
Text = reagent.ID
};

ReagentList.Add(regentItem);
}
}
}

4 changes: 3 additions & 1 deletion Content.Server/Chemistry/EntitySystems/InjectorSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ private void TryDraw(Entity<InjectorComponent> injector, Entity<BloodstreamCompo
return;
}

// Frontier - Reagent Whitelist
var applicableTargetSolution = targetSolution.Comp.Solution;
// If a whitelist exists, remove all non-whitelisted reagents from the target solution temporarily
Solution temporarilyRemovedSolution = new();
Expand All @@ -342,6 +343,7 @@ private void TryDraw(Entity<InjectorComponent> injector, Entity<BloodstreamCompo
}
temporarilyRemovedSolution = applicableTargetSolution.SplitSolutionWithout(applicableTargetSolution.Volume, reagentPrototypeWhitelistArray);
}
// Frontier - Reagent Whitelist

// Get transfer amount. May be smaller than _transferAmount if not enough room, also make sure there's room in the injector
var realTransferAmount = FixedPoint2.Min(injector.Comp.TransferAmount, applicableTargetSolution.Volume,
Expand All @@ -366,7 +368,7 @@ private void TryDraw(Entity<InjectorComponent> injector, Entity<BloodstreamCompo
// Move units from attackSolution to targetSolution
var removedSolution = SolutionContainers.Draw(target.Owner, targetSolution, realTransferAmount);

// Add back non-whitelisted reagents to the target solution
// Add back non-whitelisted reagents to the target solution, Frontier - Reagent Whitelist
applicableTargetSolution.AddSolution(temporarilyRemovedSolution, null);

if (!SolutionContainers.TryAddSolution(soln.Value, removedSolution))
Expand Down
1 change: 1 addition & 0 deletions Content.Shared/Chemistry/Components/InjectorComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ public sealed partial class InjectorComponent : Component
[DataField]
public InjectorToggleMode ToggleState = InjectorToggleMode.Draw;

// Frontier
/// <summary>
/// Reagents that are allowed to be within this injector.
/// If a solution has both allowed and non-allowed reagents, only allowed reagents will be drawn into this injector.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Content.Shared.FixedPoint;
using Robust.Shared.GameStates;

namespace Content.Shared._NF.Chemistry.Components;

/// <summary>
/// Gives click behavior for changing injector reagent whitelist.
/// </summary>
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
public sealed partial class ReagentWhitelistChangeComponent : Component
{
/// <summary>
/// The type of reagents allowed to be selected to change the reagent whitelist
/// </summary>
[DataField("allowedReagentGroup")]
[AutoNetworkedField]
[ViewVariables(VVAccess.ReadWrite)]
public List<string> AllowedReagentGroups = new();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@

using Content.Shared._NF.Chemistry.Components;
using Content.Shared._NF.Chemistry.Events;
using Content.Shared.Chemistry.Components;
using Content.Shared.Verbs;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;


namespace Content.Shared._NF.Chemistry.EntitySystems;

/// <summary>
/// Allows an entity to change an injector component's whitelist via a UI box
/// </summary>
public sealed class ReagentWhitelistChangeSystem : EntitySystem
{
[Dependency] private readonly SharedUserInterfaceSystem _ui = default!;
[NetSerializable, Serializable]
public enum ReagentWhitelistChangeUIKey : byte
{
Key
}
public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<ReagentWhitelistChangeComponent, GetVerbsEvent<InteractionVerb>>(AddChangeFilterVerb);
SubscribeLocalEvent<ReagentWhitelistChangeComponent, ReagentWhitelistChangeMessage>(OnReagentWhitelistChange);
}

private void AddChangeFilterVerb(Entity<ReagentWhitelistChangeComponent> ent, ref GetVerbsEvent<InteractionVerb> args)
{
var (uid, comp) = ent;

if (!args.CanAccess || !args.CanInteract || args.Hands == null)
return;
var @event = args;
args.Verbs.Add(new InteractionVerb()
{
// For debuging purposes only, replace before merging
Text = "Set Reagent Filter",
//Icon = new SpriteSpecifier(),
Act = () =>
{
_ui.OpenUi(uid, ReagentWhitelistChangeUIKey.Key, @event.User);
},
Priority = 1
});
}

private void OnReagentWhitelistChange(Entity<ReagentWhitelistChangeComponent> ent, ref ReagentWhitelistChangeMessage args)
{
if (!TryComp<InjectorComponent>(ent.Owner, out var injectorComp) || injectorComp.ReagentWhitelist is null)
{
return;
}

if (!ent.Comp.AllowedReagentGroups.Contains(args.NewReagentProto))
{
return;
}
injectorComp.ReagentWhitelist.Clear();
injectorComp.ReagentWhitelist.Add(args.NewReagentProto);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using Content.Shared.Chemistry.Reagent;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;

namespace Content.Shared._NF.Chemistry.Events;


/// <summary>
/// Sends a message to change the associated injector component's ReagentWhitelist to the newReagent
/// </summary>
[Serializable, NetSerializable]
public sealed class ReagentWhitelistChangeMessage : BoundUserInterfaceMessage
{
public ProtoId<ReagentPrototype> NewReagentProto;

public ReagentWhitelistChangeMessage(ProtoId<ReagentPrototype> newReagentProto)
{
NewReagentProto = newReagentProto;
}
}

0 comments on commit 9bd9255

Please sign in to comment.