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

A rudimentary implementation of multiple access levels for the purpose of restrictive cargo ordering #34755

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
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
24 changes: 24 additions & 0 deletions Content.Client/Cargo/BUI/CargoOrderConsoleBoundUserInterface.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using Content.Shared.IdentityManagement;
using Robust.Client.GameObjects;
using Robust.Client.Player;
using Robust.Client.UserInterface;
using Robust.Shared.Utility;
using Robust.Shared.Prototypes;
using static Robust.Client.UserInterface.Controls.BaseButton;
Expand Down Expand Up @@ -88,6 +89,7 @@ protected override void Open()
};
_menu.OnOrderApproved += ApproveOrder;
_menu.OnOrderCanceled += RemoveOrder;
_menu.OnOrderRestricted += RestrictOrder;
_orderMenu.SubmitButton.OnPressed += (_) =>
{
if (AddOrder())
Expand All @@ -99,6 +101,10 @@ protected override void Open()
_menu.OpenCentered();
}

/// <summary>
/// Triggers the population of the dynamic elements of the cargo request UI
/// </summary>
/// <param name="orders">List of current cargo orders</param>
private void Populate(List<CargoOrderData> orders)
{
if (_menu == null) return;
Expand All @@ -121,6 +127,7 @@ protected override void UpdateState(BoundUserInterfaceState state)

AccountName = cState.Name;

_menu?.UpdateRestrictedData(cState.RestrictedOrders);
Populate(cState.Orders);
_menu?.UpdateCargoCapacity(OrderCount, OrderCapacity);
_menu?.UpdateBankData(AccountName, BankBalance);
Expand Down Expand Up @@ -173,5 +180,22 @@ private void ApproveOrder(ButtonEventArgs args)
// Most of the UI isn't predicted anyway so.
// _menu?.UpdateCargoCapacity(OrderCount + row.Order.Amount, OrderCapacity);
}

private void RestrictOrder(ButtonEventArgs args)
GansuLalan marked this conversation as resolved.
Show resolved Hide resolved
{
// Better implementation courtesy of gusxyz
Control control = args.Button;

while (control.Parent != null)
{
if (control.Parent is CargoProductRow { Product: not null } row)
{
SendMessage(new CargoConsoleRestrictProductMessage(row.Product.ID));
return;
}

control = control.Parent;
}
}
}
}
3 changes: 3 additions & 0 deletions Content.Client/Cargo/Systems/CargoSystem.Telepad.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ private void OnChangeData(EntityUid uid, SpriteComponent? sprite = null)
if (_player.HasRunningAnimation(uid, TelepadBeamKey))
return;
_player.Stop(uid, player, TelepadIdleKey);
// My client will crash if this check isn't here as stopping the idle annimation will otherwise cause TelepadBeamKey to be played twice
if (_player.HasRunningAnimation(uid, TelepadBeamKey))
return;
_player.Play(uid, player, CargoTelepadBeamAnimation, TelepadBeamKey);
break;
case CargoTelepadState.Unpowered:
Expand Down
25 changes: 25 additions & 0 deletions Content.Client/Cargo/UI/CargoConsoleMenu.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ public sealed partial class CargoConsoleMenu : FancyWindow
public event Action<ButtonEventArgs>? OnItemSelected;
public event Action<ButtonEventArgs>? OnOrderApproved;
public event Action<ButtonEventArgs>? OnOrderCanceled;
public event Action<ButtonEventArgs>? OnOrderRestricted;

private readonly List<string> _categoryStrings = new();
private string? _category;
private List<CargoRestrictedData> _restrictedData = new();

public CargoConsoleMenu(EntityUid owner, IEntityManager entMan, IPrototypeManager protoManager, SpriteSystem spriteSystem)
{
Expand Down Expand Up @@ -85,6 +87,8 @@ public void PopulateProducts()
string.Compare(x.Name, y.Name, StringComparison.CurrentCultureIgnoreCase));

var search = SearchBar.Text.Trim().ToLowerInvariant();

var restrictedIds = GetRestrictedIds();
foreach (var prototype in products)
{
// if no search or category
Expand All @@ -95,18 +99,24 @@ public void PopulateProducts()
search.Length != 0 && prototype.Description.ToLowerInvariant().Contains(search) ||
search.Length == 0 && _category != null && Loc.GetString(prototype.Category).Equals(_category))
{

var button = new CargoProductRow
{
Product = prototype,
ProductName = { Text = prototype.Name },
MainButton = { ToolTip = prototype.Description },
PointCost = { Text = Loc.GetString("cargo-console-menu-points-amount", ("amount", prototype.Cost.ToString())) },
Icon = { Texture = _spriteSystem.Frame0(prototype.Icon) },
Restricted = { Pressed = restrictedIds.Contains(prototype.ID) },
};
button.MainButton.OnPressed += args =>
{
OnItemSelected?.Invoke(args);
};
button.Restricted.OnPressed += args =>
{
OnOrderRestricted?.Invoke(args);
};
Products.AddChild(button);
}
}
Expand Down Expand Up @@ -194,5 +204,20 @@ public void UpdateBankData(string name, int points)
AccountNameLabel.Text = name;
PointsLabel.Text = Loc.GetString("cargo-console-menu-points-amount", ("amount", points.ToString()));
}

public void UpdateRestrictedData(IEnumerable<CargoRestrictedData> restrictedData)
{
_restrictedData = restrictedData.ToList();
}

public List<string> GetRestrictedIds()
{
List<string> restrictedIds = new();
foreach (var restrictedData in _restrictedData)
{
restrictedIds.Add(restrictedData.ProductId);
}
return restrictedIds;
}
}
}
41 changes: 23 additions & 18 deletions Content.Client/Cargo/UI/CargoProductRow.xaml
Original file line number Diff line number Diff line change
@@ -1,24 +1,29 @@
<PanelContainer xmlns="https://spacestation14.io"
HorizontalExpand="True">
<Button Name="MainButton"
ToolTip=""
<PanelContainer HorizontalExpand="True" xmlns="https://spacestation14.io">
<Button
Access="Public"
HorizontalExpand="True"
Name="MainButton"
ToolTip=""
VerticalExpand="True" />
<BoxContainer HorizontalExpand="True" Orientation="Horizontal">
<TextureRect
Access="Public"
MinSize="32 32"
Name="Icon"
RectClipContent="True" />
<Label
Access="Public"
HorizontalExpand="True"
VerticalExpand="True" />
<BoxContainer Orientation="Horizontal"
HorizontalExpand="True">
<TextureRect Name="Icon"
Access="Public"
MinSize="32 32"
RectClipContent="True" />
<Label Name="ProductName"
Access="Public"
HorizontalExpand="True" />
Name="ProductName" />
<PanelContainer StyleClasses="BackgroundDark">
<Label Name="PointCost"
Access="Public"
MinSize="52 32"
Align="Right" />
<BoxContainer HorizontalExpand="True" Orientation="Horizontal">
<CheckBox Access="Public" Name="Restricted" />
<Label
Access="Public"
Align="Right"
MinSize="52 32"
Name="PointCost" />
</BoxContainer>
</PanelContainer>
</BoxContainer>
</PanelContainer>
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ public sealed partial class StationCargoOrderDatabaseComponent : Component
[ViewVariables(VVAccess.ReadWrite), DataField("orders")]
public List<CargoOrderData> Orders = new();

/// <summary>
/// Carries a hashSet of restricted cargo orders, currently minimal information but has a custom data class in case
/// more is ever added
/// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField("restricted")]
public HashSet<CargoRestrictedData> RestrictedOrders = new();

/// <summary>
/// Used to determine unique order IDs
/// </summary>
Expand Down
67 changes: 66 additions & 1 deletion Content.Server/Cargo/Systems/CargoSystem.Orders.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Content.Server.Cargo.Components;
using Content.Server.Labels.Components;
using Content.Server.Station.Components;
Expand Down Expand Up @@ -42,6 +43,7 @@ private void InitializeConsole()
SubscribeLocalEvent<CargoOrderConsoleComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<CargoOrderConsoleComponent, InteractUsingEvent>(OnInteractUsing);
SubscribeLocalEvent<CargoOrderConsoleComponent, BankBalanceUpdatedEvent>(OnOrderBalanceUpdated);
SubscribeLocalEvent<CargoOrderConsoleComponent, CargoConsoleRestrictProductMessage>(OnRestrictProductMessage);
SubscribeLocalEvent<CargoOrderConsoleComponent, GotEmaggedEvent>(OnEmagged);
Reset();
}
Expand Down Expand Up @@ -188,6 +190,22 @@ private void OnApproveOrderMessage(EntityUid uid, CargoOrderConsoleComponent com
return;
}

// Order is restricted
foreach (var restricted in orderDatabase.RestrictedOrders)
{
if (restricted.ProductProductId == order.ProductId)
{
if (!_accessReaderSystem.IsAllowed(player, uid, accessList: 0))
{
ConsolePopup(args.Actor, Loc.GetString("cargo-console-restricted-order"));
PlayDenySound(uid, component);
return;
}

break;
}
}

var ev = new FulfillCargoOrderEvent((station.Value, stationData), order, (uid, component));
RaiseLocalEvent(ref ev);
ev.FulfillmentEntity ??= station.Value;
Expand Down Expand Up @@ -326,6 +344,52 @@ private void OnAddOrderMessage(EntityUid uid, CargoOrderConsoleComponent compone

}

/// <summary>
/// Handles the adding of a product to the restricted product list
/// </summary>
/// <param name="uid">Entity doing the adding</param>
/// <param name="component">Cargo Console being used to set the restriction</param>
/// <param name="args">Carries the product id as given in the <see cref="CargoProductPrototype"/></param>
private void OnRestrictProductMessage(EntityUid uid, CargoOrderConsoleComponent component, CargoConsoleRestrictProductMessage args)
{
if (args.Actor is not { Valid: true } player)
return;

var stationUid = _station.GetOwningStation(uid);

// Checks for appropriate access, by default should be QM
if (!_accessReaderSystem.IsAllowed(player, uid, accessList:0))
{
ConsolePopup(args.Actor, Loc.GetString("cargo-console-order-not-allowed"));
PlayDenySound(uid, component);
UpdateOrderState(uid, stationUid);
return;
}

// Gets the product details from the id
if (!_protoMan.TryIndex<CargoProductPrototype>(args.Product, out var product))
{
Log.Error($"Tried to add invalid cargo product {args.Product} as order!");
return;
}

if (!TryGetOrderDatabase(stationUid, out var orderDatabase))
return;

// Adds to the list if already on and removes if not
if (orderDatabase.RestrictedOrders.Contains(new CargoRestrictedData(args.Product)))
{
orderDatabase.RestrictedOrders.Remove(new CargoRestrictedData(args.Product));
}
else
{
orderDatabase.RestrictedOrders.Add(new CargoRestrictedData(args.Product, product.Product.Id));
}

// Update the state to update the consoles
UpdateOrderState(uid, stationUid);
}

private void OnOrderUIOpened(EntityUid uid, CargoOrderConsoleComponent component, BoundUIOpenedEvent args)
{
var station = _station.GetOwningStation(uid);
Expand Down Expand Up @@ -356,7 +420,8 @@ private void UpdateOrderState(EntityUid consoleUid, EntityUid? station)
GetOutstandingOrderCount(orderDatabase),
orderDatabase.Capacity,
bankAccount.Balance,
orderDatabase.Orders
orderDatabase.Orders,
orderDatabase.RestrictedOrders
));
}
}
Expand Down
12 changes: 11 additions & 1 deletion Content.Shared/Access/Components/AccessReaderComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ public sealed partial class AccessReaderComponent : Component
[DataField("access")] [ViewVariables(VVAccess.ReadWrite)]
public List<HashSet<ProtoId<AccessLevelPrototype>>> AccessLists = new();

/// <summary>
/// List of a list for the purpose of allowing additional access groups, it follows the same rules as AccessLists
/// only allowing more lists.
/// </summary>
[DataField("additionalAccess")] [ViewVariables(VVAccess.ReadWrite)]
public List<List<HashSet<ProtoId<AccessLevelPrototype>>>> AdditionalAccessLists = new();

/// <summary>
/// A list of <see cref="StationRecordKey"/>s that grant access. Only a single matching key is required to gain
/// access.
Expand Down Expand Up @@ -100,17 +107,20 @@ public sealed class AccessReaderComponentState : ComponentState

public List<HashSet<ProtoId<AccessLevelPrototype>>> AccessLists;

public List<List<HashSet<ProtoId<AccessLevelPrototype>>>> AdditionalAccessLists;

public List<(NetEntity, uint)> AccessKeys;

public Queue<AccessRecord> AccessLog;

public int AccessLogLimit;

public AccessReaderComponentState(bool enabled, HashSet<ProtoId<AccessLevelPrototype>> denyTags, List<HashSet<ProtoId<AccessLevelPrototype>>> accessLists, List<(NetEntity, uint)> accessKeys, Queue<AccessRecord> accessLog, int accessLogLimit)
public AccessReaderComponentState(bool enabled, HashSet<ProtoId<AccessLevelPrototype>> denyTags, List<HashSet<ProtoId<AccessLevelPrototype>>> accessLists, List<List<HashSet<ProtoId<AccessLevelPrototype>>>> additionalAccessLists, List<(NetEntity, uint)> accessKeys, Queue<AccessRecord> accessLog, int accessLogLimit)
{
Enabled = enabled;
DenyTags = denyTags;
AccessLists = accessLists;
AdditionalAccessLists = additionalAccessLists;
AccessKeys = accessKeys;
AccessLog = accessLog;
AccessLogLimit = accessLogLimit;
Expand Down
Loading
Loading