Improve InteractionSystem range & BUI checks (#27999)

* Improve InteractionSystem range & BUI checks

* Ghost fixes

* AAA

* Fix test

* fix nullable

* revert to broadcast event

* Fixes for eengine PR

* Ah buckle code

* )
This commit is contained in:
Leon Friedrich
2024-05-24 17:03:03 +12:00
committed by GitHub
parent 01e7c9c37e
commit 76e13eed35
18 changed files with 232 additions and 248 deletions

View File

@@ -8,7 +8,7 @@ using Content.Shared.Interaction;
using Content.Shared.Interaction.Events;
using Content.Shared.Popups;
using Content.Shared.Verbs;
using Robust.Shared.Containers;
using Robust.Shared.Utility;
namespace Content.Shared.UserInterface;
@@ -19,15 +19,12 @@ public sealed partial class ActivatableUISystem : EntitySystem
[Dependency] private readonly SharedUserInterfaceSystem _uiSystem = default!;
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
[Dependency] private readonly SharedHandsSystem _hands = default!;
[Dependency] private readonly SharedContainerSystem _container = default!;
[Dependency] private readonly SharedInteractionSystem _interaction = default!;
private readonly List<EntityUid> _toClose = new();
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ActivatableUIComponent, ComponentStartup>(OnStartup);
SubscribeLocalEvent<ActivatableUIComponent, UseInHandEvent>(OnUseInHand);
SubscribeLocalEvent<ActivatableUIComponent, ActivateInWorldEvent>(OnActivate);
SubscribeLocalEvent<ActivatableUIComponent, InteractUsingEvent>(OnInteractUsing);
@@ -37,28 +34,24 @@ public sealed partial class ActivatableUISystem : EntitySystem
SubscribeLocalEvent<ActivatableUIComponent, GetVerbsEvent<ActivationVerb>>(GetActivationVerb);
SubscribeLocalEvent<ActivatableUIComponent, GetVerbsEvent<Verb>>(GetVerb);
// TODO ActivatableUI
// Add UI-user component, and listen for user container changes.
// I.e., should lose a computer UI if a player gets shut into a locker.
SubscribeLocalEvent<ActivatableUIComponent, EntGotInsertedIntoContainerMessage>(OnGotInserted);
SubscribeLocalEvent<ActivatableUIComponent, EntGotRemovedFromContainerMessage>(OnGotRemoved);
SubscribeLocalEvent<BoundUserInterfaceMessageAttempt>(OnBoundInterfaceInteractAttempt);
SubscribeLocalEvent<UserInterfaceComponent, OpenUiActionEvent>(OnActionPerform);
InitializePower();
}
private void OnBoundInterfaceInteractAttempt(BoundUserInterfaceMessageAttempt ev)
private void OnStartup(Entity<ActivatableUIComponent> ent, ref ComponentStartup args)
{
if (!TryComp(ev.Target, out ActivatableUIComponent? comp))
if (ent.Comp.Key == null)
{
Log.Error($"Missing UI Key for entity: {ToPrettyString(ent)}");
return;
}
if (!comp.RequireHands)
return;
if (!TryComp(ev.Actor, out HandsComponent? hands) || hands.Hands.Count == 0)
ev.Cancel();
// TODO BUI
// set interaction range to zero to avoid constant range checks.
//
// if (ent.Comp.InHandsOnly && _uiSystem.TryGetInterfaceData(ent.Owner, ent.Comp.Key, out var data))
// data.InteractionRange = 0;
}
private void OnActionPerform(EntityUid uid, UserInterfaceComponent component, OpenUiActionEvent args)
@@ -77,9 +70,10 @@ public sealed partial class ActivatableUISystem : EntitySystem
args.Verbs.Add(new ActivationVerb
{
// TODO VERBS add "open UI" icon
Act = () => InteractUI(args.User, uid, component),
Text = Loc.GetString(component.VerbText)
Text = Loc.GetString(component.VerbText),
// TODO VERB ICON find a better icon
Icon = new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/VerbIcons/settings.svg.192dpi.png")),
});
}
@@ -90,9 +84,10 @@ public sealed partial class ActivatableUISystem : EntitySystem
args.Verbs.Add(new Verb
{
// TODO VERBS add "open UI" icon
Act = () => InteractUI(args.User, uid, component),
Text = Loc.GetString(component.VerbText)
Text = Loc.GetString(component.VerbText),
// TODO VERB ICON find a better icon
Icon = new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/VerbIcons/settings.svg.192dpi.png")),
});
}
@@ -119,7 +114,7 @@ public sealed partial class ActivatableUISystem : EntitySystem
}
}
return args.CanInteract || component.AllowSpectator && HasComp<GhostComponent>(args.User);
return args.CanInteract || HasComp<GhostComponent>(args.User) && !component.BlockSpectators;
}
private void OnUseInHand(EntityUid uid, ActivatableUIComponent component, UseInHandEvent args)
@@ -191,7 +186,7 @@ public sealed partial class ActivatableUISystem : EntitySystem
return true;
}
if (!_blockerSystem.CanInteract(user, uiEntity) && (!aui.AllowSpectator || !HasComp<GhostComponent>(user)))
if (!_blockerSystem.CanInteract(user, uiEntity) && (!HasComp<GhostComponent>(user) || aui.BlockSpectators))
return false;
if (aui.RequireHands)
@@ -286,47 +281,4 @@ public sealed partial class ActivatableUISystem : EntitySystem
if (ent.Comp.RequireHands && ent.Comp.InHandsOnly)
CloseAll(ent, ent);
}
private void OnGotInserted(Entity<ActivatableUIComponent> ent, ref EntGotInsertedIntoContainerMessage args)
{
CheckAccess((ent, ent));
}
private void OnGotRemoved(Entity<ActivatableUIComponent> ent, ref EntGotRemovedFromContainerMessage args)
{
CheckAccess((ent, ent));
}
public void CheckAccess(Entity<ActivatableUIComponent?> ent)
{
if (!Resolve(ent, ref ent.Comp))
return;
if (ent.Comp.Key == null)
{
Log.Error($"Encountered null key in activatable ui on entity {ToPrettyString(ent)}");
return;
}
foreach (var user in _uiSystem.GetActors(ent.Owner, ent.Comp.Key))
{
if (!_container.IsInSameOrParentContainer(user, ent)
&& !_interaction.CanAccessViaStorage(user, ent))
{
_toClose.Add(user);
continue;
}
if (!_interaction.InRangeUnobstructed(user, ent))
_toClose.Add(user);
}
foreach (var user in _toClose)
{
_uiSystem.CloseUi(ent.Owner, ent.Comp.Key, user);
}
_toClose.Clear();
}
}