Log verbs & alt-click interactions. (#5471)

* verb logging

* Just a lil regex

Verb ([a-zA-Z]*) = new\(\)
Verb $1 = new(args)

* nvm that didn't work

* better log messages

* Revert "Just a lil regex"

This reverts commit aa2b143d042f1ed007c801d9e2c264cb07993aa1.

* remove garbage code

* better docstring
This commit is contained in:
Leon Friedrich
2021-11-23 23:00:16 +13:00
committed by GitHub
parent 2a7451dd9d
commit 3d755caea1
11 changed files with 73 additions and 9 deletions

View File

@@ -206,7 +206,11 @@ namespace Content.Client.Verbs
return; return;
} }
ExecuteVerb(verb); var user = _playerManager.LocalPlayer?.ControlledEntityUid;
if (user == null)
return;
ExecuteVerb(verb, user.Value, target);
if (!verb.ClientExclusive) if (!verb.ClientExclusive)
{ {

View File

@@ -15,6 +15,7 @@ using Content.Server.Mind.Commands;
using Content.Server.Mind.Components; using Content.Server.Mind.Components;
using Content.Server.Players; using Content.Server.Players;
using Content.Shared.Administration; using Content.Shared.Administration;
using Content.Shared.Administration.Logs;
using Content.Shared.Body.Components; using Content.Shared.Body.Components;
using Content.Shared.GameTicking; using Content.Shared.GameTicking;
using Content.Shared.Interaction.Helpers; using Content.Shared.Interaction.Helpers;
@@ -67,6 +68,7 @@ namespace Content.Server.Administration
verb.Category = VerbCategory.Debug; verb.Category = VerbCategory.Debug;
verb.IconTexture = "/Textures/Interface/VerbIcons/delete_transparent.svg.192dpi.png"; verb.IconTexture = "/Textures/Interface/VerbIcons/delete_transparent.svg.192dpi.png";
verb.Act = () => args.Target.Delete(); verb.Act = () => args.Target.Delete();
verb.Impact = LogImpact.Medium;
args.Verbs.Add(verb); args.Verbs.Add(verb);
} }
@@ -78,6 +80,7 @@ namespace Content.Server.Administration
verb.Category = VerbCategory.Debug; verb.Category = VerbCategory.Debug;
verb.IconTexture = "/Textures/Interface/VerbIcons/rejuvenate.svg.192dpi.png"; verb.IconTexture = "/Textures/Interface/VerbIcons/rejuvenate.svg.192dpi.png";
verb.Act = () => RejuvenateCommand.PerformRejuvenate(args.Target); verb.Act = () => RejuvenateCommand.PerformRejuvenate(args.Target);
verb.Impact = LogImpact.Medium;
args.Verbs.Add(verb); args.Verbs.Add(verb);
} }
@@ -95,6 +98,7 @@ namespace Content.Server.Administration
{ {
player.ContentData()?.Mind?.TransferTo(args.Target.Uid, ghostCheckOverride: true); player.ContentData()?.Mind?.TransferTo(args.Target.Uid, ghostCheckOverride: true);
}; };
verb.Impact = LogImpact.High;
args.Verbs.Add(verb); args.Verbs.Add(verb);
} }
@@ -108,9 +112,11 @@ namespace Content.Server.Administration
verb.Category = VerbCategory.Debug; verb.Category = VerbCategory.Debug;
verb.IconTexture = "/Textures/Interface/VerbIcons/sentient.svg.192dpi.png"; verb.IconTexture = "/Textures/Interface/VerbIcons/sentient.svg.192dpi.png";
verb.Act = () => MakeSentientCommand.MakeSentient(args.Target.Uid, EntityManager); verb.Act = () => MakeSentientCommand.MakeSentient(args.Target.Uid, EntityManager);
verb.Impact = LogImpact.Medium;
args.Verbs.Add(verb); args.Verbs.Add(verb);
} }
// Atillery
if (_adminManager.HasAdminFlag(player, AdminFlags.Fun)) if (_adminManager.HasAdminFlag(player, AdminFlags.Fun))
{ {
Verb verb = new(); Verb verb = new();
@@ -125,6 +131,7 @@ namespace Content.Server.Administration
body.Gib(); body.Gib();
} }
}; };
verb.Impact = LogImpact.Extreme; // if you're just outright killing a person, I guess that deserves to be extreme?
args.Verbs.Add(verb); args.Verbs.Add(verb);
} }
@@ -137,6 +144,7 @@ namespace Content.Server.Administration
verb.Category = VerbCategory.Debug; verb.Category = VerbCategory.Debug;
verb.IconTexture = "/Textures/Interface/VerbIcons/outfit.svg.192dpi.png"; verb.IconTexture = "/Textures/Interface/VerbIcons/outfit.svg.192dpi.png";
verb.Act = () => _euiManager.OpenEui(new SetOutfitEui(args.Target), player); verb.Act = () => _euiManager.OpenEui(new SetOutfitEui(args.Target), player);
verb.Impact = LogImpact.Medium;
args.Verbs.Add(verb); args.Verbs.Add(verb);
} }
@@ -179,6 +187,7 @@ namespace Content.Server.Administration
// TODO VERB ICON add ghost icon // TODO VERB ICON add ghost icon
// Where is the national park service icon for haunted forests? // Where is the national park service icon for haunted forests?
verb.Act = () => _ghostRoleSystem.OpenMakeGhostRoleEui(player, args.Target.Uid); verb.Act = () => _ghostRoleSystem.OpenMakeGhostRoleEui(player, args.Target.Uid);
verb.Impact = LogImpact.Medium;
args.Verbs.Add(verb); args.Verbs.Add(verb);
} }
@@ -203,6 +212,7 @@ namespace Content.Server.Administration
verb.Category = VerbCategory.Debug; verb.Category = VerbCategory.Debug;
verb.IconTexture = "/Textures/Interface/VerbIcons/spill.svg.192dpi.png"; verb.IconTexture = "/Textures/Interface/VerbIcons/spill.svg.192dpi.png";
verb.Act = () => OpenEditSolutionsEui(player, args.Target.Uid); verb.Act = () => OpenEditSolutionsEui(player, args.Target.Uid);
verb.Impact = LogImpact.Medium; // maybe high depending on WHAT reagents they add...
args.Verbs.Add(verb); args.Verbs.Add(verb);
} }
} }

View File

@@ -5,6 +5,7 @@ using System.Linq;
using Content.Server.Chemistry.EntitySystems; using Content.Server.Chemistry.EntitySystems;
using Content.Server.Construction.Components; using Content.Server.Construction.Components;
using Content.Server.Fluids.Components; using Content.Server.Fluids.Components;
using Content.Shared.Administration.Logs;
using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Reagent; using Content.Shared.Chemistry.Reagent;
using Content.Shared.Directions; using Content.Shared.Directions;
@@ -104,6 +105,7 @@ namespace Content.Server.Fluids.EntitySystems
// TODO VERB ICONS spill icon? pouring out a glass/beaker? // TODO VERB ICONS spill icon? pouring out a glass/beaker?
verb.Act = () => _solutionContainerSystem.SplitSolution(args.Target.Uid, verb.Act = () => _solutionContainerSystem.SplitSolution(args.Target.Uid,
solution, solution.DrainAvailable).SpillAt(args.Target.Transform.Coordinates, "PuddleSmear"); solution, solution.DrainAvailable).SpillAt(args.Target.Transform.Coordinates, "PuddleSmear");
verb.Impact = LogImpact.Medium; // dangerous reagent reaction are logged separately.
args.Verbs.Add(verb); args.Verbs.Add(verb);
} }

View File

@@ -1,4 +1,5 @@
using Content.Server.Morgue.Components; using Content.Server.Morgue.Components;
using Content.Shared.Administration.Logs;
using Content.Shared.Verbs; using Content.Shared.Verbs;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
@@ -28,6 +29,7 @@ namespace Content.Server.Morgue
verb.Text = Loc.GetString("cremate-verb-get-data-text"); verb.Text = Loc.GetString("cremate-verb-get-data-text");
// TODO VERB ICON add flame/burn symbol? // TODO VERB ICON add flame/burn symbol?
verb.Act = () => component.TryCremate(); verb.Act = () => component.TryCremate();
verb.Impact = LogImpact.Medium; // could be a body? or evidence? I dunno.
args.Verbs.Add(verb); args.Verbs.Add(verb);
} }

View File

@@ -78,7 +78,7 @@ namespace Content.Server.Verbs.Commands
verbs.TryGetValue(key, out var vset) && verbs.TryGetValue(key, out var vset) &&
vset.Any()) vset.Any())
{ {
verbSystem.ExecuteVerb(vset.First()); verbSystem.ExecuteVerb(vset.First(), playerEntity.Uid, target.Uid, forced: true);
shell.WriteLine(Loc.GetString("invoke-verb-command-success", ("verb", verbName), ("target", target), ("player", playerEntity))); shell.WriteLine(Loc.GetString("invoke-verb-command-success", ("verb", verbName), ("target", target), ("player", playerEntity)));
return; return;
} }
@@ -89,7 +89,7 @@ namespace Content.Server.Verbs.Commands
{ {
if (verb.Text.ToLowerInvariant() == verbName) if (verb.Text.ToLowerInvariant() == verbName)
{ {
verbSystem.ExecuteVerb(verb); verbSystem.ExecuteVerb(verb, playerEntity.Uid, target.Uid, forced: true);
shell.WriteLine(Loc.GetString("invoke-verb-command-success", ("verb", verb.Text), ("target", target), ("player", playerEntity))); shell.WriteLine(Loc.GetString("invoke-verb-command-success", ("verb", verb.Text), ("target", target), ("player", playerEntity)));
return; return;
} }

View File

@@ -45,7 +45,7 @@ namespace Content.Server.Verbs
// Find the requested verb. // Find the requested verb.
if (verbs.TryGetValue(args.RequestedVerb, out var verb)) if (verbs.TryGetValue(args.RequestedVerb, out var verb))
ExecuteVerb(verb); ExecuteVerb(verb, userEntity.Uid, args.Target);
else else
// 404 Verb not found. Note that this could happen due to something as simple as opening the verb menu, walking away, then trying // 404 Verb not found. Note that this could happen due to something as simple as opening the verb menu, walking away, then trying
// to run the pickup-item verb. So maybe this shouldn't even be logged? // to run the pickup-item verb. So maybe this shouldn't even be logged?

View File

@@ -12,6 +12,7 @@ public enum LogType
EventStarted = 6, EventStarted = 6,
EventRan = 16, EventRan = 16,
EventStopped = 7, EventStopped = 7,
Verb = 19,
ShuttleCalled = 8, ShuttleCalled = 8,
ShuttleRecalled = 9, ShuttleRecalled = 9,
ChemicalReaction = 17, ChemicalReaction = 17,

View File

@@ -530,7 +530,7 @@ namespace Content.Shared.Interaction
if (verb.Disabled) if (verb.Disabled)
continue; continue;
_verbSystem.ExecuteVerb(verb); _verbSystem.ExecuteVerb(verb, user.Uid, target.Uid);
break; break;
} }
} }

View File

@@ -1,21 +1,26 @@
using System.Collections.Generic; using System.Collections.Generic;
using Content.Shared.Administration.Logs;
using Content.Shared.Hands.Components;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
namespace Content.Shared.Verbs namespace Content.Shared.Verbs
{ {
public class SharedVerbSystem : EntitySystem public abstract class SharedVerbSystem : EntitySystem
{ {
[Dependency] private readonly SharedAdminLogSystem _logSystem = default!;
/// <summary> /// <summary>
/// Raises a number of events in order to get all verbs of the given type(s) defined in local systems. This /// Raises a number of events in order to get all verbs of the given type(s) defined in local systems. This
/// does not request verbs from the server. /// does not request verbs from the server.
/// </summary> /// </summary>
public virtual Dictionary<VerbType, SortedSet<Verb>> GetLocalVerbs(IEntity target, IEntity user, VerbType verbTypes, bool force=false) public virtual Dictionary<VerbType, SortedSet<Verb>> GetLocalVerbs(IEntity target, IEntity user, VerbType verbTypes, bool force = false)
{ {
Dictionary<VerbType, SortedSet<Verb>> verbs = new(); Dictionary<VerbType, SortedSet<Verb>> verbs = new();
if ((verbTypes & VerbType.Interaction) == VerbType.Interaction) if ((verbTypes & VerbType.Interaction) == VerbType.Interaction)
{ {
GetInteractionVerbsEvent getVerbEvent = new(user, target, force); GetInteractionVerbsEvent getVerbEvent = new(user, target, force);
RaiseLocalEvent(target.Uid, getVerbEvent); RaiseLocalEvent(target.Uid, getVerbEvent);
verbs.Add(VerbType.Interaction, getVerbEvent.Verbs); verbs.Add(VerbType.Interaction, getVerbEvent.Verbs);
} }
@@ -50,9 +55,12 @@ namespace Content.Shared.Verbs
/// <remarks> /// <remarks>
/// This will try to call the action delegates and raise the local events for the given verb. /// This will try to call the action delegates and raise the local events for the given verb.
/// </remarks> /// </remarks>
public void ExecuteVerb(Verb verb) public void ExecuteVerb(Verb verb, EntityUid user, EntityUid target, bool forced = false)
{ {
// first, lets log the verb. Just in case it ends up crashing the server or something.
LogVerb(verb, user, target, forced);
// then invoke any relevant actions
verb.Act?.Invoke(); verb.Act?.Invoke();
// Maybe raise a local event // Maybe raise a local event
@@ -64,5 +72,32 @@ namespace Content.Shared.Verbs
RaiseLocalEvent(verb.ExecutionEventArgs); RaiseLocalEvent(verb.ExecutionEventArgs);
} }
} }
public void LogVerb(Verb verb, EntityUid user, EntityUid target, bool forced)
{
// first get the held item. again.
EntityUid? used = null;
if (EntityManager.TryGetComponent(user, out SharedHandsComponent? hands))
{
hands.TryGetActiveHeldEntity(out var useEntityd);
used = useEntityd?.Uid;
if (used != null && EntityManager.TryGetComponent(used.Value, out HandVirtualItemComponent? pull))
used = pull.BlockingEntity;
}
// then prepare the basic log message body
var verbText = $"{verb.Category?.Text} {verb.Text}".Trim();
var logText = forced
? $"was forced to execute the '{verbText}' verb targeting " // let's not frame people, eh?
: $"executed '{verbText}' verb targeting ";
// then log with entity information
if (used != null)
_logSystem.Add(LogType.Verb, verb.Impact,
$"{user} {logText} {target} while holding {used}");
else
_logSystem.Add(LogType.Verb, verb.Impact,
$"{user} {logText} {target}");
}
} }
} }

View File

@@ -1,3 +1,4 @@
using Content.Shared.Administration.Logs;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
using Robust.Shared.Utility; using Robust.Shared.Utility;
@@ -125,6 +126,14 @@ namespace Content.Shared.Verbs
/// </remarks> /// </remarks>
public bool CloseMenu = true; public bool CloseMenu = true;
/// <summary>
/// How important is this verb, for the purposes of admin logging?
/// </summary>
/// <remarks>
/// If this is just opening a UI or ejecting an id card, this should probably be low.
/// </remarks>
public LogImpact Impact = LogImpact.Low;
/// <summary> /// <summary>
/// Compares two verbs based on their <see cref="Priority"/>, <see cref="Category"/>, <see cref="Text"/>, /// Compares two verbs based on their <see cref="Priority"/>, <see cref="Category"/>, <see cref="Text"/>,
/// and <see cref="IconTexture"/>. /// and <see cref="IconTexture"/>.

View File

@@ -7,6 +7,7 @@ using Robust.Shared.GameObjects;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Content.Shared.Interaction; using Content.Shared.Interaction;
using System.Collections.Immutable;
namespace Content.Shared.Verbs namespace Content.Shared.Verbs
{ {