VerbSystem.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. using System.Linq;
  2. using Content.Server.Administration.Managers;
  3. using Content.Server.Popups;
  4. using Content.Shared.Administration;
  5. using Content.Shared.Administration.Logs;
  6. using Content.Shared.Database;
  7. using Content.Shared.Hands.Components;
  8. using Content.Shared.Inventory.VirtualItem;
  9. using Content.Shared.Verbs;
  10. namespace Content.Server.Verbs
  11. {
  12. public sealed class VerbSystem : SharedVerbSystem
  13. {
  14. [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
  15. [Dependency] private readonly PopupSystem _popupSystem = default!;
  16. [Dependency] private readonly IAdminManager _adminMgr = default!;
  17. public override void Initialize()
  18. {
  19. base.Initialize();
  20. SubscribeNetworkEvent<RequestServerVerbsEvent>(HandleVerbRequest);
  21. }
  22. private void HandleVerbRequest(RequestServerVerbsEvent args, EntitySessionEventArgs eventArgs)
  23. {
  24. var player = eventArgs.SenderSession;
  25. if (!EntityManager.EntityExists(GetEntity(args.EntityUid)))
  26. {
  27. Log.Warning($"{nameof(HandleVerbRequest)} called on a non-existent entity with id {args.EntityUid} by player {player}.");
  28. return;
  29. }
  30. if (player.AttachedEntity is not {} attached)
  31. {
  32. Log.Warning($"{nameof(HandleVerbRequest)} called by player {player} with no attached entity.");
  33. return;
  34. }
  35. // We do not verify that the user has access to the requested entity. The individual verbs should check
  36. // this, and some verbs (e.g. view variables) won't even care about whether an entity is accessible through
  37. // the entity menu or not.
  38. var force = args.AdminRequest && eventArgs.SenderSession is { } playerSession &&
  39. _adminMgr.HasAdminFlag(playerSession, AdminFlags.Admin);
  40. List<Type> verbTypes = new();
  41. foreach (var key in args.VerbTypes)
  42. {
  43. var type = Verb.VerbTypes.FirstOrDefault(x => x.Name == key);
  44. if (type != null)
  45. verbTypes.Add(type);
  46. else
  47. Log.Error($"Unknown verb type received: {key}");
  48. }
  49. var response =
  50. new VerbsResponseEvent(args.EntityUid, GetLocalVerbs(GetEntity(args.EntityUid), attached, verbTypes, force));
  51. RaiseNetworkEvent(response, player.Channel);
  52. }
  53. /// <summary>
  54. /// Execute the provided verb.
  55. /// </summary>
  56. /// <remarks>
  57. /// This will try to call the action delegates and raise the local events for the given verb.
  58. /// </remarks>
  59. public override void ExecuteVerb(Verb verb, EntityUid user, EntityUid target, bool forced = false)
  60. {
  61. // is this verb actually valid?
  62. if (verb.Disabled)
  63. {
  64. // Send an informative pop-up message
  65. if (!string.IsNullOrWhiteSpace(verb.Message))
  66. _popupSystem.PopupEntity(verb.Message, user, user);
  67. return;
  68. }
  69. // first, lets log the verb. Just in case it ends up crashing the server or something.
  70. LogVerb(verb, user, target, forced);
  71. base.ExecuteVerb(verb, user, target, forced);
  72. }
  73. public void LogVerb(Verb verb, EntityUid user, EntityUid target, bool forced)
  74. {
  75. // first get the held item. again.
  76. EntityUid? holding = null;
  77. if (TryComp(user, out HandsComponent? hands) &&
  78. hands.ActiveHandEntity is EntityUid heldEntity)
  79. {
  80. holding = heldEntity;
  81. }
  82. // if this is a virtual pull, get the held entity
  83. if (holding != null && TryComp(holding, out VirtualItemComponent? pull))
  84. holding = pull.BlockingEntity;
  85. var verbText = $"{verb.Category?.Text} {verb.Text}".Trim();
  86. // lets not frame people, eh?
  87. var executionText = forced ? "was forced to execute" : "executed";
  88. if (holding == null)
  89. {
  90. _adminLogger.Add(LogType.Verb, verb.Impact,
  91. $"{ToPrettyString(user):user} {executionText} the [{verbText:verb}] verb targeting {ToPrettyString(target):target}");
  92. }
  93. else
  94. {
  95. _adminLogger.Add(LogType.Verb, verb.Impact,
  96. $"{ToPrettyString(user):user} {executionText} the [{verbText:verb}] verb targeting {ToPrettyString(target):target} while holding {ToPrettyString(holding.Value):held}");
  97. }
  98. }
  99. }
  100. }