2023-04-07 11:21:12 -07:00
using System.Linq ;
2021-12-30 14:11:30 -08:00
using Content.Server.Administration.Managers ;
2021-12-16 23:42:02 +13:00
using Content.Server.Popups ;
2021-12-30 14:11:30 -08:00
using Content.Shared.Administration ;
2021-12-16 23:42:02 +13:00
using Content.Shared.Administration.Logs ;
using Content.Shared.Database ;
using Content.Shared.Hands.Components ;
2024-01-14 06:18:47 -04:00
using Content.Shared.Inventory.VirtualItem ;
2021-06-09 22:19:39 +02:00
using Content.Shared.Verbs ;
2018-11-21 20:58:11 +01:00
2021-06-09 22:19:39 +02:00
namespace Content.Server.Verbs
2018-11-21 20:58:11 +01:00
{
2021-10-05 14:29:03 +11:00
public sealed class VerbSystem : SharedVerbSystem
2018-11-21 20:58:11 +01:00
{
2022-05-28 23:41:17 -07:00
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default ! ;
2021-12-16 23:42:02 +13:00
[Dependency] private readonly PopupSystem _popupSystem = default ! ;
2021-12-30 14:11:30 -08:00
[Dependency] private readonly IAdminManager _adminMgr = default ! ;
2021-12-16 23:42:02 +13:00
2018-11-21 20:58:11 +01:00
public override void Initialize ( )
{
base . Initialize ( ) ;
2021-10-05 14:29:03 +11:00
SubscribeNetworkEvent < RequestServerVerbsEvent > ( HandleVerbRequest ) ;
2020-02-18 19:43:54 -08:00
}
2018-11-21 20:58:11 +01:00
2021-10-05 14:29:03 +11:00
private void HandleVerbRequest ( RequestServerVerbsEvent args , EntitySessionEventArgs eventArgs )
2020-02-18 19:43:54 -08:00
{
2023-10-28 09:59:53 +11:00
var player = eventArgs . SenderSession ;
2018-11-21 20:58:11 +01:00
2023-09-11 09:42:41 +10:00
if ( ! EntityManager . EntityExists ( GetEntity ( args . EntityUid ) ) )
2020-02-18 19:43:54 -08:00
{
2023-09-11 09:42:41 +10:00
Log . Warning ( $"{nameof(HandleVerbRequest)} called on a non-existent entity with id {args.EntityUid} by player {player}." ) ;
2020-02-18 19:43:54 -08:00
return ;
}
2019-11-23 19:11:50 +00:00
2021-12-06 15:34:46 +01:00
if ( player . AttachedEntity is not { } attached )
2020-08-15 20:38:37 +02:00
{
2023-09-11 09:42:41 +10:00
Log . Warning ( $"{nameof(HandleVerbRequest)} called by player {player} with no attached entity." ) ;
2020-08-15 20:38:37 +02:00
return ;
}
2021-10-28 18:21:19 +13:00
// We do not verify that the user has access to the requested entity. The individual verbs should check
// this, and some verbs (e.g. view variables) won't even care about whether an entity is accessible through
// the entity menu or not.
2020-02-18 19:43:54 -08:00
2023-10-28 09:59:53 +11:00
var force = args . AdminRequest & & eventArgs . SenderSession is { } playerSession & &
2021-12-30 14:11:30 -08:00
_adminMgr . HasAdminFlag ( playerSession , AdminFlags . Admin ) ;
2022-02-10 15:30:59 +13:00
List < Type > verbTypes = new ( ) ;
foreach ( var key in args . VerbTypes )
{
var type = Verb . VerbTypes . FirstOrDefault ( x = > x . Name = = key ) ;
if ( type ! = null )
verbTypes . Add ( type ) ;
else
2023-09-11 09:42:41 +10:00
Log . Error ( $"Unknown verb type received: {key}" ) ;
2022-02-10 15:30:59 +13:00
}
2021-12-30 14:11:30 -08:00
var response =
2023-09-11 09:42:41 +10:00
new VerbsResponseEvent ( args . EntityUid , GetLocalVerbs ( GetEntity ( args . EntityUid ) , attached , verbTypes , force ) ) ;
2024-01-22 23:14:13 +01:00
RaiseNetworkEvent ( response , player . Channel ) ;
2018-11-21 20:58:11 +01:00
}
2021-12-16 23:42:02 +13:00
/// <summary>
/// Execute the provided verb.
/// </summary>
/// <remarks>
/// This will try to call the action delegates and raise the local events for the given verb.
/// </remarks>
public override void ExecuteVerb ( Verb verb , EntityUid user , EntityUid target , bool forced = false )
{
// is this verb actually valid?
if ( verb . Disabled )
{
// Send an informative pop-up message
if ( ! string . IsNullOrWhiteSpace ( verb . Message ) )
2022-12-19 10:41:47 +13:00
_popupSystem . PopupEntity ( verb . Message , user , user ) ;
2021-12-16 23:42:02 +13:00
return ;
}
// first, lets log the verb. Just in case it ends up crashing the server or something.
LogVerb ( verb , user , target , forced ) ;
2022-10-26 14:15:48 +13:00
base . ExecuteVerb ( verb , user , target , forced ) ;
2021-12-16 23:42:02 +13:00
}
public void LogVerb ( Verb verb , EntityUid user , EntityUid target , bool forced )
{
// first get the held item. again.
EntityUid ? holding = null ;
2023-04-07 11:21:12 -07:00
if ( TryComp ( user , out HandsComponent ? hands ) & &
2022-03-17 20:13:31 +13:00
hands . ActiveHandEntity is EntityUid heldEntity )
2021-12-16 23:42:02 +13:00
{
holding = heldEntity ;
}
// if this is a virtual pull, get the held entity
2024-01-14 06:18:47 -04:00
if ( holding ! = null & & TryComp ( holding , out VirtualItemComponent ? pull ) )
2021-12-16 23:42:02 +13:00
holding = pull . BlockingEntity ;
var verbText = $"{verb.Category?.Text} {verb.Text}" . Trim ( ) ;
// lets not frame people, eh?
var executionText = forced ? "was forced to execute" : "executed" ;
if ( holding = = null )
{
2022-05-28 23:41:17 -07:00
_adminLogger . Add ( LogType . Verb , verb . Impact ,
2021-12-16 23:42:02 +13:00
$"{ToPrettyString(user):user} {executionText} the [{verbText:verb}] verb targeting {ToPrettyString(target):target}" ) ;
}
else
{
2022-05-28 23:41:17 -07:00
_adminLogger . Add ( LogType . Verb , verb . Impact ,
2021-12-16 23:42:02 +13:00
$"{ToPrettyString(user):user} {executionText} the [{verbText:verb}] verb targeting {ToPrettyString(target):target} while holding {ToPrettyString(holding.Value):held}" ) ;
}
}
2018-11-21 20:58:11 +01:00
}
}