From 88df3d8b1098b59433ad187db254a8b465febb56 Mon Sep 17 00:00:00 2001 From: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com> Date: Thu, 11 Nov 2021 02:15:23 +1300 Subject: [PATCH] Cargo: pizza & bureaucracy (#5123) * add paper label component * git mv * rename namespace * add cargo printouts * more crates * directly attach paper * comment typo --- Content.Client/Entry/IgnoredComponents.cs | 1 + .../UI/HandLabelerBoundUserInterface.cs | 4 +- .../UI/HandLabelerWindow.xaml | 0 .../UI/HandLabelerWindow.xaml.cs | 2 +- .../Morgue/Visualizers/BodyBagVisualizer.cs | 4 +- Content.Server/Access/Systems/IdCardSystem.cs | 54 +++++++++++ Content.Server/Cargo/CargoConsoleSystem.cs | 23 ++++- Content.Server/Cargo/CargoOrderDatabase.cs | 6 +- .../Cargo/Components/CargoConsoleComponent.cs | 14 +-- .../Cargo/Components/CargoTelepadComponent.cs | 59 ++++++++++- Content.Server/HandLabeler/LabelSystem.cs | 36 ------- .../Label}/Components/HandLabelerComponent.cs | 2 +- .../Label}/Components/LabelComponent.cs | 2 +- .../Label/Components/PaperLabelComponent.cs | 17 ++++ .../Label}/HandLabelerSystem.cs | 6 +- Content.Server/Labels/Label/LabelSystem.cs | 97 +++++++++++++++++++ .../BodyBagEntityStorageComponent.cs | 69 +------------ Content.Server/Morgue/MorgueSystem.cs | 17 ---- Content.Server/Paper/PaperComponent.cs | 16 +++ Content.Shared/Cargo/CargoOrderData.cs | 4 +- .../LabelEvents.cs} | 8 +- Content.Shared/Morgue/SharedMorgue.cs | 6 -- .../components/cargo-console-component.ftl | 7 ++ .../en-US/label/paper-label-component.ftl | 3 + .../body-bag-entity-storage-component.ftl | 6 -- .../Prototypes/Catalog/Cargo/cargo_food.yml | 11 +++ .../Catalog/Cargo/cargo_medical.yml | 11 +++ .../Catalog/Cargo/cargo_service.yml | 12 +++ .../Prototypes/Catalog/Fills/Crates/food.yml | 12 ++- .../Catalog/Fills/Crates/service.yml | 17 +++- .../Objects/Specific/Medical/morgue.yml | 7 ++ .../Machines/Computers/computers.yml | 6 ++ .../Structures/Storage/Crates/base.yml | 7 ++ 33 files changed, 384 insertions(+), 162 deletions(-) rename Content.Client/{HandLabeler => Labels}/UI/HandLabelerBoundUserInterface.cs (95%) rename Content.Client/{HandLabeler => Labels}/UI/HandLabelerWindow.xaml (100%) rename Content.Client/{HandLabeler => Labels}/UI/HandLabelerWindow.xaml.cs (94%) delete mode 100644 Content.Server/HandLabeler/LabelSystem.cs rename Content.Server/{HandLabeler => Labels/Label}/Components/HandLabelerComponent.cs (93%) rename Content.Server/{HandLabeler => Labels/Label}/Components/LabelComponent.cs (90%) create mode 100644 Content.Server/Labels/Label/Components/PaperLabelComponent.cs rename Content.Server/{HandLabeler => Labels/Label}/HandLabelerSystem.cs (97%) create mode 100644 Content.Server/Labels/Label/LabelSystem.cs rename Content.Shared/{HandLabeler/SharedHandLabelerComponent.cs => Labels/LabelEvents.cs} (89%) create mode 100644 Resources/Locale/en-US/label/paper-label-component.ftl delete mode 100644 Resources/Locale/en-US/morgue/components/body-bag-entity-storage-component.ftl create mode 100644 Resources/Prototypes/Catalog/Cargo/cargo_food.yml create mode 100644 Resources/Prototypes/Catalog/Cargo/cargo_medical.yml diff --git a/Content.Client/Entry/IgnoredComponents.cs b/Content.Client/Entry/IgnoredComponents.cs index f23e624d57..8375ceadeb 100644 --- a/Content.Client/Entry/IgnoredComponents.cs +++ b/Content.Client/Entry/IgnoredComponents.cs @@ -25,6 +25,7 @@ namespace Content.Client.Entry "MeleeWeapon", "MeleeChemicalInjector", "Dice", + "PaperLabel", "Construction", "PoweredLight", "Smes", diff --git a/Content.Client/HandLabeler/UI/HandLabelerBoundUserInterface.cs b/Content.Client/Labels/UI/HandLabelerBoundUserInterface.cs similarity index 95% rename from Content.Client/HandLabeler/UI/HandLabelerBoundUserInterface.cs rename to Content.Client/Labels/UI/HandLabelerBoundUserInterface.cs index 82625e8ede..5728b874e8 100644 --- a/Content.Client/HandLabeler/UI/HandLabelerBoundUserInterface.cs +++ b/Content.Client/Labels/UI/HandLabelerBoundUserInterface.cs @@ -1,8 +1,8 @@ -using Content.Shared.HandLabeler; +using Content.Shared.Labels; using Robust.Client.GameObjects; using Robust.Shared.GameObjects; -namespace Content.Client.HandLabeler.UI +namespace Content.Client.Labels.UI { /// /// Initializes a and updates it when new server messages are received. diff --git a/Content.Client/HandLabeler/UI/HandLabelerWindow.xaml b/Content.Client/Labels/UI/HandLabelerWindow.xaml similarity index 100% rename from Content.Client/HandLabeler/UI/HandLabelerWindow.xaml rename to Content.Client/Labels/UI/HandLabelerWindow.xaml diff --git a/Content.Client/HandLabeler/UI/HandLabelerWindow.xaml.cs b/Content.Client/Labels/UI/HandLabelerWindow.xaml.cs similarity index 94% rename from Content.Client/HandLabeler/UI/HandLabelerWindow.xaml.cs rename to Content.Client/Labels/UI/HandLabelerWindow.xaml.cs index bfc27dda20..1ab434f3a8 100644 --- a/Content.Client/HandLabeler/UI/HandLabelerWindow.xaml.cs +++ b/Content.Client/Labels/UI/HandLabelerWindow.xaml.cs @@ -4,7 +4,7 @@ using Robust.Client.AutoGenerated; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.XAML; -namespace Content.Client.HandLabeler.UI +namespace Content.Client.Labels.UI { [GenerateTypedNameReferences] public partial class HandLabelerWindow : SS14Window diff --git a/Content.Client/Morgue/Visualizers/BodyBagVisualizer.cs b/Content.Client/Morgue/Visualizers/BodyBagVisualizer.cs index 0a632fb282..e8063689f3 100644 --- a/Content.Client/Morgue/Visualizers/BodyBagVisualizer.cs +++ b/Content.Client/Morgue/Visualizers/BodyBagVisualizer.cs @@ -1,4 +1,4 @@ -using Content.Shared.Morgue; +using Content.Shared.Labels; using JetBrains.Annotations; using Robust.Client.GameObjects; @@ -16,7 +16,7 @@ namespace Content.Client.Morgue.Visualizers return; } - if (component.TryGetData(BodyBagVisuals.Label, out bool labelVal)) + if (component.TryGetData(PaperLabelVisuals.HasLabel, out bool labelVal)) { sprite.LayerSetVisible(BodyBagVisualLayers.Label, labelVal); } diff --git a/Content.Server/Access/Systems/IdCardSystem.cs b/Content.Server/Access/Systems/IdCardSystem.cs index 034ede7a88..e15b7aafe1 100644 --- a/Content.Server/Access/Systems/IdCardSystem.cs +++ b/Content.Server/Access/Systems/IdCardSystem.cs @@ -1,7 +1,13 @@ using Content.Server.Access.Components; +using Content.Server.Inventory.Components; +using Content.Server.Items; +using Content.Server.PDA; using Content.Shared.Access; +using Content.Shared.Hands.Components; +using Content.Shared.Inventory; using Robust.Shared.GameObjects; using Robust.Shared.Localization; +using System.Diagnostics.CodeAnalysis; namespace Content.Server.Access.Systems { @@ -74,5 +80,53 @@ namespace Content.Server.Access.Systems ("fullName", id.FullName), ("jobSuffix", jobSuffix)); } + + /// + /// Attempt to find an ID card on an entity. This will look in the entity itself, in the entity's hands, and + /// in the entity's inventory. + /// + public bool TryFindIdCard(EntityUid uid, [NotNullWhen(true)] out IdCardComponent? idCard) + { + // check held item? + if (EntityManager.TryGetComponent(uid, out SharedHandsComponent? hands) && + hands.TryGetActiveHeldEntity(out var heldItem) && + TryGetIdCard(heldItem.Uid, out idCard)) + { + return true; + } + + // check entity itself + if (TryGetIdCard(uid, out idCard)) + return true; + + // check inventory slot? + if (EntityManager.TryGetComponent(uid, out InventoryComponent? inventoryComponent) && + inventoryComponent.HasSlot(EquipmentSlotDefines.Slots.IDCARD) && + inventoryComponent.TryGetSlotItem(EquipmentSlotDefines.Slots.IDCARD, out ItemComponent? item) && + TryGetIdCard(item.Owner.Uid, out idCard)) + { + return true; + } + + return false; + } + + /// + /// Attempt to get an id card component from an entity, either by getting it directly from the entity, or by + /// getting the contained id from a . + /// + private bool TryGetIdCard(EntityUid uid, [NotNullWhen(true)] out IdCardComponent? idCard) + { + if (EntityManager.TryGetComponent(uid, out idCard)) + return true; + + if (EntityManager.TryGetComponent(uid, out PDAComponent? pda) && pda.ContainedID != null) + { + idCard = pda.ContainedID; + return true; + } + + return false; + } } } diff --git a/Content.Server/Cargo/CargoConsoleSystem.cs b/Content.Server/Cargo/CargoConsoleSystem.cs index d573fe560a..8e3d70104b 100644 --- a/Content.Server/Cargo/CargoConsoleSystem.cs +++ b/Content.Server/Cargo/CargoConsoleSystem.cs @@ -1,9 +1,12 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using Content.Server.Access.Components; +using Content.Server.Access.Systems; using Content.Server.Cargo.Components; using Content.Shared.Cargo; using Content.Shared.GameTicking; using Robust.Shared.GameObjects; +using Robust.Shared.IoC; namespace Content.Server.Cargo { @@ -43,6 +46,9 @@ namespace Content.Server.Cargo public CargoOrderDatabase StationOrderDatabase => GetOrderDatabase(0); + [Dependency] private readonly IdCardSystem _idCardSystem = default!; + [Dependency] private readonly AccessReaderSystem _accessReaderSystem = default!; + public override void Initialize() { SubscribeLocalEvent(Reset); @@ -171,12 +177,25 @@ namespace Content.Server.Cargo return true; } - public bool ApproveOrder(int id, int orderNumber) + public bool ApproveOrder(EntityUid uid, EntityUid approver, int id, int orderNumber, AccessReader? reader = null) { + // does the approver have permission to approve orders? + if (Resolve(uid, ref reader) && !_accessReaderSystem.IsAllowed(reader, approver)) + return false; + + // get the approver's name + _idCardSystem.TryFindIdCard(approver, out var idCard); + var approverName = idCard?.FullName ?? string.Empty; + if (!TryGetOrderDatabase(id, out var database)) return false; - if (!database.ApproveOrder(orderNumber)) + + if (!database.TryGetOrder(orderNumber, out var order)) return false; + + if (!database.ApproveOrder(approverName, orderNumber)) + return false; + SyncComponentsWithId(id); return true; } diff --git a/Content.Server/Cargo/CargoOrderDatabase.cs b/Content.Server/Cargo/CargoOrderDatabase.cs index 66043491be..38e2cad3ac 100644 --- a/Content.Server/Cargo/CargoOrderDatabase.cs +++ b/Content.Server/Cargo/CargoOrderDatabase.cs @@ -1,7 +1,9 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; +using Content.Server.Access.Systems; using Content.Shared.Cargo; +using Robust.Shared.GameObjects; using Robust.Shared.Localization; namespace Content.Server.Cargo @@ -84,7 +86,7 @@ namespace Content.Server.Cargo /// Approves an order in the database. /// /// The order to be approved. - public bool ApproveOrder(int orderNumber) + public bool ApproveOrder(string approver, int orderNumber) { if (CurrentOrderSize == MaxOrderSize || !_orders.TryGetValue(orderNumber, out var order) || @@ -104,6 +106,8 @@ namespace Content.Server.Cargo } order.Approved = true; + order.Approver = approver; + CurrentOrderSize += order.Amount; return true; } diff --git a/Content.Server/Cargo/Components/CargoConsoleComponent.cs b/Content.Server/Cargo/Components/CargoConsoleComponent.cs index 35c51caa80..5725c4f28a 100644 --- a/Content.Server/Cargo/Components/CargoConsoleComponent.cs +++ b/Content.Server/Cargo/Components/CargoConsoleComponent.cs @@ -135,6 +135,10 @@ namespace Content.Server.Cargo.Components break; } + var uid = msg.Session.AttachedEntityUid; + if (uid == null) + break; + PrototypeManager.TryIndex(order.ProductId, out CargoProductPrototype? product); if (product == null!) break; @@ -143,13 +147,14 @@ namespace Content.Server.Cargo.Components (capacity.CurrentCapacity == capacity.MaxCapacity || capacity.CurrentCapacity + order.Amount > capacity.MaxCapacity || !_cargoConsoleSystem.CheckBalance(_bankAccount.Id, (-product.PointCost) * order.Amount) - || !_cargoConsoleSystem.ApproveOrder(orders.Database.Id, msg.OrderNumber) + || !_cargoConsoleSystem.ApproveOrder(Owner.Uid, uid.Value, orders.Database.Id, msg.OrderNumber) || !_cargoConsoleSystem.ChangeBalance(_bankAccount.Id, (-product.PointCost) * order.Amount)) ) { SoundSystem.Play(Filter.Local(), _errorSound.GetSound(), Owner, AudioParams.Default); break; } + UpdateUIState(); break; } @@ -189,12 +194,7 @@ namespace Content.Server.Cargo.Components orders.Database.ClearOrderCapacity(); foreach (var order in approvedOrders) { - if (!PrototypeManager.TryIndex(order.ProductId, out CargoProductPrototype? product)) - continue; - for (var i = 0; i < order.Amount; i++) - { - telepadComponent.QueueTeleport(product); - } + telepadComponent.QueueTeleport(order); } } } diff --git a/Content.Server/Cargo/Components/CargoTelepadComponent.cs b/Content.Server/Cargo/Components/CargoTelepadComponent.cs index 56d0d28300..3ae292c72d 100644 --- a/Content.Server/Cargo/Components/CargoTelepadComponent.cs +++ b/Content.Server/Cargo/Components/CargoTelepadComponent.cs @@ -1,13 +1,20 @@ using System; using System.Collections.Generic; +using Content.Server.Labels.Components; +using Content.Server.Paper; using Content.Server.Power.Components; using Content.Shared.Cargo; +using Content.Shared.Containers.ItemSlots; using Content.Shared.Sound; using Robust.Server.GameObjects; using Robust.Shared.Audio; using Robust.Shared.GameObjects; +using Robust.Shared.IoC; +using Robust.Shared.Localization; using Robust.Shared.Player; +using Robust.Shared.Prototypes; using Robust.Shared.Serialization.Manager.Attributes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; namespace Content.Server.Cargo.Components { @@ -17,14 +24,23 @@ namespace Content.Server.Cargo.Components [RegisterComponent] public class CargoTelepadComponent : Component { + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly IEntityManager _entityManager = default!; + public override string Name => "CargoTelepad"; private const float TeleportDuration = 0.5f; private const float TeleportDelay = 15f; - private List _teleportQueue = new List(); + private List _teleportQueue = new(); private CargoTelepadState _currentState = CargoTelepadState.Unpowered; [DataField("teleportSound")] private SoundSpecifier _teleportSound = new SoundPathSpecifier("/Audio/Machines/phasein.ogg"); + /// + /// The paper-type prototype to spawn with the order information. + /// + [DataField("printerOutput", customTypeSerializer: typeof(PrototypeIdSerializer))] + public string PrinterOutput = "Paper"; + [Obsolete("Component Messages are deprecated, use Entity Events instead.")] public override void HandleMessage(ComponentMessage message, IComponent? component) { @@ -39,9 +55,12 @@ namespace Content.Server.Cargo.Components } } - public void QueueTeleport(CargoProductPrototype product) + public void QueueTeleport(CargoOrderData order) { - _teleportQueue.Add(product); + for (var i = 0; i < order.Amount; i++) + { + _teleportQueue.Add(order); + } TeleportLoop(); } @@ -79,7 +98,7 @@ namespace Content.Server.Cargo.Components if (!Deleted && !Owner.Deleted && _currentState == CargoTelepadState.Teleporting && _teleportQueue.Count > 0) { SoundSystem.Play(Filter.Pvs(Owner), _teleportSound.GetSound(), Owner, AudioParams.Default.WithVolume(-8f)); - Owner.EntityManager.SpawnEntity(_teleportQueue[0].Product, Owner.Transform.Coordinates); + SpawnProduct(_teleportQueue[0]); _teleportQueue.RemoveAt(0); if (Owner.TryGetComponent(out var spriteComponent) && spriteComponent.LayerCount > 0) spriteComponent.LayerSetState(0, "idle"); @@ -92,6 +111,38 @@ namespace Content.Server.Cargo.Components } } + /// + /// Spawn the product and a piece of paper. Attempt to attach the paper to the product. + /// + private void SpawnProduct(CargoOrderData data) + { + // spawn the order + if (!_prototypeManager.TryIndex(data.ProductId, out CargoProductPrototype? prototype)) + return; + var product = Owner.EntityManager.SpawnEntity(prototype.Product, Owner.Transform.Coordinates); + + // spawn a piece of paper. + var printed = Owner.EntityManager.SpawnEntity(PrinterOutput, Owner.Transform.Coordinates); + if (!_entityManager.TryGetComponent(printed.Uid, out PaperComponent paper)) + return; + + // fill in the order data + printed.Name = Loc.GetString("cargo-console-paper-print-name", ("orderNumber", data.OrderNumber)); + paper.SetContent(Loc.GetString( + "cargo-console-paper-print-text", + ("orderNumber", data.OrderNumber), + ("requester", data.Requester), + ("reason", data.Reason), + ("approver", data.Approver))); + + // attempt to attach the label + if (_entityManager.TryGetComponent(product.Uid, out PaperLabelComponent label) && + _entityManager.TryGetComponent(product.Uid, out SharedItemSlotsComponent slots)) + { + EntitySystem.Get().TryInsertContent(slots, printed, label.LabelSlot); + } + } + private enum CargoTelepadState { Unpowered, Idle, Charging, Teleporting }; } } diff --git a/Content.Server/HandLabeler/LabelSystem.cs b/Content.Server/HandLabeler/LabelSystem.cs deleted file mode 100644 index 048a9a8b46..0000000000 --- a/Content.Server/HandLabeler/LabelSystem.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Content.Server.HandLabeler.Components; -using Content.Shared.Examine; -using JetBrains.Annotations; -using Robust.Shared.GameObjects; -using Robust.Shared.Localization; -using Robust.Shared.Utility; - -namespace Content.Server.HandLabeler -{ - /// - /// A system that lets players see the contents of a label on an object. - /// - [UsedImplicitly] - public class LabelSystem : EntitySystem - { - public override void Initialize() - { - base.Initialize(); - - SubscribeLocalEvent(OnExamine); - } - - private void OnExamine(EntityUid uid, LabelComponent? label, ExaminedEvent args) - { - if (!Resolve(uid, ref label)) - return; - - if (label.CurrentLabel == null) - return; - - var message = new FormattedMessage(); - message.AddText(Loc.GetString("hand-labeler-has-label", ("label", label.CurrentLabel))); - args.PushMessage(message); - } - } -} diff --git a/Content.Server/HandLabeler/Components/HandLabelerComponent.cs b/Content.Server/Labels/Label/Components/HandLabelerComponent.cs similarity index 93% rename from Content.Server/HandLabeler/Components/HandLabelerComponent.cs rename to Content.Server/Labels/Label/Components/HandLabelerComponent.cs index c7334eb4f4..396a538903 100644 --- a/Content.Server/HandLabeler/Components/HandLabelerComponent.cs +++ b/Content.Server/Labels/Label/Components/HandLabelerComponent.cs @@ -5,7 +5,7 @@ using Robust.Shared.GameObjects; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.ViewVariables; -namespace Content.Server.HandLabeler.Components +namespace Content.Server.Labels.Components { [RegisterComponent] public class HandLabelerComponent : Component diff --git a/Content.Server/HandLabeler/Components/LabelComponent.cs b/Content.Server/Labels/Label/Components/LabelComponent.cs similarity index 90% rename from Content.Server/HandLabeler/Components/LabelComponent.cs rename to Content.Server/Labels/Label/Components/LabelComponent.cs index e98ff32b23..5ae78370d0 100644 --- a/Content.Server/HandLabeler/Components/LabelComponent.cs +++ b/Content.Server/Labels/Label/Components/LabelComponent.cs @@ -2,7 +2,7 @@ using Robust.Shared.GameObjects; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.ViewVariables; -namespace Content.Server.HandLabeler.Components +namespace Content.Server.Labels.Components { [RegisterComponent] public class LabelComponent : Component diff --git a/Content.Server/Labels/Label/Components/PaperLabelComponent.cs b/Content.Server/Labels/Label/Components/PaperLabelComponent.cs new file mode 100644 index 0000000000..ed74b2547b --- /dev/null +++ b/Content.Server/Labels/Label/Components/PaperLabelComponent.cs @@ -0,0 +1,17 @@ +using Robust.Shared.GameObjects; +using Robust.Shared.Serialization.Manager.Attributes; + +namespace Content.Server.Labels.Components +{ + /// + /// This component allows you to attach and remove a piece of paper to an entity. + /// + [RegisterComponent] + public class PaperLabelComponent : Component + { + public override string Name => "PaperLabel"; + + [DataField("labelSlot")] + public string LabelSlot = "labelSlot"; + } +} diff --git a/Content.Server/HandLabeler/HandLabelerSystem.cs b/Content.Server/Labels/Label/HandLabelerSystem.cs similarity index 97% rename from Content.Server/HandLabeler/HandLabelerSystem.cs rename to Content.Server/Labels/Label/HandLabelerSystem.cs index aad30f03b2..fcc1a08c0d 100644 --- a/Content.Server/HandLabeler/HandLabelerSystem.cs +++ b/Content.Server/Labels/Label/HandLabelerSystem.cs @@ -1,7 +1,7 @@ -using Content.Server.HandLabeler.Components; +using Content.Server.Labels.Components; using Content.Server.UserInterface; using Content.Shared.ActionBlocker; -using Content.Shared.HandLabeler; +using Content.Shared.Labels; using Content.Shared.Interaction; using Robust.Server.GameObjects; using Robust.Shared.GameObjects; @@ -12,7 +12,7 @@ using Robust.Shared.Localization; using Content.Shared.Popups; using System; -namespace Content.Server.HandLabeler +namespace Content.Server.Labels { /// /// A hand labeler system that lets an object apply labels to objects with the . diff --git a/Content.Server/Labels/Label/LabelSystem.cs b/Content.Server/Labels/Label/LabelSystem.cs new file mode 100644 index 0000000000..4fd4485cde --- /dev/null +++ b/Content.Server/Labels/Label/LabelSystem.cs @@ -0,0 +1,97 @@ +using Content.Server.Labels.Components; +using Content.Server.Paper; +using Content.Shared.Containers.ItemSlots; +using Content.Shared.Examine; +using Content.Shared.Labels; +using JetBrains.Annotations; +using Robust.Shared.GameObjects; +using Robust.Shared.IoC; +using Robust.Shared.Localization; +using Robust.Shared.Utility; +using System; + +namespace Content.Server.Labels +{ + /// + /// A system that lets players see the contents of a label on an object. + /// + [UsedImplicitly] + public class LabelSystem : EntitySystem + { + [Dependency] private readonly SharedItemSlotsSystem _itemSlotsSystem = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnExamine); + SubscribeLocalEvent(InitializePaperLabel); + SubscribeLocalEvent(OnItemSlotChanged); + SubscribeLocalEvent(OnExamined); + } + + private void InitializePaperLabel(EntityUid uid, PaperLabelComponent component, ComponentInit args) + { + if (!EntityManager.TryGetComponent(uid, out SharedAppearanceComponent appearance)) + return; + + appearance.SetData(PaperLabelVisuals.HasLabel, false); + } + + private void OnExamine(EntityUid uid, LabelComponent? label, ExaminedEvent args) + { + if (!Resolve(uid, ref label)) + return; + + if (label.CurrentLabel == null) + return; + + var message = new FormattedMessage(); + message.AddText(Loc.GetString("hand-labeler-has-label", ("label", label.CurrentLabel))); + args.PushMessage(message); + } + + private void OnExamined(EntityUid uid, PaperLabelComponent comp, ExaminedEvent args) + { + if (!EntityManager.TryGetComponent(uid, out SharedItemSlotsComponent slots)) + return; + + var label = _itemSlotsSystem.PeekItemInSlot(slots, comp.LabelSlot); + + if (label == null) + return; + + if (!args.IsInDetailsRange) + { + args.PushMarkup(Loc.GetString("comp-paper-label-has-label-cant-read")); + return; + } + + if (!EntityManager.TryGetComponent(label.Uid, out PaperComponent paper)) + // should never happen + return; + + if (string.IsNullOrWhiteSpace(paper.Content)) + { + args.PushMarkup(Loc.GetString("comp-paper-label-has-label-blank")); + return; + } + + args.PushMarkup(Loc.GetString("comp-paper-label-has-label")); + var text = paper.Content; + args.PushMarkup(text.TrimEnd()); + } + + + private void OnItemSlotChanged(EntityUid uid, PaperLabelComponent component, ItemSlotChangedEvent args) + { + if (args.SlotName != component.LabelSlot) + return; + + if (!EntityManager.TryGetComponent(uid, out SharedAppearanceComponent appearance)) + return; + + appearance.SetData(PaperLabelVisuals.HasLabel, args.ContainedItem != null); + } + } +} diff --git a/Content.Server/Morgue/Components/BodyBagEntityStorageComponent.cs b/Content.Server/Morgue/Components/BodyBagEntityStorageComponent.cs index 3f355d5eed..0489e4a2a9 100644 --- a/Content.Server/Morgue/Components/BodyBagEntityStorageComponent.cs +++ b/Content.Server/Morgue/Components/BodyBagEntityStorageComponent.cs @@ -22,81 +22,14 @@ namespace Content.Server.Morgue.Components [ComponentReference(typeof(EntityStorageComponent))] [ComponentReference(typeof(IActivate))] [ComponentReference(typeof(IStorageComponent))] -#pragma warning disable 618 - public class BodyBagEntityStorageComponent : EntityStorageComponent, IExamine, IInteractUsing -#pragma warning restore 618 + public class BodyBagEntityStorageComponent : EntityStorageComponent { public override string Name => "BodyBagEntityStorage"; - [ViewVariables] - [ComponentDependency] private readonly AppearanceComponent? _appearance = null; - - [ViewVariables] public ContainerSlot? LabelContainer { get; private set; } - - protected override void Initialize() - { - base.Initialize(); - _appearance?.SetData(BodyBagVisuals.Label, false); - LabelContainer = Owner.EnsureContainer("body_bag_label", out _); - } - protected override bool AddToContents(IEntity entity) { if (entity.HasComponent() && !EntitySystem.Get().IsDown(entity.Uid)) return false; return base.AddToContents(entity); } - - void IExamine.Examine(FormattedMessage message, bool inDetailsRange) - { - if (inDetailsRange) - { - if (LabelContainer?.ContainedEntity != null && LabelContainer.ContainedEntity.TryGetComponent(out var paper)) - { - message.AddText(Loc.GetString("body-bag-entity-storage-component-on-examine-details", ("paper", paper.Content))); - } - } - } - - async Task IInteractUsing.InteractUsing(InteractUsingEventArgs eventArgs) - { - if (LabelContainer == null) return false; - - if (LabelContainer.ContainedEntity != null) - { - Owner.PopupMessage(eventArgs.User, Loc.GetString("body-bag-entity-storage-component-interact-using-already-attached")); - return false; - } - - var handsComponent = eventArgs.User.GetComponent(); - if (!handsComponent.Drop(eventArgs.Using, LabelContainer)) - { - return false; - } - - _appearance?.SetData(BodyBagVisuals.Label, true); - - Owner.PopupMessage(eventArgs.User, Loc.GetString("body-bag-entity-storage-component-interact-using-success",("entity", eventArgs.Using))); - return true; - } - - public void RemoveLabel(IEntity user) - { - if (LabelContainer == null) return; - - var ent = LabelContainer.ContainedEntity; - if(ent is null) - return; - - if (user.TryGetComponent(out HandsComponent? hands)) - { - hands.PutInHandOrDrop(ent.GetComponent()); - _appearance?.SetData(BodyBagVisuals.Label, false); - } - else if (LabelContainer.Remove(ent)) - { - ent.Transform.Coordinates = Owner.Transform.Coordinates; - _appearance?.SetData(BodyBagVisuals.Label, false); - } - } } } diff --git a/Content.Server/Morgue/MorgueSystem.cs b/Content.Server/Morgue/MorgueSystem.cs index 8fe10c8579..26e44b7629 100644 --- a/Content.Server/Morgue/MorgueSystem.cs +++ b/Content.Server/Morgue/MorgueSystem.cs @@ -17,7 +17,6 @@ namespace Content.Server.Morgue base.Initialize(); SubscribeLocalEvent(AddCremateVerb); - SubscribeLocalEvent(AddRemoveLabelVerb); } private void AddCremateVerb(EntityUid uid, CrematoriumEntityStorageComponent component, GetAlternativeVerbsEvent args) @@ -32,22 +31,6 @@ namespace Content.Server.Morgue args.Verbs.Add(verb); } - /// - /// This adds the "remove label" verb to the list of verbs. Yes, this is a stupid function name, but it's - /// consistent with other get-verb event handlers. - /// - private void AddRemoveLabelVerb(EntityUid uid, BodyBagEntityStorageComponent component, GetAlternativeVerbsEvent args) - { - if (args.Hands == null || !args.CanAccess || !args.CanInteract || component.LabelContainer?.ContainedEntity == null) - return; - - Verb verb = new(); - verb.Text = Loc.GetString("remove-label-verb-get-data-text"); - // TODO VERB ICON Add cancel/X icon? or maybe just use the pick-up or eject icon? - verb.Act = () => component.RemoveLabel(args.User); - args.Verbs.Add(verb); - } - public override void Update(float frameTime) { _accumulatedFrameTime += frameTime; diff --git a/Content.Server/Paper/PaperComponent.cs b/Content.Server/Paper/PaperComponent.cs index 5c7a3a72b8..7c37957dde 100644 --- a/Content.Server/Paper/PaperComponent.cs +++ b/Content.Server/Paper/PaperComponent.cs @@ -36,6 +36,22 @@ namespace Content.Server.Paper _mode = PaperAction.Read; UpdateUserInterface(); } + + public void SetContent(string content) + { + Content = content + '\n'; + UpdateUserInterface(); + + if (!Owner.TryGetComponent(out AppearanceComponent? appearance)) + return; + + var status = string.IsNullOrWhiteSpace(content) + ? PaperStatus.Blank + : PaperStatus.Written; + + appearance.SetData(PaperVisuals.Status, status); + } + private void UpdateUserInterface() { UserInterface?.SetState(new PaperBoundUserInterfaceState(Content, _mode)); diff --git a/Content.Shared/Cargo/CargoOrderData.cs b/Content.Shared/Cargo/CargoOrderData.cs index 770cc18856..2f9e747951 100644 --- a/Content.Shared/Cargo/CargoOrderData.cs +++ b/Content.Shared/Cargo/CargoOrderData.cs @@ -1,4 +1,4 @@ -using System; +using System; using Robust.Shared.Serialization; namespace Content.Shared.Cargo @@ -15,6 +15,7 @@ namespace Content.Shared.Cargo public int Amount; public int PayingAccountId; public bool Approved; + public string Approver = string.Empty; public CargoOrderData(int orderNumber, string requester, string reason, string productId, int amount, int payingAccountId) { @@ -24,7 +25,6 @@ namespace Content.Shared.Cargo ProductId = productId; Amount = amount; PayingAccountId = payingAccountId; - Approved = false; } } } diff --git a/Content.Shared/HandLabeler/SharedHandLabelerComponent.cs b/Content.Shared/Labels/LabelEvents.cs similarity index 89% rename from Content.Shared/HandLabeler/SharedHandLabelerComponent.cs rename to Content.Shared/Labels/LabelEvents.cs index 26eb165b5d..b79532189f 100644 --- a/Content.Shared/HandLabeler/SharedHandLabelerComponent.cs +++ b/Content.Shared/Labels/LabelEvents.cs @@ -2,7 +2,7 @@ using System; using Robust.Shared.GameObjects; using Robust.Shared.Serialization; -namespace Content.Shared.HandLabeler +namespace Content.Shared.Labels { /// /// Key representing which is currently open. @@ -14,6 +14,12 @@ namespace Content.Shared.HandLabeler Key, } + [Serializable, NetSerializable] + public enum PaperLabelVisuals + { + HasLabel, + } + /// /// Represents a state that can be sent to the client /// diff --git a/Content.Shared/Morgue/SharedMorgue.cs b/Content.Shared/Morgue/SharedMorgue.cs index cb56adbe07..091036cfbc 100644 --- a/Content.Shared/Morgue/SharedMorgue.cs +++ b/Content.Shared/Morgue/SharedMorgue.cs @@ -17,10 +17,4 @@ namespace Content.Shared.Morgue { Burning, } - - [Serializable, NetSerializable] - public enum BodyBagVisuals - { - Label, - } } diff --git a/Resources/Locale/en-US/cargo/components/cargo-console-component.ftl b/Resources/Locale/en-US/cargo/components/cargo-console-component.ftl index b96b0bc845..32bce89169 100644 --- a/Resources/Locale/en-US/cargo/components/cargo-console-component.ftl +++ b/Resources/Locale/en-US/cargo/components/cargo-console-component.ftl @@ -18,3 +18,10 @@ cargo-console-menu-populate-categories-all-text = All cargo-console-menu-populate-orders-cargo-order-row-product-name-text = {$productName} (x{$orderAmount}) by {$orderRequester} cargo-console-menu-cargo-order-row-approve-button = Approve cargo-console-menu-cargo-order-row-cancel-button = Cancel + +cargo-console-paper-print-name = Order #{$orderNumber} +cargo-console-paper-print-text = + Order #{$orderNumber} + Requested by: {$requester} + Reason: {$reason} + Approved by: {$approver} diff --git a/Resources/Locale/en-US/label/paper-label-component.ftl b/Resources/Locale/en-US/label/paper-label-component.ftl new file mode 100644 index 0000000000..a62fc0244d --- /dev/null +++ b/Resources/Locale/en-US/label/paper-label-component.ftl @@ -0,0 +1,3 @@ +comp-paper-label-has-label = There is a label attached, it reads: +comp-paper-label-has-label-blank = There is a label attached, but it's blank. +comp-paper-label-has-label-cant-read = There is a label attached, but you can't read it from this distance. diff --git a/Resources/Locale/en-US/morgue/components/body-bag-entity-storage-component.ftl b/Resources/Locale/en-US/morgue/components/body-bag-entity-storage-component.ftl deleted file mode 100644 index 7d4d4fa753..0000000000 --- a/Resources/Locale/en-US/morgue/components/body-bag-entity-storage-component.ftl +++ /dev/null @@ -1,6 +0,0 @@ -body-bag-entity-storage-component-on-examine-details = The label reads: {$paper} -body-bag-entity-storage-component-interact-using-already-attached = There's already a label attached. -body-bag-entity-storage-component-interact-using-success = You attach {$entity} to the body bag. - -# RemoveLabelVerb -remove-label-verb-get-data-text = Remove label \ No newline at end of file diff --git a/Resources/Prototypes/Catalog/Cargo/cargo_food.yml b/Resources/Prototypes/Catalog/Cargo/cargo_food.yml new file mode 100644 index 0000000000..ee1376b4a3 --- /dev/null +++ b/Resources/Prototypes/Catalog/Cargo/cargo_food.yml @@ -0,0 +1,11 @@ +- type: cargoProduct + name: "emergency pizza crate" + id: FoodPizza + description: Help do your part to end station hunger by distributing pizza to underfunded departments! + icon: + sprite: Objects/Consumable/Food/Baked/pizza.rsi + state: margherita + product: CrateFoodPizza + cost: 1000 + category: Food + group: market diff --git a/Resources/Prototypes/Catalog/Cargo/cargo_medical.yml b/Resources/Prototypes/Catalog/Cargo/cargo_medical.yml new file mode 100644 index 0000000000..a191c14025 --- /dev/null +++ b/Resources/Prototypes/Catalog/Cargo/cargo_medical.yml @@ -0,0 +1,11 @@ +- type: cargoProduct + name: "Medical Supplies" + id: MedicalSupplies + description: Basic medical supplies. + icon: + sprite: Objects/Specific/Medical/firstaidkits.rsi + state: firstaid + product: CrateMedicalSupplies + cost: 1000 + category: Mdeical + group: market diff --git a/Resources/Prototypes/Catalog/Cargo/cargo_service.yml b/Resources/Prototypes/Catalog/Cargo/cargo_service.yml index 06165e1282..121c51d9ec 100644 --- a/Resources/Prototypes/Catalog/Cargo/cargo_service.yml +++ b/Resources/Prototypes/Catalog/Cargo/cargo_service.yml @@ -33,3 +33,15 @@ cost: 2000 category: Service group: market + +- type: cargoProduct + name: "DIY lung cancer crate" + id: ServiceCustomSmokable + description: "Want to get a little creative with what you use to destroy your lungs? Then this crate is for you! Has everything you need to roll your own Cigarettes." + icon: + sprite: Objects/Consumable/Smokeables/Cigarettes/Cartons/green.rsi + state: closed + product: CrateServiceCustomSmokable + cost: 1000 + category: Service + group: market diff --git a/Resources/Prototypes/Catalog/Fills/Crates/food.yml b/Resources/Prototypes/Catalog/Fills/Crates/food.yml index c031fdd6b1..7d6a12d929 100644 --- a/Resources/Prototypes/Catalog/Fills/Crates/food.yml +++ b/Resources/Prototypes/Catalog/Fills/Crates/food.yml @@ -1 +1,11 @@ -# Bro what do I PUT here +- type: entity + id: CrateFoodPizza + name: emergency pizza delivery + description: Help do your part to end station hunger by distributing pizza to underfunded departments! + parent: CratePlastic + components: + - type: StorageFill + contents: + - id: FoodBoxPizzaFilled + amount: 4 + - id: KnifePlastic \ No newline at end of file diff --git a/Resources/Prototypes/Catalog/Fills/Crates/service.yml b/Resources/Prototypes/Catalog/Fills/Crates/service.yml index fca9cd747f..2e2576cf97 100644 --- a/Resources/Prototypes/Catalog/Fills/Crates/service.yml +++ b/Resources/Prototypes/Catalog/Fills/Crates/service.yml @@ -56,4 +56,19 @@ - id: CigarCase orGroup: Cigars - id: Matchbox - amount: 2 + amount: 2 + +- type: entity + id: CrateServiceCustomSmokable + name: DIY smokeables crate + description: Want to get a little creative with what you use to destroy your lungs? Then this crate is for you! Has everything you need to roll your own Cigarettes. + parent: CrateGenericonimo + components: + - type: StorageFill + contents: + - id: PackPaperRolling + - id: CigaretteFilter + amount: 8 + - id: GroundTobacco + amount: 4 + - id: Matchbox diff --git a/Resources/Prototypes/Entities/Objects/Specific/Medical/morgue.yml b/Resources/Prototypes/Entities/Objects/Specific/Medical/morgue.yml index 8930b4141f..56a0fd0cde 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Medical/morgue.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Medical/morgue.yml @@ -32,6 +32,13 @@ path: /Audio/Misc/zip.ogg openSound: path: /Audio/Misc/zip.ogg + - type: PaperLabel + - type: ItemSlots + slots: + labelSlot: + whitelist: + components: + - Paper - type: Appearance visuals: - type: StorageVisualizer diff --git a/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml b/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml index 1950c686a7..3f1511c3a8 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml @@ -226,6 +226,7 @@ - type: CargoOrderDatabase - type: GalacticMarket products: + - MedicalSupplies - EmergencyExplosive - EmergencyFire - EmergencyInternals @@ -242,8 +243,11 @@ - HydroponicsSeeds - HydroponicsSeedsExotic - LivestockMonkeyCube + - FoodPizza - ServiceJanitorial - ServiceLightsReplacement + - ServiceSmokeables + - ServiceCustomSmokable - EngineeringCableLv - EngineeringCableMv - EngineeringCableHv @@ -282,6 +286,8 @@ radius: 1.5 energy: 1.6 color: "#b89f25" + - type: AccessReader + access: [["Cargo"]] - type: entity id: ComputerSupplyRequest diff --git a/Resources/Prototypes/Entities/Structures/Storage/Crates/base.yml b/Resources/Prototypes/Entities/Structures/Storage/Crates/base.yml index e1dbf08572..a7196f62fd 100644 --- a/Resources/Prototypes/Entities/Structures/Storage/Crates/base.yml +++ b/Resources/Prototypes/Entities/Structures/Storage/Crates/base.yml @@ -53,3 +53,10 @@ - type: StorageVisualizer state_open: crate_open state_closed: crate_door + - type: PaperLabel + - type: ItemSlots + slots: + labelSlot: + whitelist: + components: + - Paper