Cargo: pizza & bureaucracy (#5123)

* add paper label component

* git mv

* rename namespace

* add cargo printouts

* more crates

* directly attach paper

* comment typo
This commit is contained in:
Leon Friedrich
2021-11-11 02:15:23 +13:00
committed by GitHub
parent b8d8f48b11
commit 88df3d8b10
33 changed files with 384 additions and 162 deletions

View File

@@ -25,6 +25,7 @@ namespace Content.Client.Entry
"MeleeWeapon", "MeleeWeapon",
"MeleeChemicalInjector", "MeleeChemicalInjector",
"Dice", "Dice",
"PaperLabel",
"Construction", "Construction",
"PoweredLight", "PoweredLight",
"Smes", "Smes",

View File

@@ -1,8 +1,8 @@
using Content.Shared.HandLabeler; using Content.Shared.Labels;
using Robust.Client.GameObjects; using Robust.Client.GameObjects;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
namespace Content.Client.HandLabeler.UI namespace Content.Client.Labels.UI
{ {
/// <summary> /// <summary>
/// Initializes a <see cref="HandLabelerWindow"/> and updates it when new server messages are received. /// Initializes a <see cref="HandLabelerWindow"/> and updates it when new server messages are received.

View File

@@ -4,7 +4,7 @@ using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML; using Robust.Client.UserInterface.XAML;
namespace Content.Client.HandLabeler.UI namespace Content.Client.Labels.UI
{ {
[GenerateTypedNameReferences] [GenerateTypedNameReferences]
public partial class HandLabelerWindow : SS14Window public partial class HandLabelerWindow : SS14Window

View File

@@ -1,4 +1,4 @@
using Content.Shared.Morgue; using Content.Shared.Labels;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Client.GameObjects; using Robust.Client.GameObjects;
@@ -16,7 +16,7 @@ namespace Content.Client.Morgue.Visualizers
return; return;
} }
if (component.TryGetData(BodyBagVisuals.Label, out bool labelVal)) if (component.TryGetData(PaperLabelVisuals.HasLabel, out bool labelVal))
{ {
sprite.LayerSetVisible(BodyBagVisualLayers.Label, labelVal); sprite.LayerSetVisible(BodyBagVisualLayers.Label, labelVal);
} }

View File

@@ -1,7 +1,13 @@
using Content.Server.Access.Components; 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.Access;
using Content.Shared.Hands.Components;
using Content.Shared.Inventory;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.Localization; using Robust.Shared.Localization;
using System.Diagnostics.CodeAnalysis;
namespace Content.Server.Access.Systems namespace Content.Server.Access.Systems
{ {
@@ -74,5 +80,53 @@ namespace Content.Server.Access.Systems
("fullName", id.FullName), ("fullName", id.FullName),
("jobSuffix", jobSuffix)); ("jobSuffix", jobSuffix));
} }
/// <summary>
/// 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.
/// </summary>
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;
}
/// <summary>
/// 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 <see cref="PDAComponent"/>.
/// </summary>
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;
}
} }
} }

View File

@@ -1,9 +1,12 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using Content.Server.Access.Components;
using Content.Server.Access.Systems;
using Content.Server.Cargo.Components; using Content.Server.Cargo.Components;
using Content.Shared.Cargo; using Content.Shared.Cargo;
using Content.Shared.GameTicking; using Content.Shared.GameTicking;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
namespace Content.Server.Cargo namespace Content.Server.Cargo
{ {
@@ -43,6 +46,9 @@ namespace Content.Server.Cargo
public CargoOrderDatabase StationOrderDatabase => GetOrderDatabase(0); public CargoOrderDatabase StationOrderDatabase => GetOrderDatabase(0);
[Dependency] private readonly IdCardSystem _idCardSystem = default!;
[Dependency] private readonly AccessReaderSystem _accessReaderSystem = default!;
public override void Initialize() public override void Initialize()
{ {
SubscribeLocalEvent<RoundRestartCleanupEvent>(Reset); SubscribeLocalEvent<RoundRestartCleanupEvent>(Reset);
@@ -171,12 +177,25 @@ namespace Content.Server.Cargo
return true; 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)) if (!TryGetOrderDatabase(id, out var database))
return false; return false;
if (!database.ApproveOrder(orderNumber))
if (!database.TryGetOrder(orderNumber, out var order))
return false; return false;
if (!database.ApproveOrder(approverName, orderNumber))
return false;
SyncComponentsWithId(id); SyncComponentsWithId(id);
return true; return true;
} }

View File

@@ -1,7 +1,9 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using Content.Server.Access.Systems;
using Content.Shared.Cargo; using Content.Shared.Cargo;
using Robust.Shared.GameObjects;
using Robust.Shared.Localization; using Robust.Shared.Localization;
namespace Content.Server.Cargo namespace Content.Server.Cargo
@@ -84,7 +86,7 @@ namespace Content.Server.Cargo
/// Approves an order in the database. /// Approves an order in the database.
/// </summary> /// </summary>
/// <param name="order">The order to be approved.</param> /// <param name="order">The order to be approved.</param>
public bool ApproveOrder(int orderNumber) public bool ApproveOrder(string approver, int orderNumber)
{ {
if (CurrentOrderSize == MaxOrderSize || if (CurrentOrderSize == MaxOrderSize ||
!_orders.TryGetValue(orderNumber, out var order) || !_orders.TryGetValue(orderNumber, out var order) ||
@@ -104,6 +106,8 @@ namespace Content.Server.Cargo
} }
order.Approved = true; order.Approved = true;
order.Approver = approver;
CurrentOrderSize += order.Amount; CurrentOrderSize += order.Amount;
return true; return true;
} }

View File

@@ -135,6 +135,10 @@ namespace Content.Server.Cargo.Components
break; break;
} }
var uid = msg.Session.AttachedEntityUid;
if (uid == null)
break;
PrototypeManager.TryIndex(order.ProductId, out CargoProductPrototype? product); PrototypeManager.TryIndex(order.ProductId, out CargoProductPrototype? product);
if (product == null!) if (product == null!)
break; break;
@@ -143,13 +147,14 @@ namespace Content.Server.Cargo.Components
(capacity.CurrentCapacity == capacity.MaxCapacity (capacity.CurrentCapacity == capacity.MaxCapacity
|| capacity.CurrentCapacity + order.Amount > capacity.MaxCapacity || capacity.CurrentCapacity + order.Amount > capacity.MaxCapacity
|| !_cargoConsoleSystem.CheckBalance(_bankAccount.Id, (-product.PointCost) * order.Amount) || !_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)) || !_cargoConsoleSystem.ChangeBalance(_bankAccount.Id, (-product.PointCost) * order.Amount))
) )
{ {
SoundSystem.Play(Filter.Local(), _errorSound.GetSound(), Owner, AudioParams.Default); SoundSystem.Play(Filter.Local(), _errorSound.GetSound(), Owner, AudioParams.Default);
break; break;
} }
UpdateUIState(); UpdateUIState();
break; break;
} }
@@ -189,12 +194,7 @@ namespace Content.Server.Cargo.Components
orders.Database.ClearOrderCapacity(); orders.Database.ClearOrderCapacity();
foreach (var order in approvedOrders) foreach (var order in approvedOrders)
{ {
if (!PrototypeManager.TryIndex(order.ProductId, out CargoProductPrototype? product)) telepadComponent.QueueTeleport(order);
continue;
for (var i = 0; i < order.Amount; i++)
{
telepadComponent.QueueTeleport(product);
}
} }
} }
} }

View File

@@ -1,13 +1,20 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Content.Server.Labels.Components;
using Content.Server.Paper;
using Content.Server.Power.Components; using Content.Server.Power.Components;
using Content.Shared.Cargo; using Content.Shared.Cargo;
using Content.Shared.Containers.ItemSlots;
using Content.Shared.Sound; using Content.Shared.Sound;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
using Robust.Shared.Audio; using Robust.Shared.Audio;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Player; using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Server.Cargo.Components namespace Content.Server.Cargo.Components
{ {
@@ -17,14 +24,23 @@ namespace Content.Server.Cargo.Components
[RegisterComponent] [RegisterComponent]
public class CargoTelepadComponent : Component public class CargoTelepadComponent : Component
{ {
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;
public override string Name => "CargoTelepad"; public override string Name => "CargoTelepad";
private const float TeleportDuration = 0.5f; private const float TeleportDuration = 0.5f;
private const float TeleportDelay = 15f; private const float TeleportDelay = 15f;
private List<CargoProductPrototype> _teleportQueue = new List<CargoProductPrototype>(); private List<CargoOrderData> _teleportQueue = new();
private CargoTelepadState _currentState = CargoTelepadState.Unpowered; private CargoTelepadState _currentState = CargoTelepadState.Unpowered;
[DataField("teleportSound")] private SoundSpecifier _teleportSound = new SoundPathSpecifier("/Audio/Machines/phasein.ogg"); [DataField("teleportSound")] private SoundSpecifier _teleportSound = new SoundPathSpecifier("/Audio/Machines/phasein.ogg");
/// <summary>
/// The paper-type prototype to spawn with the order information.
/// </summary>
[DataField("printerOutput", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
public string PrinterOutput = "Paper";
[Obsolete("Component Messages are deprecated, use Entity Events instead.")] [Obsolete("Component Messages are deprecated, use Entity Events instead.")]
public override void HandleMessage(ComponentMessage message, IComponent? component) 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(); TeleportLoop();
} }
@@ -79,7 +98,7 @@ namespace Content.Server.Cargo.Components
if (!Deleted && !Owner.Deleted && _currentState == CargoTelepadState.Teleporting && _teleportQueue.Count > 0) if (!Deleted && !Owner.Deleted && _currentState == CargoTelepadState.Teleporting && _teleportQueue.Count > 0)
{ {
SoundSystem.Play(Filter.Pvs(Owner), _teleportSound.GetSound(), Owner, AudioParams.Default.WithVolume(-8f)); 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); _teleportQueue.RemoveAt(0);
if (Owner.TryGetComponent<SpriteComponent>(out var spriteComponent) && spriteComponent.LayerCount > 0) if (Owner.TryGetComponent<SpriteComponent>(out var spriteComponent) && spriteComponent.LayerCount > 0)
spriteComponent.LayerSetState(0, "idle"); spriteComponent.LayerSetState(0, "idle");
@@ -92,6 +111,38 @@ namespace Content.Server.Cargo.Components
} }
} }
/// <summary>
/// Spawn the product and a piece of paper. Attempt to attach the paper to the product.
/// </summary>
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<SharedItemSlotsSystem>().TryInsertContent(slots, printed, label.LabelSlot);
}
}
private enum CargoTelepadState { Unpowered, Idle, Charging, Teleporting }; private enum CargoTelepadState { Unpowered, Idle, Charging, Teleporting };
} }
} }

View File

@@ -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
{
/// <summary>
/// A system that lets players see the contents of a label on an object.
/// </summary>
[UsedImplicitly]
public class LabelSystem : EntitySystem
{
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<LabelComponent, ExaminedEvent>(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);
}
}
}

View File

@@ -5,7 +5,7 @@ using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;
namespace Content.Server.HandLabeler.Components namespace Content.Server.Labels.Components
{ {
[RegisterComponent] [RegisterComponent]
public class HandLabelerComponent : Component public class HandLabelerComponent : Component

View File

@@ -2,7 +2,7 @@ using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;
namespace Content.Server.HandLabeler.Components namespace Content.Server.Labels.Components
{ {
[RegisterComponent] [RegisterComponent]
public class LabelComponent : Component public class LabelComponent : Component

View File

@@ -0,0 +1,17 @@
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Server.Labels.Components
{
/// <summary>
/// This component allows you to attach and remove a piece of paper to an entity.
/// </summary>
[RegisterComponent]
public class PaperLabelComponent : Component
{
public override string Name => "PaperLabel";
[DataField("labelSlot")]
public string LabelSlot = "labelSlot";
}
}

View File

@@ -1,7 +1,7 @@
using Content.Server.HandLabeler.Components; using Content.Server.Labels.Components;
using Content.Server.UserInterface; using Content.Server.UserInterface;
using Content.Shared.ActionBlocker; using Content.Shared.ActionBlocker;
using Content.Shared.HandLabeler; using Content.Shared.Labels;
using Content.Shared.Interaction; using Content.Shared.Interaction;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
@@ -12,7 +12,7 @@ using Robust.Shared.Localization;
using Content.Shared.Popups; using Content.Shared.Popups;
using System; using System;
namespace Content.Server.HandLabeler namespace Content.Server.Labels
{ {
/// <summary> /// <summary>
/// A hand labeler system that lets an object apply labels to objects with the <see cref="LabelComponent"/> . /// A hand labeler system that lets an object apply labels to objects with the <see cref="LabelComponent"/> .

View File

@@ -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
{
/// <summary>
/// A system that lets players see the contents of a label on an object.
/// </summary>
[UsedImplicitly]
public class LabelSystem : EntitySystem
{
[Dependency] private readonly SharedItemSlotsSystem _itemSlotsSystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<LabelComponent, ExaminedEvent>(OnExamine);
SubscribeLocalEvent<PaperLabelComponent, ComponentInit>(InitializePaperLabel);
SubscribeLocalEvent<PaperLabelComponent, ItemSlotChangedEvent>(OnItemSlotChanged);
SubscribeLocalEvent<PaperLabelComponent, ExaminedEvent>(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);
}
}
}

View File

@@ -22,81 +22,14 @@ namespace Content.Server.Morgue.Components
[ComponentReference(typeof(EntityStorageComponent))] [ComponentReference(typeof(EntityStorageComponent))]
[ComponentReference(typeof(IActivate))] [ComponentReference(typeof(IActivate))]
[ComponentReference(typeof(IStorageComponent))] [ComponentReference(typeof(IStorageComponent))]
#pragma warning disable 618 public class BodyBagEntityStorageComponent : EntityStorageComponent
public class BodyBagEntityStorageComponent : EntityStorageComponent, IExamine, IInteractUsing
#pragma warning restore 618
{ {
public override string Name => "BodyBagEntityStorage"; 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<ContainerSlot>("body_bag_label", out _);
}
protected override bool AddToContents(IEntity entity) protected override bool AddToContents(IEntity entity)
{ {
if (entity.HasComponent<SharedBodyComponent>() && !EntitySystem.Get<StandingStateSystem>().IsDown(entity.Uid)) return false; if (entity.HasComponent<SharedBodyComponent>() && !EntitySystem.Get<StandingStateSystem>().IsDown(entity.Uid)) return false;
return base.AddToContents(entity); return base.AddToContents(entity);
} }
void IExamine.Examine(FormattedMessage message, bool inDetailsRange)
{
if (inDetailsRange)
{
if (LabelContainer?.ContainedEntity != null && LabelContainer.ContainedEntity.TryGetComponent<PaperComponent>(out var paper))
{
message.AddText(Loc.GetString("body-bag-entity-storage-component-on-examine-details", ("paper", paper.Content)));
}
}
}
async Task<bool> 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<HandsComponent>();
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<ItemComponent>());
_appearance?.SetData(BodyBagVisuals.Label, false);
}
else if (LabelContainer.Remove(ent))
{
ent.Transform.Coordinates = Owner.Transform.Coordinates;
_appearance?.SetData(BodyBagVisuals.Label, false);
}
}
} }
} }

View File

@@ -17,7 +17,6 @@ namespace Content.Server.Morgue
base.Initialize(); base.Initialize();
SubscribeLocalEvent<CrematoriumEntityStorageComponent, GetAlternativeVerbsEvent>(AddCremateVerb); SubscribeLocalEvent<CrematoriumEntityStorageComponent, GetAlternativeVerbsEvent>(AddCremateVerb);
SubscribeLocalEvent<BodyBagEntityStorageComponent, GetAlternativeVerbsEvent>(AddRemoveLabelVerb);
} }
private void AddCremateVerb(EntityUid uid, CrematoriumEntityStorageComponent component, GetAlternativeVerbsEvent args) private void AddCremateVerb(EntityUid uid, CrematoriumEntityStorageComponent component, GetAlternativeVerbsEvent args)
@@ -32,22 +31,6 @@ namespace Content.Server.Morgue
args.Verbs.Add(verb); args.Verbs.Add(verb);
} }
/// <summary>
/// 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.
/// </summary>
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) public override void Update(float frameTime)
{ {
_accumulatedFrameTime += frameTime; _accumulatedFrameTime += frameTime;

View File

@@ -36,6 +36,22 @@ namespace Content.Server.Paper
_mode = PaperAction.Read; _mode = PaperAction.Read;
UpdateUserInterface(); 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() private void UpdateUserInterface()
{ {
UserInterface?.SetState(new PaperBoundUserInterfaceState(Content, _mode)); UserInterface?.SetState(new PaperBoundUserInterfaceState(Content, _mode));

View File

@@ -1,4 +1,4 @@
using System; using System;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
namespace Content.Shared.Cargo namespace Content.Shared.Cargo
@@ -15,6 +15,7 @@ namespace Content.Shared.Cargo
public int Amount; public int Amount;
public int PayingAccountId; public int PayingAccountId;
public bool Approved; public bool Approved;
public string Approver = string.Empty;
public CargoOrderData(int orderNumber, string requester, string reason, string productId, int amount, int payingAccountId) public CargoOrderData(int orderNumber, string requester, string reason, string productId, int amount, int payingAccountId)
{ {
@@ -24,7 +25,6 @@ namespace Content.Shared.Cargo
ProductId = productId; ProductId = productId;
Amount = amount; Amount = amount;
PayingAccountId = payingAccountId; PayingAccountId = payingAccountId;
Approved = false;
} }
} }
} }

View File

@@ -2,7 +2,7 @@ using System;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
namespace Content.Shared.HandLabeler namespace Content.Shared.Labels
{ {
/// <summary> /// <summary>
/// Key representing which <see cref="BoundUserInterface"/> is currently open. /// Key representing which <see cref="BoundUserInterface"/> is currently open.
@@ -14,6 +14,12 @@ namespace Content.Shared.HandLabeler
Key, Key,
} }
[Serializable, NetSerializable]
public enum PaperLabelVisuals
{
HasLabel,
}
/// <summary> /// <summary>
/// Represents a <see cref="HandLabelerComponent"/> state that can be sent to the client /// Represents a <see cref="HandLabelerComponent"/> state that can be sent to the client
/// </summary> /// </summary>

View File

@@ -17,10 +17,4 @@ namespace Content.Shared.Morgue
{ {
Burning, Burning,
} }
[Serializable, NetSerializable]
public enum BodyBagVisuals
{
Label,
}
} }

View File

@@ -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-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-approve-button = Approve
cargo-console-menu-cargo-order-row-cancel-button = Cancel 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}

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -33,3 +33,15 @@
cost: 2000 cost: 2000
category: Service category: Service
group: market 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

View File

@@ -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

View File

@@ -56,4 +56,19 @@
- id: CigarCase - id: CigarCase
orGroup: Cigars orGroup: Cigars
- id: Matchbox - 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

View File

@@ -32,6 +32,13 @@
path: /Audio/Misc/zip.ogg path: /Audio/Misc/zip.ogg
openSound: openSound:
path: /Audio/Misc/zip.ogg path: /Audio/Misc/zip.ogg
- type: PaperLabel
- type: ItemSlots
slots:
labelSlot:
whitelist:
components:
- Paper
- type: Appearance - type: Appearance
visuals: visuals:
- type: StorageVisualizer - type: StorageVisualizer

View File

@@ -226,6 +226,7 @@
- type: CargoOrderDatabase - type: CargoOrderDatabase
- type: GalacticMarket - type: GalacticMarket
products: products:
- MedicalSupplies
- EmergencyExplosive - EmergencyExplosive
- EmergencyFire - EmergencyFire
- EmergencyInternals - EmergencyInternals
@@ -242,8 +243,11 @@
- HydroponicsSeeds - HydroponicsSeeds
- HydroponicsSeedsExotic - HydroponicsSeedsExotic
- LivestockMonkeyCube - LivestockMonkeyCube
- FoodPizza
- ServiceJanitorial - ServiceJanitorial
- ServiceLightsReplacement - ServiceLightsReplacement
- ServiceSmokeables
- ServiceCustomSmokable
- EngineeringCableLv - EngineeringCableLv
- EngineeringCableMv - EngineeringCableMv
- EngineeringCableHv - EngineeringCableHv
@@ -282,6 +286,8 @@
radius: 1.5 radius: 1.5
energy: 1.6 energy: 1.6
color: "#b89f25" color: "#b89f25"
- type: AccessReader
access: [["Cargo"]]
- type: entity - type: entity
id: ComputerSupplyRequest id: ComputerSupplyRequest

View File

@@ -53,3 +53,10 @@
- type: StorageVisualizer - type: StorageVisualizer
state_open: crate_open state_open: crate_open
state_closed: crate_door state_closed: crate_door
- type: PaperLabel
- type: ItemSlots
slots:
labelSlot:
whitelist:
components:
- Paper