Enable verbs for items in storage and prevent orphaned nested UIs (#5512)

This commit is contained in:
Leon Friedrich
2021-11-29 12:25:22 +13:00
committed by GitHub
parent 3601416f72
commit 22ee9f5e83
9 changed files with 190 additions and 86 deletions

View File

@@ -5,9 +5,7 @@ using Content.Shared.Hands.Components;
using Robust.Shared.Containers;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization;
using Robust.Shared.IoC;
using Content.Shared.Interaction;
using System.Collections.Immutable;
namespace Content.Shared.Verbs
{
@@ -17,10 +15,18 @@ namespace Content.Shared.Verbs
public readonly EntityUid EntityUid;
public readonly VerbType Type;
public RequestServerVerbsEvent(EntityUid entityUid, VerbType type)
/// <summary>
/// If the target item is inside of some storage (e.g., backpack), this is the entity that owns that item
/// slot. Needed for validating that the user can access the target item.
/// </summary>
public readonly EntityUid? SlotOwner;
public RequestServerVerbsEvent(EntityUid entityUid, VerbType type, EntityUid? slotOwner = null)
{
EntityUid = entityUid;
Type = type;
SlotOwner = slotOwner;
}
}
@@ -75,7 +81,9 @@ namespace Content.Shared.Verbs
/// </remarks>
public class GetInteractionVerbsEvent : GetVerbsEvent
{
public GetInteractionVerbsEvent(IEntity user, IEntity target, bool force=false) : base(user, target, force) { }
public GetInteractionVerbsEvent(IEntity user, IEntity target, IEntity? @using, SharedHandsComponent? hands,
bool canInteract, bool canAccess) : base(user, target, @using, hands, canInteract, canAccess) { }
}
/// <summary>
@@ -89,7 +97,8 @@ namespace Content.Shared.Verbs
/// </remarks>
public class GetActivationVerbsEvent : GetVerbsEvent
{
public GetActivationVerbsEvent(IEntity user, IEntity target, bool force=false) : base(user, target, force) { }
public GetActivationVerbsEvent(IEntity user, IEntity target, IEntity? @using, SharedHandsComponent? hands,
bool canInteract, bool canAccess) : base(user, target, @using, hands, canInteract, canAccess) { }
}
/// <summary>
@@ -101,7 +110,8 @@ namespace Content.Shared.Verbs
/// </remarks>
public class GetAlternativeVerbsEvent : GetVerbsEvent
{
public GetAlternativeVerbsEvent(IEntity user, IEntity target, bool force=false) : base(user, target, force) { }
public GetAlternativeVerbsEvent(IEntity user, IEntity target, IEntity? @using, SharedHandsComponent? hands,
bool canInteract, bool canAccess) : base(user, target, @using, hands, canInteract, canAccess) { }
}
/// <summary>
@@ -113,7 +123,8 @@ namespace Content.Shared.Verbs
/// </remarks>
public class GetOtherVerbsEvent : GetVerbsEvent
{
public GetOtherVerbsEvent(IEntity user, IEntity target, bool force=false) : base(user, target, force) { }
public GetOtherVerbsEvent(IEntity user, IEntity target, IEntity? @using, SharedHandsComponent? hands,
bool canInteract, bool canAccess) : base(user, target, @using, hands, canInteract, canAccess) { }
}
/// <summary>
@@ -124,7 +135,7 @@ namespace Content.Shared.Verbs
/// <summary>
/// Event output. Set of verbs that can be executed.
/// </summary>
public SortedSet<Verb> Verbs = new();
public readonly SortedSet<Verb> Verbs = new();
/// <summary>
/// Can the user physically access the target?
@@ -133,17 +144,17 @@ namespace Content.Shared.Verbs
/// This is a combination of <see cref="ContainerHelpers.IsInSameOrParentContainer"/> and
/// <see cref="SharedInteractionSystem.InRangeUnobstructed"/>.
/// </remarks>
public bool CanAccess;
public readonly bool CanAccess = false;
/// <summary>
/// The entity being targeted for the verb.
/// </summary>
public IEntity Target;
public readonly IEntity Target;
/// <summary>
/// The entity that will be "performing" the verb.
/// </summary>
public IEntity User;
public readonly IEntity User;
/// <summary>
/// Can the user physically interact?
@@ -153,7 +164,7 @@ namespace Content.Shared.Verbs
/// to check this, it prevents it from having to be repeatedly called by each individual system that might
/// contribute a verb.
/// </remarks>
public bool CanInteract;
public readonly bool CanInteract;
/// <summary>
/// The User's hand component.
@@ -161,7 +172,7 @@ namespace Content.Shared.Verbs
/// <remarks>
/// This may be null if the user has no hands.
/// </remarks>
public SharedHandsComponent? Hands;
public readonly SharedHandsComponent? Hands;
/// <summary>
/// The entity currently being held by the active hand.
@@ -170,34 +181,21 @@ namespace Content.Shared.Verbs
/// This is only ever not null when <see cref="ActionBlockerSystem.CanUse(EntityUid)"/> is true and the user
/// has hands.
/// </remarks>
public IEntity? Using;
public readonly IEntity? Using;
public GetVerbsEvent(IEntity user, IEntity target, bool force=false)
// for eventual removal of IEntity.
public EntityUid UserUid => User.Uid;
public EntityUid TargetUid => Target.Uid;
public EntityUid? UsingUid => Using?.Uid;
public GetVerbsEvent(IEntity user, IEntity target, IEntity? @using, SharedHandsComponent? hands, bool canInteract, bool canAccess)
{
User = user;
Target = target;
CanAccess = force || (Target == User) || user.IsInSameOrParentContainer(target) &&
EntitySystem.Get<SharedInteractionSystem>().InRangeUnobstructed(user, target, ignoreInsideBlocker: true);
// A large number of verbs need to check action blockers. Instead of repeatedly having each system individually
// call ActionBlocker checks, just cache it for the verb request.
var actionBlockerSystem = EntitySystem.Get<ActionBlockerSystem>();
CanInteract = force || actionBlockerSystem.CanInteract(user.Uid);
if (!user.TryGetComponent(out Hands) ||
!actionBlockerSystem.CanUse(user.Uid))
return;
Hands.TryGetActiveHeldEntity(out Using);
// Check whether the "Held" entity is a virtual pull entity. If yes, set that as the entity being "Used".
// This allows you to do things like buckle a dragged person onto a surgery table, without click-dragging
// their sprite.
if (Using != null && Using.TryGetComponent<HandVirtualItemComponent>(out var pull))
{
Using = IoCManager.Resolve<IEntityManager>().GetEntity(pull.BlockingEntity);
}
Using = @using;
Hands = hands;
CanAccess = canAccess;
CanInteract = canInteract;
}
}
}