1
0

StorageVoiceControlSystem.cs 4.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. using Content.Server.Hands.Systems;
  2. using Content.Server.Storage.EntitySystems;
  3. using Content.Shared.Administration.Logs;
  4. using Content.Shared.Database;
  5. using Content.Shared.Hands.Components;
  6. using Content.Shared.Inventory;
  7. using Content.Shared.Popups;
  8. using Content.Shared.Storage;
  9. using Robust.Server.Containers;
  10. namespace Content.Server.VoiceTrigger;
  11. /// <summary>
  12. /// Allows storages to be manipulated using voice commands.
  13. /// </summary>
  14. public sealed class StorageVoiceControlSystem : EntitySystem
  15. {
  16. [Dependency] private readonly ContainerSystem _container = default!;
  17. [Dependency] private readonly HandsSystem _hands = default!;
  18. [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
  19. [Dependency] private readonly InventorySystem _inventory = default!;
  20. [Dependency] private readonly SharedPopupSystem _popup = default!;
  21. [Dependency] private readonly StorageSystem _storage = default!;
  22. public override void Initialize()
  23. {
  24. base.Initialize();
  25. SubscribeLocalEvent<StorageVoiceControlComponent, VoiceTriggeredEvent>(VoiceTriggered);
  26. }
  27. private void VoiceTriggered(Entity<StorageVoiceControlComponent> ent, ref VoiceTriggeredEvent args)
  28. {
  29. // Check if the component has any slot restrictions via AllowedSlots
  30. // If it has slot restrictions, check if the item is in a slot that is allowed
  31. if (ent.Comp.AllowedSlots != null && _inventory.TryGetContainingSlot(ent.Owner, out var itemSlot) &&
  32. (itemSlot.SlotFlags & ent.Comp.AllowedSlots) == 0)
  33. return;
  34. // Don't do anything if there is no message
  35. if (args.Message == null)
  36. return;
  37. // Get the storage component
  38. if (!TryComp<StorageComponent>(ent, out var storage))
  39. return;
  40. // Get the hands component
  41. if (!TryComp<HandsComponent>(args.Source, out var hands))
  42. return;
  43. // If the player has something in their hands, try to insert it into the storage
  44. if (hands.ActiveHand != null && hands.ActiveHand.HeldEntity.HasValue)
  45. {
  46. // Disallow insertion and provide a reason why if the person decides to insert the item into itself
  47. if (ent.Owner.Equals(hands.ActiveHand.HeldEntity.Value))
  48. {
  49. _popup.PopupEntity(Loc.GetString("comp-storagevoicecontrol-self-insert", ("entity", hands.ActiveHand.HeldEntity.Value)), ent, args.Source);
  50. return;
  51. }
  52. if (_storage.CanInsert(ent, hands.ActiveHand.HeldEntity.Value, out var failedReason))
  53. {
  54. // We adminlog before insertion, otherwise the logger will attempt to pull info on an entity that no longer is present and throw an exception
  55. _adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(args.Source)} inserted {ToPrettyString(hands.ActiveHand.HeldEntity.Value)} into {ToPrettyString(ent)} via voice control");
  56. _storage.Insert(ent, hands.ActiveHand.HeldEntity.Value, out _);
  57. return;
  58. }
  59. {
  60. // Tell the player the reason why the item couldn't be inserted
  61. if (failedReason == null)
  62. return;
  63. _popup.PopupEntity(Loc.GetString(failedReason), ent, args.Source);
  64. _adminLogger.Add(LogType.Action,
  65. LogImpact.Low,
  66. $"{ToPrettyString(args.Source)} failed to insert {ToPrettyString(hands.ActiveHand.HeldEntity.Value)} into {ToPrettyString(ent)} via voice control");
  67. }
  68. return;
  69. }
  70. // If otherwise, we're retrieving an item, so check all the items currently in the attached storage
  71. foreach (var item in storage.Container.ContainedEntities)
  72. {
  73. // Get the item's name
  74. var itemName = MetaData(item).EntityName;
  75. // The message doesn't match the item name the requestor requested, skip and move on to the next item
  76. if (!args.Message.Contains(itemName, StringComparison.InvariantCultureIgnoreCase))
  77. continue;
  78. // We found the item we want, so draw it from storage and place it into the player's hands
  79. if (storage.Container.ContainedEntities.Count != 0)
  80. {
  81. _container.RemoveEntity(ent, item);
  82. _adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(args.Source)} retrieved {ToPrettyString(item)} from {ToPrettyString(ent)} via voice control");
  83. _hands.TryPickup(args.Source, item, handsComp: hands);
  84. break;
  85. }
  86. }
  87. }
  88. }