base.Open();
var spriteSystem = EntMan.System<SpriteSystem>();
- _menu = new CargoConsoleMenu(IoCManager.Resolve<IPrototypeManager>(), spriteSystem);
+ _menu = new CargoConsoleMenu(Owner, IoCManager.Resolve<EntityManager>(), IoCManager.Resolve<IPrototypeManager>(), spriteSystem);
var localPlayer = IoCManager.Resolve<IPlayerManager>()?.LocalPlayer?.ControlledEntity;
var description = new FormattedMessage();
using System.Linq;
using Content.Client.UserInterface.Controls;
using Content.Shared.Cargo;
+using Content.Shared.Cargo.Components;
using Content.Shared.Cargo.Prototypes;
using Robust.Client.AutoGenerated;
using Robust.Client.GameObjects;
[GenerateTypedNameReferences]
public sealed partial class CargoConsoleMenu : FancyWindow
{
+ private IEntityManager _entityManager;
private IPrototypeManager _protoManager;
private SpriteSystem _spriteSystem;
+ private EntityUid _owner;
public event Action<ButtonEventArgs>? OnItemSelected;
public event Action<ButtonEventArgs>? OnOrderApproved;
private readonly List<string> _categoryStrings = new();
private string? _category;
- public CargoConsoleMenu(IPrototypeManager protoManager, SpriteSystem spriteSystem)
+ public CargoConsoleMenu(EntityUid owner, IEntityManager entMan, IPrototypeManager protoManager, SpriteSystem spriteSystem)
{
RobustXamlLoader.Load(this);
+ _entityManager = entMan;
_protoManager = protoManager;
_spriteSystem = spriteSystem;
+ _owner = owner;
Title = Loc.GetString("cargo-console-menu-title");
Categories.SelectId(id);
}
- public IEnumerable<CargoProductPrototype> ProductPrototypes => _protoManager.EnumeratePrototypes<CargoProductPrototype>();
+ public IEnumerable<CargoProductPrototype> ProductPrototypes
+ {
+ get
+ {
+ var allowedGroups = _entityManager.GetComponentOrNull<CargoOrderConsoleComponent>(_owner)?.AllowedGroups;
+
+ foreach (var cargoPrototype in _protoManager.EnumeratePrototypes<CargoProductPrototype>())
+ {
+ if (!allowedGroups?.Contains(cargoPrototype.Group) ?? false)
+ continue;
+
+ yield return cargoPrototype;
+ }
+ }
+ }
/// <summary>
/// Populates the list of products that will actually be shown, using the current filters.
Product = prototype,
ProductName = { Text = prototype.Name },
MainButton = { ToolTip = prototype.Description },
- PointCost = { Text = Loc.GetString("cargo-console-menu-points-amount", ("amount", prototype.PointCost.ToString())) },
+ PointCost = { Text = Loc.GetString("cargo-console-menu-points-amount", ("amount", prototype.Cost.ToString())) },
Icon = { Texture = _spriteSystem.Frame0(prototype.Icon) },
};
button.MainButton.OnPressed += args =>
var ent = entManager.SpawnEntity(proto.Product, testMap.MapCoords);
var price = pricing.GetPrice(ent);
- Assert.That(price, Is.AtMost(proto.PointCost), $"Found arbitrage on {proto.ID} cargo product! Cost is {proto.PointCost} but sell is {price}!");
+ Assert.That(price, Is.AtMost(proto.Cost), $"Found arbitrage on {proto.ID} cargo product! Cost is {proto.Cost} but sell is {price}!");
entManager.DeleteEntity(ent);
}
});
foreach (var bounty in bounties)
{
if (cargo.IsBountyComplete(ent, bounty))
- Assert.That(proto.PointCost, Is.GreaterThanOrEqualTo(bounty.Reward), $"Found arbitrage on {bounty.ID} cargo bounty! Product {proto.ID} costs {proto.PointCost} but fulfills bounty {bounty.ID} with reward {bounty.Reward}!");
+ Assert.That(proto.Cost, Is.GreaterThanOrEqualTo(bounty.Reward), $"Found arbitrage on {bounty.ID} cargo bounty! Product {proto.ID} costs {proto.Cost} but fulfills bounty {bounty.ID} with reward {bounty.Reward}!");
}
entManager.DeleteEntity(ent);
+++ /dev/null
-using Robust.Shared.Audio;
-
-namespace Content.Server.Cargo.Components
-{
- /// <summary>
- /// Handles sending order requests to cargo. Doesn't handle orders themselves via shuttle or telepads.
- /// </summary>
- [RegisterComponent]
- public sealed partial class CargoOrderConsoleComponent : Component
- {
- [DataField("soundError")] public SoundSpecifier ErrorSound =
- new SoundPathSpecifier("/Audio/Effects/Cargo/buzz_sigh.ogg");
-
- [DataField("soundConfirm")]
- public SoundSpecifier ConfirmSound = new SoundPathSpecifier("/Audio/Effects/Cargo/ping.ogg");
- }
-}
return;
}
+ if (!component.AllowedGroups.Contains(product.Group))
+ return;
+
var data = GetOrderData(args, product, GenerateOrderId(orderDatabase));
if (!TryAddOrder(stationUid.Value, data, orderDatabase))
private static CargoOrderData GetOrderData(CargoConsoleAddOrderMessage args, CargoProductPrototype cargoProduct, int id)
{
- return new CargoOrderData(id, cargoProduct.Product, cargoProduct.PointCost, args.Amount, args.Requester, args.Reason);
+ return new CargoOrderData(id, cargoProduct.Product, cargoProduct.Cost, args.Amount, args.Requester, args.Reason);
}
public static int GetOutstandingOrderCount(StationCargoOrderDatabaseComponent component)
using Content.Shared.Access.Systems;
using Content.Shared.Administration.Logs;
using Content.Shared.Cargo;
+using Content.Shared.Cargo.Components;
using Content.Shared.Containers.ItemSlots;
using Content.Shared.Mobs.Components;
using JetBrains.Annotations;
if (!_cargoSystem.AddAndApproveOrder(
station!.Value,
product.Product,
- product.PointCost,
+ product.Cost,
qty,
Loc.GetString(component.Sender),
Loc.GetString(component.Description),
--- /dev/null
+using Content.Shared.Cargo.Prototypes;
+using Robust.Shared.Audio;
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Cargo.Components;
+
+/// <summary>
+/// Handles sending order requests to cargo. Doesn't handle orders themselves via shuttle or telepads.
+/// </summary>
+[RegisterComponent, NetworkedComponent]
+public sealed partial class CargoOrderConsoleComponent : Component
+{
+ [DataField("soundError")] public SoundSpecifier ErrorSound =
+ new SoundPathSpecifier("/Audio/Effects/Cargo/buzz_sigh.ogg");
+
+ [DataField("soundConfirm")]
+ public SoundSpecifier ConfirmSound = new SoundPathSpecifier("/Audio/Effects/Cargo/ping.ogg");
+
+ /// <summary>
+ /// All of the <see cref="CargoProductPrototype.Group"/>s that are supported.
+ /// </summary>
+ [DataField, ViewVariables(VVAccess.ReadWrite)]
+ public List<string> AllowedGroups = new() { "market" };
+}
+
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Array;
using Robust.Shared.Utility;
namespace Content.Shared.Cargo.Prototypes
{
- [Prototype("cargoProduct")]
- public sealed partial class CargoProductPrototype : IPrototype
+ [Prototype]
+ public sealed partial class CargoProductPrototype : IPrototype, IInheritingPrototype
{
+ /// <inheritdoc />
+ [ParentDataField(typeof(AbstractPrototypeIdArraySerializer<CargoProductPrototype>))]
+ public string[]? Parents { get; }
+
+ /// <inheritdoc />
+ [NeverPushInheritance]
+ [AbstractDataField]
+ public bool Abstract { get; }
+
[DataField("name")] private string _name = string.Empty;
[DataField("description")] private string _description = string.Empty;
/// <summary>
/// Texture path used in the CargoConsole GUI.
/// </summary>
- [DataField("icon")]
+ [DataField]
public SpriteSpecifier Icon { get; private set; } = SpriteSpecifier.Invalid;
/// <summary>
- /// The prototype name of the product.
+ /// The entity prototype ID of the product.
/// </summary>
- [DataField("product", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
- public string Product { get; private set; } = string.Empty;
+ [DataField]
+ public EntProtoId Product { get; private set; } = string.Empty;
/// <summary>
/// The point cost of the product.
/// </summary>
- [DataField("cost")]
- public int PointCost { get; private set; }
+ [DataField]
+ public int Cost { get; private set; }
/// <summary>
/// The prototype category of the product. (e.g. Engineering, Medical)
/// </summary>
- [DataField("category")]
+ [DataField]
public string Category { get; private set; } = string.Empty;
/// <summary>
/// The prototype group of the product. (e.g. Contraband)
/// </summary>
- [DataField("group")]
- public string Group { get; private set; } = string.Empty;
+ [DataField]
+ public string Group { get; private set; } = "market";
}
}