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