diff --git a/Content.Client/DragDrop/DragDropSystem.cs b/Content.Client/DragDrop/DragDropSystem.cs
index 7c772ff698..1bf2dac727 100644
--- a/Content.Client/DragDrop/DragDropSystem.cs
+++ b/Content.Client/DragDrop/DragDropSystem.cs
@@ -5,6 +5,7 @@ using Content.Client.Viewport;
using Content.Shared.ActionBlocker;
using Content.Shared.DragDrop;
using Content.Shared.Interaction;
+using Content.Shared.Interaction.Events;
using Content.Shared.Interaction.Helpers;
using Content.Shared.Popups;
using JetBrains.Annotations;
@@ -428,11 +429,18 @@ namespace Content.Client.DragDrop
/// null if the target doesn't support IDragDropOn
private bool? ValidDragDrop(DragDropEvent eventArgs)
{
- if (!_actionBlockerSystem.CanInteract(eventArgs.User))
+ if (!_actionBlockerSystem.CanInteract(eventArgs.User, eventArgs.Target))
{
return false;
}
+ // CanInteract() doesn't support checking a second "target" entity.
+ // Doing so manually:
+ var ev = new GettingInteractedWithAttemptEvent(eventArgs.User, eventArgs.Dragged);
+ RaiseLocalEvent(eventArgs.Dragged, ev);
+ if (ev.Cancelled)
+ return false;
+
var valid = CheckDragDropOn(eventArgs);
foreach (var comp in EntityManager.GetComponents(eventArgs.Target))
diff --git a/Content.Server/AME/Components/AMEControllerComponent.cs b/Content.Server/AME/Components/AMEControllerComponent.cs
index 7e8b5035c0..2b567848e5 100644
--- a/Content.Server/AME/Components/AMEControllerComponent.cs
+++ b/Content.Server/AME/Components/AMEControllerComponent.cs
@@ -172,11 +172,6 @@ namespace Content.Server.AME.Components
if (playerEntity == default)
return false;
- var actionBlocker = EntitySystem.Get();
-
- //Check if player can interact in their current state
- if (!actionBlocker.CanInteract(playerEntity) || !actionBlocker.CanUse(playerEntity))
- return false;
//Check if device is powered
if (needsPower && !Powered)
return false;
diff --git a/Content.Server/Actions/Spells/GiveItemSpell.cs b/Content.Server/Actions/Spells/GiveItemSpell.cs
index cd916e7a90..58fa0d8bf0 100644
--- a/Content.Server/Actions/Spells/GiveItemSpell.cs
+++ b/Content.Server/Actions/Spells/GiveItemSpell.cs
@@ -45,7 +45,7 @@ namespace Content.Server.Actions.Spells
return;
}
- if (!EntitySystem.Get().CanInteract(caster)) return;
+ if (!EntitySystem.Get().CanInteract(caster, null)) return;
// TODO: Nix when we get EntityPrototype serializers
if (!IoCManager.Resolve().HasIndex(ItemProto))
diff --git a/Content.Server/Alert/Click/StopBeingPulled.cs b/Content.Server/Alert/Click/StopBeingPulled.cs
index 4046b324bd..56bcd0ce3d 100644
--- a/Content.Server/Alert/Click/StopBeingPulled.cs
+++ b/Content.Server/Alert/Click/StopBeingPulled.cs
@@ -18,7 +18,7 @@ namespace Content.Server.Alert.Click
{
public void AlertClicked(EntityUid player)
{
- if (!EntitySystem.Get().CanInteract(player))
+ if (!EntitySystem.Get().CanInteract(player, null))
return;
if (IoCManager.Resolve().TryGetComponent(player, out var playerPullable))
diff --git a/Content.Server/Arcade/Components/BlockGameArcadeComponent.cs b/Content.Server/Arcade/Components/BlockGameArcadeComponent.cs
index c6f35c94fe..4593aa6240 100644
--- a/Content.Server/Arcade/Components/BlockGameArcadeComponent.cs
+++ b/Content.Server/Arcade/Components/BlockGameArcadeComponent.cs
@@ -49,9 +49,6 @@ namespace Content.Server.Arcade.Components
if(!Powered || !IoCManager.Resolve().TryGetComponent(eventArgs.User, out ActorComponent? actor))
return;
- if(!EntitySystem.Get().CanInteract(eventArgs.User))
- return;
-
UserInterface?.Toggle(actor.PlayerSession);
if (UserInterface?.SessionHasOpen(actor.PlayerSession) == true)
{
@@ -130,13 +127,6 @@ namespace Content.Server.Arcade.Components
case BlockGameMessages.BlockGamePlayerActionMessage playerActionMessage:
if (obj.Session != _player) break;
- // TODO: Should this check if the Owner can interact...?
- if (!EntitySystem.Get().CanInteract(Owner))
- {
- DeactivePlayer(obj.Session);
- break;
- }
-
if (playerActionMessage.PlayerAction == BlockGamePlayerAction.NewGame)
{
if(_game?.Started == true) _game = new BlockGame(this);
diff --git a/Content.Server/Arcade/Components/SpaceVillainArcadeComponent.cs b/Content.Server/Arcade/Components/SpaceVillainArcadeComponent.cs
index ab2d174d3c..07d3ead6a2 100644
--- a/Content.Server/Arcade/Components/SpaceVillainArcadeComponent.cs
+++ b/Content.Server/Arcade/Components/SpaceVillainArcadeComponent.cs
@@ -77,9 +77,6 @@ namespace Content.Server.Arcade.Components
if (!Powered || !IoCManager.Resolve().TryGetComponent(eventArgs.User, out ActorComponent? actor))
return;
- if (!EntitySystem.Get().CanInteract(eventArgs.User))
- return;
-
_game ??= new SpaceVillainGame(this);
if (_entityManager.TryGetComponent(Owner, out var wiresComponent) && wiresComponent.IsPanelOpen)
diff --git a/Content.Server/Atmos/Components/GasTankComponent.cs b/Content.Server/Atmos/Components/GasTankComponent.cs
index 1a8c10e7aa..aa6c046d8c 100644
--- a/Content.Server/Atmos/Components/GasTankComponent.cs
+++ b/Content.Server/Atmos/Components/GasTankComponent.cs
@@ -207,11 +207,6 @@ namespace Content.Server.Atmos.Components
internal void ToggleInternals()
{
- var user = GetInternalsComponent()?.Owner;
-
- if (user == null || !EntitySystem.Get().CanUse(user.Value))
- return;
-
if (IsConnected)
{
DisconnectFromInternals();
@@ -321,6 +316,9 @@ namespace Content.Server.Atmos.Components
{
public bool DoToggleAction(ToggleItemActionEventArgs args)
{
+ if (!EntitySystem.Get().CanInteract(args.Performer, args.Item))
+ return false;
+
if (!IoCManager.Resolve().TryGetComponent(args.Item, out var gasTankComponent)) return false;
// no change
if (gasTankComponent.IsConnected == args.ToggledOn) return false;
diff --git a/Content.Server/Atmos/EntitySystems/FlammableSystem.cs b/Content.Server/Atmos/EntitySystems/FlammableSystem.cs
index 8262946b8a..d657b0d081 100644
--- a/Content.Server/Atmos/EntitySystems/FlammableSystem.cs
+++ b/Content.Server/Atmos/EntitySystems/FlammableSystem.cs
@@ -181,7 +181,7 @@ namespace Content.Server.Atmos.EntitySystems
if (!Resolve(uid, ref flammable))
return;
- if (!flammable.OnFire || !_actionBlockerSystem.CanInteract(flammable.Owner) || flammable.Resisting)
+ if (!flammable.OnFire || !_actionBlockerSystem.CanInteract(flammable.Owner, null) || flammable.Resisting)
return;
flammable.Resisting = true;
diff --git a/Content.Server/Atmos/Piping/Binary/EntitySystems/GasValveSystem.cs b/Content.Server/Atmos/Piping/Binary/EntitySystems/GasValveSystem.cs
index dd31411b1f..cec4cdab22 100644
--- a/Content.Server/Atmos/Piping/Binary/EntitySystems/GasValveSystem.cs
+++ b/Content.Server/Atmos/Piping/Binary/EntitySystems/GasValveSystem.cs
@@ -18,10 +18,8 @@ using Robust.Shared.Player;
namespace Content.Server.Atmos.Piping.Binary.EntitySystems
{
[UsedImplicitly]
- public class GasValveSystem : EntitySystem
+ public sealed class GasValveSystem : EntitySystem
{
- [Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!;
-
public override void Initialize()
{
base.Initialize();
@@ -51,11 +49,8 @@ namespace Content.Server.Atmos.Piping.Binary.EntitySystems
private void OnActivate(EntityUid uid, GasValveComponent component, ActivateInWorldEvent args)
{
- if (args.User.InRangeUnobstructed(args.Target) && _actionBlockerSystem.CanInteract(args.User))
- {
- Toggle(uid, component);
- SoundSystem.Play(Filter.Pvs(component.Owner), component.ValveSound.GetSound(), component.Owner, AudioHelpers.WithVariation(0.25f));
- }
+ Toggle(uid, component);
+ SoundSystem.Play(Filter.Pvs(component.Owner), component.ValveSound.GetSound(), component.Owner, AudioHelpers.WithVariation(0.25f));
}
public void Set(EntityUid uid, GasValveComponent component, bool value)
diff --git a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCanisterSystem.cs b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCanisterSystem.cs
index 7f0352547f..87144b4c55 100644
--- a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCanisterSystem.cs
+++ b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCanisterSystem.cs
@@ -25,11 +25,10 @@ using Robust.Shared.Players;
namespace Content.Server.Atmos.Piping.Unary.EntitySystems
{
[UsedImplicitly]
- public class GasCanisterSystem : EntitySystem
+ public sealed class GasCanisterSystem : EntitySystem
{
[Dependency] private readonly UserInterfaceSystem _userInterfaceSystem = default!;
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
- [Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!;
[Dependency] private readonly AdminLogSystem _adminLogSystem = default!;
public override void Initialize()
diff --git a/Content.Server/Botany/Components/PlantHolderComponent.cs b/Content.Server/Botany/Components/PlantHolderComponent.cs
index 720a545577..6443aefd77 100644
--- a/Content.Server/Botany/Components/PlantHolderComponent.cs
+++ b/Content.Server/Botany/Components/PlantHolderComponent.cs
@@ -422,7 +422,7 @@ namespace Content.Server.Botany.Components
public bool DoHarvest(EntityUid user)
{
- if (Seed == null || _entMan.Deleted(user) || !EntitySystem.Get().CanInteract(user))
+ if (Seed == null || _entMan.Deleted(user))
return false;
var botanySystem = EntitySystem.Get();
@@ -657,7 +657,7 @@ namespace Content.Server.Botany.Components
var user = eventArgs.User;
var usingItem = eventArgs.Using;
- if ((!_entMan.EntityExists(usingItem) ? EntityLifeStage.Deleted : _entMan.GetComponent(usingItem).EntityLifeStage) >= EntityLifeStage.Deleted || !EntitySystem.Get().CanInteract(user))
+ if ((!_entMan.EntityExists(usingItem) ? EntityLifeStage.Deleted : _entMan.GetComponent(usingItem).EntityLifeStage) >= EntityLifeStage.Deleted)
return false;
var botanySystem = EntitySystem.Get();
diff --git a/Content.Server/Buckle/Components/BuckleComponent.cs b/Content.Server/Buckle/Components/BuckleComponent.cs
index 02169ab846..6f720460fe 100644
--- a/Content.Server/Buckle/Components/BuckleComponent.cs
+++ b/Content.Server/Buckle/Components/BuckleComponent.cs
@@ -138,12 +138,6 @@ namespace Content.Server.Buckle.Components
return false;
}
- if (!EntitySystem.Get().CanInteract(user))
- {
- popupSystem.PopupEntity(Loc.GetString("buckle-component-cannot-do-that-message"), user, Filter.Entities(user));
- return false;
- }
-
if (!_entMan.TryGetComponent(to, out strap))
{
return false;
@@ -295,13 +289,6 @@ namespace Content.Server.Buckle.Components
return false;
}
- if (!EntitySystem.Get().CanInteract(user))
- {
- var popupSystem = EntitySystem.Get();
- popupSystem.PopupEntity(Loc.GetString("buckle-component-cannot-do-that-message"), user, Filter.Entities(user));
- return false;
- }
-
if (!user.InRangeUnobstructed(oldBuckledTo.Owner, Range, popup: true))
{
return false;
diff --git a/Content.Server/Chemistry/Components/ChemMasterComponent.cs b/Content.Server/Chemistry/Components/ChemMasterComponent.cs
index 0484479817..e772cf4514 100644
--- a/Content.Server/Chemistry/Components/ChemMasterComponent.cs
+++ b/Content.Server/Chemistry/Components/ChemMasterComponent.cs
@@ -162,11 +162,6 @@ namespace Content.Server.Chemistry.Components
if (playerEntity == default)
return false;
- var actionBlocker = EntitySystem.Get();
-
- //Check if player can interact in their current state
- if (!actionBlocker.CanInteract(playerEntity) || !actionBlocker.CanUse(playerEntity))
- return false;
//Check if device is powered
if (needsPower && !Powered)
return false;
diff --git a/Content.Server/Chemistry/Components/ReagentDispenserComponent.cs b/Content.Server/Chemistry/Components/ReagentDispenserComponent.cs
index ac9b846da5..bb1538cd6e 100644
--- a/Content.Server/Chemistry/Components/ReagentDispenserComponent.cs
+++ b/Content.Server/Chemistry/Components/ReagentDispenserComponent.cs
@@ -207,11 +207,6 @@ namespace Content.Server.Chemistry.Components
if (playerEntity == null)
return false;
- var actionBlocker = EntitySystem.Get();
-
- //Check if player can interact in their current state
- if (!actionBlocker.CanInteract(playerEntity.Value) || !actionBlocker.CanUse(playerEntity.Value))
- return false;
//Check if device is powered
if (needsPower && !Powered)
return false;
diff --git a/Content.Server/Climbing/Components/ClimbableComponent.cs b/Content.Server/Climbing/Components/ClimbableComponent.cs
index df8a23d782..a5a6f6397a 100644
--- a/Content.Server/Climbing/Components/ClimbableComponent.cs
+++ b/Content.Server/Climbing/Components/ClimbableComponent.cs
@@ -6,6 +6,7 @@ using Content.Shared.Body.Components;
using Content.Shared.Body.Part;
using Content.Shared.Climbing;
using Content.Shared.DragDrop;
+using Content.Shared.Interaction.Events;
using Content.Shared.Interaction.Helpers;
using Content.Shared.Popups;
using Robust.Shared.GameObjects;
@@ -70,7 +71,7 @@ namespace Content.Server.Climbing.Components
///
private bool CanVault(EntityUid user, EntityUid target, out string reason)
{
- if (!EntitySystem.Get().CanInteract(user))
+ if (!EntitySystem.Get().CanInteract(user, target))
{
reason = Loc.GetString("comp-climbable-cant-interact");
return false;
@@ -110,7 +111,17 @@ namespace Content.Server.Climbing.Components
///
private bool CanVault(EntityUid user, EntityUid dragged, EntityUid target, out string reason)
{
- if (!EntitySystem.Get().CanInteract(user))
+ if (!EntitySystem.Get().CanInteract(user, dragged))
+ {
+ reason = Loc.GetString("comp-climbable-cant-interact");
+ return false;
+ }
+
+ // CanInteract() doesn't support checking a second "target" entity.
+ // Doing so manually:
+ var ev = new GettingInteractedWithAttemptEvent(user, target);
+ _entities.EventBus.RaiseLocalEvent(target, ev);
+ if (ev.Cancelled)
{
reason = Loc.GetString("comp-climbable-cant-interact");
return false;
diff --git a/Content.Server/Construction/ConstructionSystem.Initial.cs b/Content.Server/Construction/ConstructionSystem.Initial.cs
index 093f132c91..00af70c522 100644
--- a/Content.Server/Construction/ConstructionSystem.Initial.cs
+++ b/Content.Server/Construction/ConstructionSystem.Initial.cs
@@ -301,7 +301,7 @@ namespace Content.Server.Construction
var pathFind = constructionGraph.Path(startNode.Name, targetNode.Name);
if (args.SenderSession.AttachedEntity is not {Valid: true} user ||
- !Get().CanInteract(user)) return;
+ !Get().CanInteract(user, null)) return;
if (!EntityManager.TryGetComponent(user, out HandsComponent? hands)) return;
@@ -399,7 +399,7 @@ namespace Content.Server.Construction
_beingBuilt[args.SenderSession].Remove(ev.Ack);
}
- if (!Get().CanInteract(user)
+ if (!Get().CanInteract(user, null)
|| !EntityManager.TryGetComponent(user, out HandsComponent? hands) || hands.GetActiveHandItem == null
|| !user.InRangeUnobstructed(ev.Location, ignoreInsideBlocker:constructionPrototype.CanBuildInImpassable))
{
diff --git a/Content.Server/Cuffs/Components/HandcuffComponent.cs b/Content.Server/Cuffs/Components/HandcuffComponent.cs
index dbc07472e9..51637946d6 100644
--- a/Content.Server/Cuffs/Components/HandcuffComponent.cs
+++ b/Content.Server/Cuffs/Components/HandcuffComponent.cs
@@ -149,7 +149,6 @@ namespace Content.Server.Cuffs.Components
if (_cuffing) return true;
if (eventArgs.Target is not {Valid: true} target ||
- !EntitySystem.Get().CanUse(eventArgs.User) ||
!_entities.TryGetComponent(eventArgs.Target.Value, out var cuffed))
{
return false;
diff --git a/Content.Server/Cuffs/CuffableSystem.cs b/Content.Server/Cuffs/CuffableSystem.cs
index 4ad2953664..4953e09747 100644
--- a/Content.Server/Cuffs/CuffableSystem.cs
+++ b/Content.Server/Cuffs/CuffableSystem.cs
@@ -83,7 +83,7 @@ namespace Content.Server.Cuffs
else
{
// Check if the user can interact.
- if (!_actionBlockerSystem.CanInteract(args.User))
+ if (!_actionBlockerSystem.CanInteract(args.User, args.Target))
{
args.Cancel();
}
diff --git a/Content.Server/Disposal/Tube/Components/DisposalRouterComponent.cs b/Content.Server/Disposal/Tube/Components/DisposalRouterComponent.cs
index 88fd0b8166..5fc44224d7 100644
--- a/Content.Server/Disposal/Tube/Components/DisposalRouterComponent.cs
+++ b/Content.Server/Disposal/Tube/Components/DisposalRouterComponent.cs
@@ -81,7 +81,7 @@ namespace Content.Server.Disposal.Tube.Components
var msg = (UiActionMessage) obj.Message;
- if (!PlayerCanUseDisposalTagger(obj.Session))
+ if (!Anchored)
return;
//Check for correct message and ignore maleformed strings
@@ -96,29 +96,6 @@ namespace Content.Server.Disposal.Tube.Components
}
}
- ///
- /// Checks whether the player entity is able to use the configuration interface of the pipe tagger.
- ///
- /// The player session.
- /// Returns true if the entity can use the configuration interface, and false if it cannot.
- private bool PlayerCanUseDisposalTagger(IPlayerSession session)
- {
- //Need player entity to check if they are still able to use the configuration interface
- if (session.AttachedEntity is not {} attached)
- return false;
- if (!Anchored)
- return false;
-
- var actionBlocker = EntitySystem.Get();
- var groupController = IoCManager.Resolve();
- //Check if player can interact in their current state
- if (!groupController.CanAdminMenu(session) && (!actionBlocker.CanInteract(attached) || !actionBlocker.CanUse(attached)))
- return false;
-
- return true;
- }
-
-
///
/// Gets component data to be used to update the user interface client-side.
///
diff --git a/Content.Server/Disposal/Tube/Components/DisposalTaggerComponent.cs b/Content.Server/Disposal/Tube/Components/DisposalTaggerComponent.cs
index 8dbc160e4c..8f616217a3 100644
--- a/Content.Server/Disposal/Tube/Components/DisposalTaggerComponent.cs
+++ b/Content.Server/Disposal/Tube/Components/DisposalTaggerComponent.cs
@@ -67,7 +67,7 @@ namespace Content.Server.Disposal.Tube.Components
{
var msg = (UiActionMessage) obj.Message;
- if (!PlayerCanUseDisposalTagger(obj.Session))
+ if (!Anchored)
return;
//Check for correct message and ignore maleformed strings
@@ -78,28 +78,6 @@ namespace Content.Server.Disposal.Tube.Components
}
}
- ///
- /// Checks whether the player entity is able to use the configuration interface of the pipe tagger.
- ///
- /// The player entity.
- /// Returns true if the entity can use the configuration interface, and false if it cannot.
- private bool PlayerCanUseDisposalTagger(IPlayerSession session)
- {
- //Need player entity to check if they are still able to use the configuration interface
- if (session.AttachedEntity is not {} attached)
- return false;
- if (!Anchored)
- return false;
-
- var actionBlocker = EntitySystem.Get();
- var groupController = IoCManager.Resolve();
- //Check if player can interact in their current state
- if (!groupController.CanAdminMenu(session) && (!actionBlocker.CanInteract(attached) || !actionBlocker.CanUse(attached)))
- return false;
-
- return true;
- }
-
///
/// Gets component data to be used to update the user interface client-side.
///
diff --git a/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs b/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs
index 3a305477cc..e85253ae0d 100644
--- a/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs
+++ b/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs
@@ -184,11 +184,6 @@ namespace Content.Server.Disposal.Unit.EntitySystems
return;
}
- if (!_actionBlockerSystem.CanInteract(player) || !_actionBlockerSystem.CanUse(player))
- {
- return;
- }
-
switch (args.Button)
{
case SharedDisposalUnitComponent.UiButton.Eject:
@@ -241,11 +236,7 @@ namespace Content.Server.Disposal.Unit.EntitySystems
}
args.Handled = true;
-
- if (IsValidInteraction(args))
- {
- component.Owner.GetUIOrNull(SharedDisposalUnitComponent.DisposalUnitUiKey.Key)?.Open(actor.PlayerSession);
- }
+ component.Owner.GetUIOrNull(SharedDisposalUnitComponent.DisposalUnitUiKey.Key)?.Open(actor.PlayerSession);
}
private void HandleAfterInteractUsing(EntityUid uid, DisposalUnitComponent component, AfterInteractUsingEvent args)
@@ -439,30 +430,6 @@ namespace Content.Server.Disposal.Unit.EntitySystems
return state == SharedDisposalUnitComponent.PressureState.Ready && component.RecentlyEjected.Count == 0;
}
- private bool IsValidInteraction(ITargetedInteractEventArgs eventArgs)
- {
- if (!Get().CanInteract(eventArgs.User))
- {
- eventArgs.Target.PopupMessage(eventArgs.User, Loc.GetString("ui-disposal-unit-is-valid-interaction-cannot=interact"));
- return false;
- }
-
- if (eventArgs.User.IsInContainer())
- {
- eventArgs.Target.PopupMessage(eventArgs.User, Loc.GetString("ui-disposal-unit-is-valid-interaction-cannot-reach"));
- return false;
- }
- // This popup message doesn't appear on clicks, even when code was seperate. Unsure why.
-
- if (!EntityManager.HasComponent(eventArgs.User))
- {
- eventArgs.Target.PopupMessage(eventArgs.User, Loc.GetString("ui-disposal-unit-is-valid-interaction-no-hands"));
- return false;
- }
-
- return true;
- }
-
public bool TryInsert(EntityUid unitId, EntityUid toInsertId, EntityUid userId, DisposalUnitComponent? unit = null)
{
if (!Resolve(unitId, ref unit))
diff --git a/Content.Server/Extinguisher/FireExtinguisherSystem.cs b/Content.Server/Extinguisher/FireExtinguisherSystem.cs
index a76a72e7bd..f3c463daad 100644
--- a/Content.Server/Extinguisher/FireExtinguisherSystem.cs
+++ b/Content.Server/Extinguisher/FireExtinguisherSystem.cs
@@ -19,7 +19,6 @@ namespace Content.Server.Extinguisher;
public class FireExtinguisherSystem : EntitySystem
{
- [Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!;
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
@@ -145,9 +144,6 @@ public class FireExtinguisherSystem : EntitySystem
if (!Resolve(uid, ref extinguisher))
return;
- if (!_actionBlockerSystem.CanInteract(user) || !extinguisher.HasSafety)
- return;
-
extinguisher.Safety = !extinguisher.Safety;
SoundSystem.Play(Filter.Pvs(uid), extinguisher.SafetySound.GetSound(), uid,
AudioHelpers.WithVariation(0.125f).WithVolume(-4f));
diff --git a/Content.Server/Interaction/InteractionSystem.cs b/Content.Server/Interaction/InteractionSystem.cs
index dbb6cb80cc..34f752d893 100644
--- a/Content.Server/Interaction/InteractionSystem.cs
+++ b/Content.Server/Interaction/InteractionSystem.cs
@@ -100,10 +100,10 @@ namespace Content.Server.Interaction
return;
}
- if (!_actionBlockerSystem.CanInteract(userEntity.Value))
+ if (Deleted(msg.Dropped) || Deleted(msg.Target))
return;
- if (Deleted(msg.Dropped) || Deleted(msg.Target))
+ if (!_actionBlockerSystem.CanInteract(userEntity.Value, msg.Target))
return;
var interactionArgs = new DragDropEvent(userEntity.Value, msg.DropLocation, msg.Dropped, msg.Target);
@@ -232,13 +232,11 @@ namespace Content.Server.Interaction
///
/// Uses an empty hand on an entity
/// Finds components with the InteractHand interface and calls their function
- /// NOTE: Does not have an InRangeUnobstructed check
+ /// NOTE: Does not have any range or can-interact checks. These should all have been done before this function is called.
///
- public override void InteractHand(EntityUid user, EntityUid target, bool checkActionBlocker = true)
+ public override void InteractHand(EntityUid user, EntityUid target)
{
// TODO PREDICTION move server-side interaction logic into the shared system for interaction prediction.
- if (checkActionBlocker && !_actionBlockerSystem.CanInteract(user))
- return;
// all interactions should only happen when in range / unobstructed, so no range check is needed
var message = new InteractHandEvent(user, target);
@@ -260,18 +258,26 @@ namespace Content.Server.Interaction
}
// Else we run Activate.
- InteractionActivate(user, target);
+ InteractionActivate(user, target,
+ checkCanInteract: false,
+ checkUseDelay: true,
+ checkAccess: false);
}
///
/// Will have two behaviors, either "uses" the used entity at range on the target entity if it is capable of accepting that action
/// Or it will use the used entity itself on the position clicked, regardless of what was there
///
- public override async Task InteractUsingRanged(EntityUid user, EntityUid used, EntityUid? target, EntityCoordinates clickLocation, bool inRangeUnobstructed)
+ public override void InteractUsingRanged(
+ EntityUid user,
+ EntityUid used,
+ EntityUid? target,
+ EntityCoordinates clickLocation,
+ bool inRangeUnobstructed)
{
// TODO PREDICTION move server-side interaction logic into the shared system for interaction prediction.
- if (InteractDoBefore(user, used, target, clickLocation, inRangeUnobstructed))
- return true;
+ if (RangedInteractDoBefore(user, used, target, clickLocation, inRangeUnobstructed))
+ return;
if (target != null)
{
@@ -279,10 +285,10 @@ namespace Content.Server.Interaction
RaiseLocalEvent(target.Value, rangedMsg);
if (rangedMsg.Handled)
- return true;
+ return;
}
- return await InteractDoAfter(user, used, target, clickLocation, inRangeUnobstructed);
+ InteractDoAfter(user, used, target, clickLocation, inRangeUnobstructed);
}
public override void DoAttack(EntityUid user, EntityCoordinates coordinates, bool wideAttack, EntityUid? target = null)
diff --git a/Content.Server/Labels/Label/HandLabelerSystem.cs b/Content.Server/Labels/Label/HandLabelerSystem.cs
index 0288bbad03..4afb84f16e 100644
--- a/Content.Server/Labels/Label/HandLabelerSystem.cs
+++ b/Content.Server/Labels/Label/HandLabelerSystem.cs
@@ -79,21 +79,8 @@ namespace Content.Server.Labels
args.Handled = true;
}
- private bool CheckInteract(ICommonSession session)
- {
- if (session.AttachedEntity is not {Valid: true } uid
- || !Get().CanInteract(uid)
- || !Get().CanUse(uid))
- return false;
-
- return true;
- }
-
private void OnHandLabelerLabelChanged(EntityUid uid, HandLabelerComponent handLabeler, HandLabelerLabelChangedMessage args)
{
- if (!CheckInteract(args.Session))
- return;
-
handLabeler.AssignedLabel = args.Label.Trim().Substring(0, Math.Min(handLabeler.MaxLabelChars, args.Label.Length));
DirtyUI(uid, handLabeler);
}
diff --git a/Content.Server/Light/Components/HandheldLightComponent.cs b/Content.Server/Light/Components/HandheldLightComponent.cs
index 7f84497f66..a24dba0fd2 100644
--- a/Content.Server/Light/Components/HandheldLightComponent.cs
+++ b/Content.Server/Light/Components/HandheldLightComponent.cs
@@ -1,6 +1,7 @@
using System.Threading.Tasks;
using Content.Server.Clothing.Components;
using Content.Server.Light.EntitySystems;
+using Content.Shared.ActionBlocker;
using Content.Shared.Actions.Behaviors.Item;
using Content.Shared.Examine;
using Content.Shared.Interaction;
@@ -50,10 +51,11 @@ namespace Content.Server.Light.Components
[UsedImplicitly]
[DataDefinition]
- public class ToggleLightAction : IToggleItemAction
+ public sealed class ToggleLightAction : IToggleItemAction
{
public bool DoToggleAction(ToggleItemActionEventArgs args)
{
+ if (!EntitySystem.Get().CanInteract(args.Performer, args.Item)) return false;
if (!IoCManager.Resolve().TryGetComponent(args.Item, out var lightComponent)) return false;
if (lightComponent.Activated == args.ToggledOn) return false;
return EntitySystem.Get().ToggleStatus(args.Performer, lightComponent);
diff --git a/Content.Server/Light/EntitySystems/HandheldLightSystem.cs b/Content.Server/Light/EntitySystems/HandheldLightSystem.cs
index 001867f050..2b462bb696 100644
--- a/Content.Server/Light/EntitySystems/HandheldLightSystem.cs
+++ b/Content.Server/Light/EntitySystems/HandheldLightSystem.cs
@@ -28,7 +28,6 @@ namespace Content.Server.Light.EntitySystems
[UsedImplicitly]
public sealed class HandheldLightSystem : EntitySystem
{
- [Dependency] private readonly ActionBlockerSystem _blocker = default!;
[Dependency] private readonly PopupSystem _popup = default!;
[Dependency] private readonly PowerCellSystem _powerCell = default!;
@@ -96,7 +95,6 @@ namespace Content.Server.Light.EntitySystems
/// True if the light's status was toggled, false otherwise.
public bool ToggleStatus(EntityUid user, HandheldLightComponent component)
{
- if (!_blocker.CanUse(user)) return false;
return component.Activated ? TurnOff(component) : TurnOn(user, component);
}
diff --git a/Content.Server/Light/EntitySystems/LightReplacerSystem.cs b/Content.Server/Light/EntitySystems/LightReplacerSystem.cs
index ab361124a1..82d2aa2932 100644
--- a/Content.Server/Light/EntitySystems/LightReplacerSystem.cs
+++ b/Content.Server/Light/EntitySystems/LightReplacerSystem.cs
@@ -16,9 +16,8 @@ using Robust.Shared.Player;
namespace Content.Server.Light.EntitySystems
{
[UsedImplicitly]
- public class LightReplacerSystem : EntitySystem
+ public sealed class LightReplacerSystem : EntitySystem
{
- [Dependency] private readonly ActionBlockerSystem _blocker = default!;
[Dependency] private readonly PoweredLightSystem _poweredLight = default!;
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
@@ -42,7 +41,6 @@ namespace Content.Server.Light.EntitySystems
return;
// standard interaction checks
- if (!_blocker.CanUse(eventArgs.User)) return;
if (!eventArgs.CanReach) return;
// behaviour will depends on target type
@@ -64,9 +62,6 @@ namespace Content.Server.Light.EntitySystems
if (eventArgs.Handled)
return;
- // standard interaction checks
- if (!_blocker.CanInteract(eventArgs.User)) return;
-
var usedUid = eventArgs.Used;
// want to insert a new light bulb?
diff --git a/Content.Server/Medical/MedicalScannerSystem.cs b/Content.Server/Medical/MedicalScannerSystem.cs
index 62b1345e0d..0e8d22cc10 100644
--- a/Content.Server/Medical/MedicalScannerSystem.cs
+++ b/Content.Server/Medical/MedicalScannerSystem.cs
@@ -75,7 +75,7 @@ namespace Content.Server.Medical
private void OnRelayMovement(EntityUid uid, MedicalScannerComponent component, RelayMovementEntityEvent args)
{
- if (_blocker.CanInteract(args.Entity))
+ if (_blocker.CanInteract(args.Entity, null))
{
if (_gameTiming.CurTime <
component.LastInternalOpenAttempt + MedicalScannerComponent.InternalOpenAttemptDelay)
diff --git a/Content.Server/Medical/SuitSensors/SuitSensorSystem.cs b/Content.Server/Medical/SuitSensors/SuitSensorSystem.cs
index 7471f6b6c7..7d4ed128c9 100644
--- a/Content.Server/Medical/SuitSensors/SuitSensorSystem.cs
+++ b/Content.Server/Medical/SuitSensors/SuitSensorSystem.cs
@@ -24,7 +24,6 @@ namespace Content.Server.Medical.SuitSensors
{
public class SuitSensorSystem : EntitySystem
{
- [Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly IdCardSystem _idCardSystem = default!;
@@ -142,7 +141,7 @@ namespace Content.Server.Medical.SuitSensors
return;
// standard interaction checks
- if (!args.CanAccess || !args.CanInteract || !_actionBlockerSystem.CanDrop(args.User))
+ if (!args.CanAccess || !args.CanInteract)
return;
args.Verbs.UnionWith(new[]
diff --git a/Content.Server/Nuke/NukeSystem.cs b/Content.Server/Nuke/NukeSystem.cs
index 0393e807ea..05b151c5b4 100644
--- a/Content.Server/Nuke/NukeSystem.cs
+++ b/Content.Server/Nuke/NukeSystem.cs
@@ -117,12 +117,6 @@ namespace Content.Server.Nuke
if (args.Handled)
return;
- // standard interactions check
- if (!args.InRangeUnobstructed())
- return;
- if (!_actionBlocker.CanInteract(args.User) || !_actionBlocker.CanUse(args.User))
- return;
-
if (!EntityManager.TryGetComponent(args.User, out ActorComponent? actor))
return;
diff --git a/Content.Server/Nutrition/EntitySystems/DrinkSystem.cs b/Content.Server/Nutrition/EntitySystems/DrinkSystem.cs
index e6de25dd53..f1d6ca264a 100644
--- a/Content.Server/Nutrition/EntitySystems/DrinkSystem.cs
+++ b/Content.Server/Nutrition/EntitySystems/DrinkSystem.cs
@@ -40,7 +40,6 @@ namespace Content.Server.Nutrition.EntitySystems
[Dependency] private readonly StomachSystem _stomachSystem = default!;
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly SharedAdminLogSystem _logSystem = default!;
- [Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!;
[Dependency] private readonly SpillableSystem _spillableSystem = default!;
public override void Initialize()
@@ -111,10 +110,6 @@ namespace Content.Server.Nutrition.EntitySystems
if (args.Handled || args.Target == null || !args.CanReach)
return;
- // CanInteract already checked CanInteract
- if (!_actionBlockerSystem.CanUse(args.User))
- return;
-
args.Handled = TryDrink(args.User, args.Target.Value, component);
}
@@ -122,12 +117,6 @@ namespace Content.Server.Nutrition.EntitySystems
{
if (args.Handled) return;
- if (!args.User.InRangeUnobstructed(uid, popup: true))
- {
- args.Handled = true;
- return;
- }
-
if (!component.Opened)
{
//Do the opening stuff like playing the sounds.
@@ -137,10 +126,6 @@ namespace Content.Server.Nutrition.EntitySystems
return;
}
- // CanUse already checked; trying to keep it consistent if we interact with ourselves.
- if (!_actionBlockerSystem.CanInteract(args.User))
- return;
-
args.Handled = TryDrink(args.User, args.User, component);
}
diff --git a/Content.Server/Nutrition/EntitySystems/FoodSystem.cs b/Content.Server/Nutrition/EntitySystems/FoodSystem.cs
index 25605c7a4c..1c62e00a5d 100644
--- a/Content.Server/Nutrition/EntitySystems/FoodSystem.cs
+++ b/Content.Server/Nutrition/EntitySystems/FoodSystem.cs
@@ -40,7 +40,6 @@ namespace Content.Server.Nutrition.EntitySystems
[Dependency] private readonly UtensilSystem _utensilSystem = default!;
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly SharedAdminLogSystem _logSystem = default!;
- [Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!;
[Dependency] private readonly InventorySystem _inventorySystem = default!;
public override void Initialize()
@@ -79,9 +78,6 @@ namespace Content.Server.Nutrition.EntitySystems
public bool TryFeed(EntityUid user, EntityUid target, FoodComponent food)
{
- if (!_actionBlockerSystem.CanInteract(user) || !_actionBlockerSystem.CanUse(user))
- return false;
-
// if currently being used to feed, cancel that action.
if (food.CancelToken != null)
{
diff --git a/Content.Server/ParticleAccelerator/Components/ParticleAcceleratorControlBoxComponent.cs b/Content.Server/ParticleAccelerator/Components/ParticleAcceleratorControlBoxComponent.cs
index ac987f92e2..d413fb3bb4 100644
--- a/Content.Server/ParticleAccelerator/Components/ParticleAcceleratorControlBoxComponent.cs
+++ b/Content.Server/ParticleAccelerator/Components/ParticleAcceleratorControlBoxComponent.cs
@@ -150,13 +150,6 @@ namespace Content.Server.ParticleAccelerator.Components
return;
}
-
- if (obj.Session.AttachedEntity is not {Valid: true} attached ||
- !EntitySystem.Get().CanInteract(attached))
- {
- return;
- }
-
if (_wireInterfaceBlocked)
{
return;
diff --git a/Content.Server/Plants/Systems/PottedPlantHideSystem.cs b/Content.Server/Plants/Systems/PottedPlantHideSystem.cs
index f0dfe1aae8..10dd5e5dbd 100644
--- a/Content.Server/Plants/Systems/PottedPlantHideSystem.cs
+++ b/Content.Server/Plants/Systems/PottedPlantHideSystem.cs
@@ -37,9 +37,6 @@ namespace Content.Server.Plants.Systems
if (args.Handled)
return;
- // standard interaction checks
- if (!_blocker.CanInteract(args.User)) return;
-
Rustle(uid, component);
args.Handled = _stashSystem.TryHideItem(uid, args.User, args.Used);
}
@@ -49,9 +46,6 @@ namespace Content.Server.Plants.Systems
if (args.Handled)
return;
- // standard interaction checks
- if (!_blocker.CanInteract(args.User)) return;
-
Rustle(uid, component);
var gotItem = _stashSystem.TryGetItem(uid, args.User);
diff --git a/Content.Server/Shuttles/EntitySystems/ShuttleConsoleSystem.cs b/Content.Server/Shuttles/EntitySystems/ShuttleConsoleSystem.cs
index c060da4298..53992d56be 100644
--- a/Content.Server/Shuttles/EntitySystems/ShuttleConsoleSystem.cs
+++ b/Content.Server/Shuttles/EntitySystems/ShuttleConsoleSystem.cs
@@ -96,7 +96,7 @@ namespace Content.Server.Shuttles.EntitySystems
{
if (comp.Console == null) continue;
- if (!_blocker.CanInteract((comp).Owner))
+ if (!_blocker.CanInteract(comp.Owner, comp.Console.Owner))
{
toRemove.Add(comp);
}
@@ -189,8 +189,7 @@ namespace Content.Server.Shuttles.EntitySystems
public void AddPilot(EntityUid entity, ShuttleConsoleComponent component)
{
- if (!_blocker.CanInteract(entity) ||
- !EntityManager.TryGetComponent(entity, out PilotComponent? pilotComponent) ||
+ if (!EntityManager.TryGetComponent(entity, out PilotComponent? pilotComponent) ||
component.SubscribedPilots.Contains(pilotComponent))
{
return;
diff --git a/Content.Server/Strip/StrippableComponent.cs b/Content.Server/Strip/StrippableComponent.cs
index 8cf8acc606..f48ab805f0 100644
--- a/Content.Server/Strip/StrippableComponent.cs
+++ b/Content.Server/Strip/StrippableComponent.cs
@@ -88,9 +88,6 @@ namespace Content.Server.Strip
bool Check()
{
- if (!EntitySystem.Get().CanInteract(user))
- return false;
-
if (item == null)
{
user.PopupMessageCursor(Loc.GetString("strippable-component-not-holding-anything"));
@@ -153,9 +150,6 @@ namespace Content.Server.Strip
bool Check()
{
- if (!EntitySystem.Get().CanInteract(user))
- return false;
-
if (item == null)
{
user.PopupMessageCursor(Loc.GetString("strippable-component-not-holding-anything"));
@@ -219,9 +213,6 @@ namespace Content.Server.Strip
bool Check()
{
- if (!EntitySystem.Get().CanInteract(user))
- return false;
-
if (!invSystem.HasSlot(Owner, slot))
return false;
@@ -272,9 +263,6 @@ namespace Content.Server.Strip
bool Check()
{
- if (!EntitySystem.Get().CanInteract(user))
- return false;
-
if (!hands.HasHand(hand))
return false;
diff --git a/Content.Server/Stunnable/StunbatonSystem.cs b/Content.Server/Stunnable/StunbatonSystem.cs
index caeffc02af..1d197ff78d 100644
--- a/Content.Server/Stunnable/StunbatonSystem.cs
+++ b/Content.Server/Stunnable/StunbatonSystem.cs
@@ -73,9 +73,6 @@ namespace Content.Server.Stunnable
private void OnUseInHand(EntityUid uid, StunbatonComponent comp, UseInHandEvent args)
{
- if (!Get().CanUse(args.User))
- return;
-
if (comp.Activated)
{
TurnOff(comp);
diff --git a/Content.Server/Tabletop/TabletopSystem.cs b/Content.Server/Tabletop/TabletopSystem.cs
index 88a2ff9254..bd0618777b 100644
--- a/Content.Server/Tabletop/TabletopSystem.cs
+++ b/Content.Server/Tabletop/TabletopSystem.cs
@@ -58,9 +58,7 @@ namespace Content.Server.Tabletop
if (!EntityManager.TryGetComponent(args.User, out ActorComponent? actor))
return;
- // Check that the entity can interact with the game board.
- if(_actionBlockerSystem.CanInteract(args.User))
- OpenSessionFor(actor.PlayerSession, uid);
+ OpenSessionFor(actor.PlayerSession, uid);
}
private void OnGameShutdown(EntityUid uid, TabletopGameComponent component, ComponentShutdown args)
diff --git a/Content.Server/Tools/ToolSystem.Welder.cs b/Content.Server/Tools/ToolSystem.Welder.cs
index a4649bd07f..4990ab0e84 100644
--- a/Content.Server/Tools/ToolSystem.Welder.cs
+++ b/Content.Server/Tools/ToolSystem.Welder.cs
@@ -102,9 +102,6 @@ namespace Content.Server.Tools
return false;
}
- if (user != null && !_actionBlockerSystem.CanInteract(user.Value))
- return false;
-
solution.RemoveReagent(welder.FuelReagent, welder.FuelLitCost);
welder.Lit = true;
@@ -140,9 +137,6 @@ namespace Content.Server.Tools
// Optional components.
Resolve(uid, ref item, ref light, ref sprite);
- if (user != null && !_actionBlockerSystem.CanInteract(user.Value))
- return false;
-
welder.Lit = false;
// TODO: Make all this use visualizers.
diff --git a/Content.Server/Tools/ToolSystem.cs b/Content.Server/Tools/ToolSystem.cs
index d7a166e715..fc11270f29 100644
--- a/Content.Server/Tools/ToolSystem.cs
+++ b/Content.Server/Tools/ToolSystem.cs
@@ -23,7 +23,6 @@ namespace Content.Server.Tools
[Dependency] private readonly ITileDefinitionManager _tileDefinitionManager = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
- [Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!;
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
@@ -214,7 +213,7 @@ namespace Content.Server.Tools
if (!Resolve(tool, ref toolComponent))
return false;
- if (!toolComponent.Qualities.ContainsAll(toolQualitiesNeeded) || !_actionBlockerSystem.CanInteract(user))
+ if (!toolComponent.Qualities.ContainsAll(toolQualitiesNeeded))
return false;
var beforeAttempt = new ToolUseAttemptEvent(fuel, user);
diff --git a/Content.Server/Traitor/Uplink/UplinkSystem.cs b/Content.Server/Traitor/Uplink/UplinkSystem.cs
index 925a9741e2..0534d06fc3 100644
--- a/Content.Server/Traitor/Uplink/UplinkSystem.cs
+++ b/Content.Server/Traitor/Uplink/UplinkSystem.cs
@@ -89,10 +89,6 @@ namespace Content.Server.Traitor.Uplink
if (!EntityManager.TryGetComponent(args.User, out ActorComponent? actor))
return;
- var actionBlocker = EntitySystem.Get();
- if (!actionBlocker.CanInteract(uid) || !actionBlocker.CanUse(uid))
- return;
-
ToggleUplinkUI(component, actor.PlayerSession);
args.Handled = true;
}
diff --git a/Content.Server/UserInterface/ActivatableUISystem.cs b/Content.Server/UserInterface/ActivatableUISystem.cs
index 1eae822e41..2df6b3dff0 100644
--- a/Content.Server/UserInterface/ActivatableUISystem.cs
+++ b/Content.Server/UserInterface/ActivatableUISystem.cs
@@ -18,7 +18,6 @@ namespace Content.Server.UserInterface
[UsedImplicitly]
internal sealed class ActivatableUISystem : EntitySystem
{
- [Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!;
[Dependency] private readonly IAdminManager _adminManager = default!;
public override void Initialize()
@@ -82,12 +81,6 @@ namespace Content.Server.UserInterface
if (aui.AdminOnly && !_adminManager.IsAdmin(actor.PlayerSession)) return false;
- if (!HasComp(user) && !_actionBlockerSystem.CanInteract(user))
- {
- user.PopupMessageCursor(Loc.GetString("base-computer-ui-component-cannot-interact"));
- return true;
- }
-
var ui = aui.UserInterface;
if (ui == null) return false;
diff --git a/Content.Server/Weapon/Melee/EnergySword/EnergySwordSystem.cs b/Content.Server/Weapon/Melee/EnergySword/EnergySwordSystem.cs
index c4311548e6..8a50244fbf 100644
--- a/Content.Server/Weapon/Melee/EnergySword/EnergySwordSystem.cs
+++ b/Content.Server/Weapon/Melee/EnergySword/EnergySwordSystem.cs
@@ -44,9 +44,6 @@ namespace Content.Server.Weapon.Melee.EnergySword
{
if (args.Handled) return;
- if (!_blockerSystem.CanUse(args.User))
- return;
-
args.Handled = true;
if (comp.Activated)
@@ -114,7 +111,7 @@ namespace Content.Server.Weapon.Melee.EnergySword
{
if (args.Handled) return;
- if (comp.Hacked || !_blockerSystem.CanInteract(args.User))
+ if (comp.Hacked)
return;
if (!TryComp(args.Used, out ToolComponent? tool) || !tool.Qualities.ContainsAny("Pulsing")) return;
diff --git a/Content.Server/Weapon/Ranged/GunSystem.Guns.cs b/Content.Server/Weapon/Ranged/GunSystem.Guns.cs
index 2477d10644..7eac43dfaf 100644
--- a/Content.Server/Weapon/Ranged/GunSystem.Guns.cs
+++ b/Content.Server/Weapon/Ranged/GunSystem.Guns.cs
@@ -40,7 +40,7 @@ public sealed partial class GunSystem
if (!TryComp(user, out CombatModeComponent? combat) ||
!combat.IsInCombatMode ||
- !_blocker.CanInteract(user)) return;
+ !_blocker.CanInteract(user, gun.Owner)) return;
var fireAttempt = new GunFireAttemptEvent(user, gun);
EntityManager.EventBus.RaiseLocalEvent(gun.Owner, fireAttempt);
diff --git a/Content.Shared/ActionBlocker/ActionBlockerSystem.cs b/Content.Shared/ActionBlocker/ActionBlockerSystem.cs
index bd36316bae..e9f2f19fda 100644
--- a/Content.Shared/ActionBlocker/ActionBlockerSystem.cs
+++ b/Content.Shared/ActionBlocker/ActionBlockerSystem.cs
@@ -16,7 +16,7 @@ namespace Content.Shared.ActionBlocker
/// Utility methods to check if a specific entity is allowed to perform an action.
///
[UsedImplicitly]
- public class ActionBlockerSystem : EntitySystem
+ public sealed class ActionBlockerSystem : EntitySystem
{
public bool CanMove(EntityUid uid)
{
@@ -26,26 +26,54 @@ namespace Content.Shared.ActionBlocker
return !ev.Cancelled;
}
- public bool CanInteract(EntityUid uid)
+ ///
+ /// Raises an event directed at both the user and the target entity to check whether a user is capable of
+ /// interacting with this entity.
+ ///
+ ///
+ /// If this is a generic interaction without a target (e.g., stop-drop-and-roll when burning), the target
+ /// may be null. Note that this is checked by . In the majority of
+ /// cases, systems that provide interactions will not need to check this themselves, though they may need to
+ /// check other blockers like
+ ///
+ ///
+ public bool CanInteract(EntityUid user, EntityUid? target)
{
- var ev = new InteractionAttemptEvent(uid);
- RaiseLocalEvent(uid, ev);
+ var ev = new InteractionAttemptEvent(user, target);
+ RaiseLocalEvent(user, ev);
+
+ if (ev.Cancelled)
+ return false;
+
+ if (target == null)
+ return true;
+
+ var targetEv = new GettingInteractedWithAttemptEvent(user, target);
+ RaiseLocalEvent(target.Value, targetEv);
+
+ return !targetEv.Cancelled;
+ }
+
+ ///
+ /// Can a user utilize the entity that they are currently holding in their hands.
+ /// >
+ ///
+ /// This event is automatically checked by for any interactions that
+ /// involve using a held entity. In the majority of cases, systems that provide interactions will not need
+ /// to check this themselves.
+ ///
+ public bool CanUseHeldEntity(EntityUid user)
+ {
+ var ev = new UseAttemptEvent(user);
+ RaiseLocalEvent(user, ev);
return !ev.Cancelled;
}
- public bool CanUse(EntityUid uid)
+ public bool CanThrow(EntityUid user)
{
- var ev = new UseAttemptEvent(uid);
- RaiseLocalEvent(uid, ev);
-
- return !ev.Cancelled;
- }
-
- public bool CanThrow(EntityUid uid)
- {
- var ev = new ThrowAttemptEvent(uid);
- RaiseLocalEvent(uid, ev);
+ var ev = new ThrowAttemptEvent(user);
+ RaiseLocalEvent(user, ev);
return !ev.Cancelled;
}
diff --git a/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs b/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs
index 05ecdc05f0..106fec4e6e 100644
--- a/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs
+++ b/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs
@@ -278,6 +278,7 @@ namespace Content.Shared.Containers.ItemSlots
///
/// Tries to insert item into a specific slot from an entity's hand.
+ /// Does not check action blockers.
///
/// False if failed to insert item
public bool TryInsertFromHand(EntityUid uid, ItemSlot slot, EntityUid user, SharedHandsComponent? hands = null)
@@ -293,7 +294,7 @@ namespace Content.Shared.Containers.ItemSlots
return false;
// hands.Drop(item) checks CanDrop action blocker
- if (!_actionBlockerSystem.CanInteract(user) && hands.Drop(heldItem))
+ if (hands.Drop(heldItem))
return false;
Insert(uid, slot, heldItem, user);
diff --git a/Content.Shared/Hands/Components/SharedHandsComponent.cs b/Content.Shared/Hands/Components/SharedHandsComponent.cs
index 448ad6d4bb..777c79c07d 100644
--- a/Content.Shared/Hands/Components/SharedHandsComponent.cs
+++ b/Content.Shared/Hands/Components/SharedHandsComponent.cs
@@ -561,7 +561,7 @@ namespace Content.Shared.Hands.Components
///
/// Attempts to interact with the item in a hand using the active held item.
///
- public async void InteractHandWithActiveHand(string handName)
+ public void InteractHandWithActiveHand(string handName)
{
if (!TryGetActiveHeldEntity(out var activeHeldEntity))
return;
@@ -572,7 +572,7 @@ namespace Content.Shared.Hands.Components
if (activeHeldEntity == heldEntity)
return;
- await EntitySystem.Get()
+ EntitySystem.Get()
.InteractUsing(Owner, activeHeldEntity.Value, heldEntity.Value, EntityCoordinates.Invalid);
}
@@ -585,7 +585,7 @@ namespace Content.Shared.Hands.Components
if (altInteract)
sys.AltInteract(Owner, heldEntity.Value);
else
- sys.TryUseInteraction(Owner, heldEntity.Value);
+ sys.UseInHandInteraction(Owner, heldEntity.Value);
}
public void ActivateHeldEntity(string handName)
@@ -594,7 +594,7 @@ namespace Content.Shared.Hands.Components
return;
EntitySystem.Get()
- .TryInteractionActivate(Owner, heldEntity);
+ .InteractionActivate(Owner, heldEntity.Value);
}
///
diff --git a/Content.Shared/Hands/SharedHandVirtualItemSystem.cs b/Content.Shared/Hands/SharedHandVirtualItemSystem.cs
index 57345608e5..fd7b2e8a22 100644
--- a/Content.Shared/Hands/SharedHandVirtualItemSystem.cs
+++ b/Content.Shared/Hands/SharedHandVirtualItemSystem.cs
@@ -12,7 +12,7 @@ public abstract class SharedHandVirtualItemSystem : EntitySystem
base.Initialize();
SubscribeLocalEvent(OnBeingEquippedAttempt);
- SubscribeLocalEvent(HandleBeforeInteract);
+ SubscribeLocalEvent(HandleBeforeInteract);
}
private void OnBeingEquippedAttempt(EntityUid uid, HandVirtualItemComponent component, BeingEquippedAttemptEvent args)
@@ -23,7 +23,7 @@ public abstract class SharedHandVirtualItemSystem : EntitySystem
private static void HandleBeforeInteract(
EntityUid uid,
HandVirtualItemComponent component,
- BeforeInteractEvent args)
+ BeforeRangedInteractEvent args)
{
// No interactions with a virtual item, please.
args.Handled = true;
diff --git a/Content.Shared/Interaction/BeforeInteract.cs b/Content.Shared/Interaction/BeforeInteract.cs
index c2c5563511..156507fd87 100644
--- a/Content.Shared/Interaction/BeforeInteract.cs
+++ b/Content.Shared/Interaction/BeforeInteract.cs
@@ -8,7 +8,7 @@ namespace Content.Shared.Interaction
/// Raised directed on the used object when clicking on another object before an interaction is handled.
///
[PublicAPI]
- public class BeforeInteractEvent : HandledEntityEventArgs
+ public class BeforeRangedInteractEvent : HandledEntityEventArgs
{
///
/// Entity that triggered the interaction.
@@ -35,7 +35,7 @@ namespace Content.Shared.Interaction
///
public bool CanReach { get; }
- public BeforeInteractEvent(
+ public BeforeRangedInteractEvent(
EntityUid user,
EntityUid used,
EntityUid? target,
diff --git a/Content.Shared/Interaction/Events/InteractionAttemptEvent.cs b/Content.Shared/Interaction/Events/InteractionAttemptEvent.cs
index a8186e9878..3f4e19d05c 100644
--- a/Content.Shared/Interaction/Events/InteractionAttemptEvent.cs
+++ b/Content.Shared/Interaction/Events/InteractionAttemptEvent.cs
@@ -2,13 +2,34 @@
namespace Content.Shared.Interaction.Events
{
- public class InteractionAttemptEvent : CancellableEntityEventArgs
+ ///
+ /// Event raised directed at a user to see if they can perform a generic interaction.
+ ///
+ public sealed class InteractionAttemptEvent : CancellableEntityEventArgs
{
- public InteractionAttemptEvent(EntityUid uid)
+ public InteractionAttemptEvent(EntityUid uid, EntityUid? target)
{
Uid = uid;
+ Target = target;
}
public EntityUid Uid { get; }
+ public EntityUid? Target { get; }
+ }
+
+ ///
+ /// Event raised directed at the target entity of an interaction to see if the user is allowed to perform some
+ /// generic interaction.
+ ///
+ public sealed class GettingInteractedWithAttemptEvent : CancellableEntityEventArgs
+ {
+ public GettingInteractedWithAttemptEvent(EntityUid uid, EntityUid? target)
+ {
+ Uid = uid;
+ Target = target;
+ }
+
+ public EntityUid Uid { get; }
+ public EntityUid? Target { get; }
}
}
diff --git a/Content.Shared/Interaction/SharedInteractionSystem.cs b/Content.Shared/Interaction/SharedInteractionSystem.cs
index 66799a5e83..64ef8048b3 100644
--- a/Content.Shared/Interaction/SharedInteractionSystem.cs
+++ b/Content.Shared/Interaction/SharedInteractionSystem.cs
@@ -75,7 +75,7 @@ namespace Content.Shared.Interaction
///
private void OnBoundInterfaceInteractAttempt(BoundUserInterfaceMessageAttempt ev)
{
- if (ev.Sender.AttachedEntity is not EntityUid user || !_actionBlockerSystem.CanInteract(user))
+ if (ev.Sender.AttachedEntity is not EntityUid user || !_actionBlockerSystem.CanInteract(user, ev.Target))
{
ev.Cancel();
return;
@@ -108,6 +108,11 @@ namespace Content.Shared.Interaction
return;
}
+ // We won't bother to check that the target item is ACTUALLY in an inventory slot. UserInteraction() and
+ // InteractionActivate() should check that the item is accessible. So.. if a user wants to lie about an
+ // in-reach item being used in a slot... that should have no impact. This is functionally the same as if
+ // they had somehow directly clicked on that item.
+
if (msg.AltInteract)
// Use 'UserInteraction' function - behaves as if the user alt-clicked the item in the world.
UserInteraction(user.Value, coords, msg.ItemUid, msg.AltInteract);
@@ -139,7 +144,14 @@ namespace Content.Shared.Interaction
/// Whether to use default or alternative interactions (usually as a result of
/// alt+clicking). If combat mode is enabled, the alternative action is to perform the default non-combat
/// interaction. Having an item in the active hand also disables alternative interactions.
- public async void UserInteraction(EntityUid user, EntityCoordinates coordinates, EntityUid? target, bool altInteract = false)
+ public void UserInteraction(
+ EntityUid user,
+ EntityCoordinates coordinates,
+ EntityUid? target,
+ bool altInteract = false,
+ bool checkCanInteract = true,
+ bool checkAccess = true,
+ bool checkCanUse = true)
{
if (target != null && Deleted(target.Value))
return;
@@ -154,55 +166,71 @@ namespace Content.Shared.Interaction
if (!ValidateInteractAndFace(user, coordinates))
return;
- if (!_actionBlockerSystem.CanInteract(user))
+ if (altInteract && target != null)
+ {
+ // Perform alternative interactions, using context menu verbs.
+ // These perform their own range, can-interact, and accessibility checks.
+ AltInteract(user, target.Value);
+ }
+
+ if (checkCanInteract && !_actionBlockerSystem.CanInteract(user, target))
return;
// Check if interacted entity is in the same container, the direct child, or direct parent of the user.
- // This is bypassed IF the interaction happened through an item slot (e.g., backpack UI)
- if (target != null && !ContainerSystem.IsInSameOrParentContainer(user, target.Value) && !CanAccessViaStorage(user, target.Value))
+ // Also checks if the item is accessible via some storage UI (e.g., open backpack)
+ if (checkAccess
+ && target != null
+ && !ContainerSystem.IsInSameOrParentContainer(user, target.Value)
+ && !CanAccessViaStorage(user, target.Value))
return;
- // Verify user has a hand, and find what object they are currently holding in their active hand
- if (!TryComp(user, out SharedHandsComponent? hands))
+ // Does the user have hands?
+ Hand? hand;
+ if (!TryComp(user, out SharedHandsComponent? hands) || !hands.TryGetActiveHand(out hand))
return;
+ // ^ In future, things like looking at a UI & opening doors (i.e., Activate interactions) shouldn't neccesarily require hands.
+ // But that would first involve some work with BUIs & making sure other activate-interactions check hands if they are required.
+
+ // Check range
// TODO: Replace with body interaction range when we get something like arm length or telekinesis or something.
- var inRangeUnobstructed = user.InRangeUnobstructed(coordinates, ignoreInsideBlocker: true);
- if (target == null || !inRangeUnobstructed)
+ var inRangeUnobstructed = !checkAccess || user.InRangeUnobstructed(coordinates, ignoreInsideBlocker: true);
+
+ // empty-hand interactions
+ if (hand.HeldEntity == null)
{
- if (!hands.TryGetActiveHeldEntity(out var heldEntity) || !_actionBlockerSystem.CanUse(user))
- return;
-
- if (await InteractUsingRanged(user, heldEntity.Value, target, coordinates, inRangeUnobstructed))
- return;
-
- // Generate popup only if user actually tried to click on something.
- if (!inRangeUnobstructed && target != null)
- {
- _popupSystem.PopupCursor(Loc.GetString("interaction-system-user-interaction-cannot-reach"), Filter.Entities(user));
- }
+ if (inRangeUnobstructed && target != null)
+ InteractHand(user, target.Value);
return;
}
- // We are close to the nearby object.
- if (altInteract)
+ // Can the user use the held entity?
+ if (checkCanUse && !_actionBlockerSystem.CanUseHeldEntity(user))
+ return;
+
+ if (inRangeUnobstructed && target != null)
{
- // Perform alternative interactions, using context menu verbs.
- AltInteract(user, target.Value);
- }
- else if (!hands.TryGetActiveHeldEntity(out var heldEntity))
- {
- // Since our hand is empty we will use InteractHand/Activate
- InteractHand(user, target.Value, checkActionBlocker: false);
- }
- else if (heldEntity != target && _actionBlockerSystem.CanUse(user))
- {
- await InteractUsing(user, heldEntity.Value, target.Value, coordinates, checkActionBlocker: false);
+ InteractUsing(
+ user,
+ hand.HeldEntity.Value,
+ target.Value,
+ coordinates,
+ checkCanInteract: false,
+ checkCanUse: false);
+
+ return;
}
+
+ InteractUsingRanged(
+ user,
+ hand.HeldEntity.Value,
+ target,
+ coordinates,
+ inRangeUnobstructed);
}
- public virtual void InteractHand(EntityUid user, EntityUid target, bool checkActionBlocker = true)
+ public virtual void InteractHand(EntityUid user, EntityUid target)
{
// TODO PREDICTION move server-side interaction logic into the shared system for interaction prediction.
}
@@ -213,11 +241,10 @@ namespace Content.Shared.Interaction
// TODO PREDICTION move server-side interaction logic into the shared system for interaction prediction.
}
- public virtual async Task InteractUsingRanged(EntityUid user, EntityUid used, EntityUid? target,
+ public virtual void InteractUsingRanged(EntityUid user, EntityUid used, EntityUid? target,
EntityCoordinates clickLocation, bool inRangeUnobstructed)
{
// TODO PREDICTION move server-side interaction logic into the shared system for interaction prediction.
- return await Task.FromResult(true);
}
protected bool ValidateInteractAndFace(EntityUid user, EntityCoordinates coordinates)
@@ -548,21 +575,21 @@ namespace Content.Shared.Interaction
if (!inRange && popup)
{
- var message = Loc.GetString("shared-interaction-system-in-range-unobstructed-cannot-reach");
+ var message = Loc.GetString("interaction-system-user-interaction-cannot-reach");
origin.PopupMessage(message);
}
return inRange;
}
- public bool InteractDoBefore(
+ public bool RangedInteractDoBefore(
EntityUid user,
EntityUid used,
EntityUid? target,
EntityCoordinates clickLocation,
bool canReach)
{
- var ev = new BeforeInteractEvent(user, used, target, clickLocation, canReach);
+ var ev = new BeforeRangedInteractEvent(user, used, target, clickLocation, canReach);
RaiseLocalEvent(used, ev, false);
return ev.Handled;
}
@@ -572,12 +599,22 @@ namespace Content.Shared.Interaction
/// Finds components with the InteractUsing interface and calls their function
/// NOTE: Does not have an InRangeUnobstructed check
///
- public async Task InteractUsing(EntityUid user, EntityUid used, EntityUid target, EntityCoordinates clickLocation, bool predicted = false, bool checkActionBlocker = true)
+ public async void InteractUsing(
+ EntityUid user,
+ EntityUid used,
+ EntityUid target,
+ EntityCoordinates clickLocation,
+ bool predicted = false,
+ bool checkCanInteract = true,
+ bool checkCanUse = true)
{
- if (checkActionBlocker && (!_actionBlockerSystem.CanInteract(user) || !_actionBlockerSystem.CanUse(user)))
+ if (checkCanInteract && !_actionBlockerSystem.CanInteract(user, target))
return;
- if (InteractDoBefore(user, used, target, clickLocation, true))
+ if (checkCanUse && !_actionBlockerSystem.CanUseHeldEntity(user))
+ return;
+
+ if (RangedInteractDoBefore(user, used, target, clickLocation, true))
return;
// all interactions should only happen when in range / unobstructed, so no range check is needed
@@ -596,13 +633,13 @@ namespace Content.Shared.Interaction
return;
}
- await InteractDoAfter(user, used, target, clickLocation, true);
+ InteractDoAfter(user, used, target, clickLocation, canReach: true);
}
///
/// Used when clicking on an entity resulted in no other interaction. Used for low-priority interactions.
///
- public async Task InteractDoAfter(EntityUid user, EntityUid used, EntityUid? target, EntityCoordinates clickLocation, bool canReach)
+ public async void InteractDoAfter(EntityUid user, EntityUid used, EntityUid? target, EntityCoordinates clickLocation, bool canReach)
{
if (target is {Valid: false})
target = null;
@@ -610,7 +647,7 @@ namespace Content.Shared.Interaction
var afterInteractEvent = new AfterInteractEvent(user, used, target, clickLocation, canReach);
RaiseLocalEvent(used, afterInteractEvent, false);
if (afterInteractEvent.Handled)
- return true;
+ return;
var afterInteractEventArgs = new AfterInteractEventArgs(user, clickLocation, target, canReach);
var afterInteracts = AllComps(used).OrderByDescending(x => x.Priority).ToList();
@@ -618,46 +655,49 @@ namespace Content.Shared.Interaction
foreach (var afterInteract in afterInteracts)
{
if (await afterInteract.AfterInteract(afterInteractEventArgs))
- return true;
+ return;
}
if (target == null)
- return false;
+ return;
var afterInteractUsingEvent = new AfterInteractUsingEvent(user, used, target, clickLocation, canReach);
RaiseLocalEvent(target.Value, afterInteractUsingEvent, false);
- return afterInteractEvent.Handled;
}
#region ActivateItemInWorld
///
- /// Activates the IActivate behavior of an object
- /// Verifies that the user is capable of doing the use interaction first
+ /// Raises events and activates the IActivate behavior of an object.
///
- public void TryInteractionActivate(EntityUid? user, EntityUid? used)
+ ///
+ /// Does not check the can-use action blocker. In activations interacts can target entities outside of the users
+ /// hands.
+ ///
+ public bool InteractionActivate(
+ EntityUid user,
+ EntityUid used,
+ bool checkCanInteract = true,
+ bool checkUseDelay = true,
+ bool checkAccess = true)
{
- if (user == null || used == null)
- return;
+ UseDelayComponent? delayComponent = null;
+ if (checkUseDelay
+ && TryComp(used, out delayComponent)
+ && delayComponent.ActiveDelay)
+ return false;
- InteractionActivate(user.Value, used.Value);
- }
+ if (checkCanInteract && !_actionBlockerSystem.CanInteract(user, used))
+ return false;
- protected void InteractionActivate(EntityUid user, EntityUid used)
- {
- if (TryComp(used, out UseDelayComponent? delayComponent) && delayComponent.ActiveDelay)
- return;
-
- if (!_actionBlockerSystem.CanInteract(user) || !_actionBlockerSystem.CanUse(user))
- return;
// all activates should only fire when in range / unobstructed
- if (!InRangeUnobstructed(user, used, ignoreInsideBlocker: true, popup: true))
- return;
+ if (checkAccess && !InRangeUnobstructed(user, used, ignoreInsideBlocker: true, popup: true))
+ return false;
// Check if interacted entity is in the same container, the direct child, or direct parent of the user.
// This is bypassed IF the interaction happened through an item slot (e.g., backpack UI)
- if (!ContainerSystem.IsInSameOrParentContainer(user, used) && !CanAccessViaStorage(user, used))
- return;
+ if (checkAccess && !ContainerSystem.IsInSameOrParentContainer(user, used) && !CanAccessViaStorage(user, used))
+ return false;
var activateMsg = new ActivateInWorldEvent(user, used);
RaiseLocalEvent(used, activateMsg);
@@ -665,44 +705,47 @@ namespace Content.Shared.Interaction
{
BeginDelay(delayComponent);
_adminLogSystem.Add(LogType.InteractActivate, LogImpact.Low, $"{ToPrettyString(user):user} activated {ToPrettyString(used):used}");
- return;
+ return true;
}
if (!TryComp(used, out IActivate? activateComp))
- return;
+ return false;
var activateEventArgs = new ActivateEventArgs(user, used);
activateComp.Activate(activateEventArgs);
BeginDelay(delayComponent);
_adminLogSystem.Add(LogType.InteractActivate, LogImpact.Low, $"{ToPrettyString(user):user} activated {ToPrettyString(used):used}"); // No way to check success.
+ return true;
}
#endregion
#region Hands
#region Use
///
- /// Attempt to perform a use-interaction on an entity. If no interaction occurs, it will instead attempt to
- /// activate the entity.
- ///
- public void TryUseInteraction(EntityUid user, EntityUid used)
- {
- if (_actionBlockerSystem.CanUse(user) && UseInteraction(user, used))
- return;
-
- // no use-interaction occurred. Attempt to activate the item instead.
- InteractionActivate(user, used);
- }
-
- ///
- /// Activates the IUse behaviors of an entity without first checking
- /// if the user is capable of doing the use interaction.
+ /// Raises UseInHandEvents and activates the IUse behaviors of an entity
+ /// Does not check accessibility or range, for obvious reasons
///
/// True if the interaction was handled. False otherwise
- public bool UseInteraction(EntityUid user, EntityUid used)
+ public bool UseInHandInteraction(
+ EntityUid user,
+ EntityUid used,
+ bool checkCanUse = true,
+ bool checkCanInteract = true,
+ bool checkUseDelay = true)
{
- if (TryComp(used, out UseDelayComponent? delayComponent) && delayComponent.ActiveDelay)
+ UseDelayComponent? delayComponent = null;
+
+ if (checkUseDelay
+ && TryComp(used, out delayComponent)
+ && delayComponent.ActiveDelay)
return true; // if the item is on cooldown, we consider this handled.
+ if (checkCanInteract && !_actionBlockerSystem.CanInteract(user, used))
+ return false;
+
+ if (checkCanUse && !_actionBlockerSystem.CanUseHeldEntity(user))
+ return false;
+
var useMsg = new UseInHandEvent(user, used);
RaiseLocalEvent(used, useMsg);
if (useMsg.Handled)
@@ -724,7 +767,8 @@ namespace Content.Shared.Interaction
}
}
- return false;
+ // else, default to activating the item
+ return InteractionActivate(user, used, false, false, false);
}
protected virtual void BeginDelay(UseDelayComponent? component = null)
@@ -854,7 +898,7 @@ namespace Content.Shared.Interaction
/// Raised when a player attempts to activate an item in an inventory slot or hand slot
///
[Serializable, NetSerializable]
- public class InteractInventorySlotEvent : EntityEventArgs
+ public sealed class InteractInventorySlotEvent : EntityEventArgs
{
///
/// Entity that was interacted with.
diff --git a/Content.Shared/Pulling/Systems/SharedPullingSystem.Actions.cs b/Content.Shared/Pulling/Systems/SharedPullingSystem.Actions.cs
index 5e34801595..9406f58fca 100644
--- a/Content.Shared/Pulling/Systems/SharedPullingSystem.Actions.cs
+++ b/Content.Shared/Pulling/Systems/SharedPullingSystem.Actions.cs
@@ -24,7 +24,7 @@ namespace Content.Shared.Pulling
return false;
}
- if (!_blocker.CanInteract(puller))
+ if (!_blocker.CanInteract(puller, pulled))
{
return false;
}
diff --git a/Content.Shared/Storage/SharedStorageComponent.cs b/Content.Shared/Storage/SharedStorageComponent.cs
index 4275633e75..f9f5c4a4fe 100644
--- a/Content.Shared/Storage/SharedStorageComponent.cs
+++ b/Content.Shared/Storage/SharedStorageComponent.cs
@@ -34,7 +34,7 @@ namespace Content.Shared.Storage
bool IDraggable.Drop(DragDropEvent eventArgs)
{
- if (!EntitySystem.Get().CanInteract(eventArgs.User))
+ if (!EntitySystem.Get().CanInteract(eventArgs.User, eventArgs.Target))
{
return false;
}
diff --git a/Content.Shared/Strip/Components/SharedStrippableComponent.cs b/Content.Shared/Strip/Components/SharedStrippableComponent.cs
index 57146d81c5..1546e69885 100644
--- a/Content.Shared/Strip/Components/SharedStrippableComponent.cs
+++ b/Content.Shared/Strip/Components/SharedStrippableComponent.cs
@@ -15,7 +15,7 @@ namespace Content.Shared.Strip.Components
{
return by != Owner
&& IoCManager.Resolve().HasComponent(@by)
- && EntitySystem.Get().CanInteract(@by);
+ && EntitySystem.Get().CanInteract(@by, Owner);
}
bool IDraggable.CanDrop(CanDropEvent args)
diff --git a/Content.Shared/Tabletop/SharedTabletopSystem.cs b/Content.Shared/Tabletop/SharedTabletopSystem.cs
index da267354de..e3e9807286 100644
--- a/Content.Shared/Tabletop/SharedTabletopSystem.cs
+++ b/Content.Shared/Tabletop/SharedTabletopSystem.cs
@@ -49,7 +49,7 @@ namespace Content.Shared.Tabletop
return false;
}
- return playerEntity.InRangeUnobstructed(table.Value) && _actionBlockerSystem.CanInteract(playerEntity);
+ return playerEntity.InRangeUnobstructed(table.Value) && _actionBlockerSystem.CanInteract(playerEntity, table);
}
protected bool StunnedOrNoHands(EntityUid playerEntity)
diff --git a/Content.Shared/Verbs/SharedVerbSystem.cs b/Content.Shared/Verbs/SharedVerbSystem.cs
index caa590dda1..6950f1c576 100644
--- a/Content.Shared/Verbs/SharedVerbSystem.cs
+++ b/Content.Shared/Verbs/SharedVerbSystem.cs
@@ -76,10 +76,10 @@ namespace Content.Shared.Verbs
// 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 canInteract = force || _actionBlockerSystem.CanInteract(user);
+ var canInteract = force || _actionBlockerSystem.CanInteract(user, target);
EntityUid? @using = null;
- if (TryComp(user, out SharedHandsComponent? hands) && (force || _actionBlockerSystem.CanUse(user)))
+ if (TryComp(user, out SharedHandsComponent? hands) && (force || _actionBlockerSystem.CanUseHeldEntity(user)))
{
hands.TryGetActiveHeldEntity(out @using);
diff --git a/Content.Shared/Verbs/VerbEvents.cs b/Content.Shared/Verbs/VerbEvents.cs
index a997fb59cb..ed7de92fff 100644
--- a/Content.Shared/Verbs/VerbEvents.cs
+++ b/Content.Shared/Verbs/VerbEvents.cs
@@ -118,7 +118,7 @@ namespace Content.Shared.Verbs
/// The entity currently being held by the active hand.
///
///
- /// This is only ever not null when is true and the user
+ /// This is only ever not null when is true and the user
/// has hands.
///
public readonly EntityUid? Using;
diff --git a/Resources/Locale/en-US/buckle/components/buckle-component.ftl b/Resources/Locale/en-US/buckle/components/buckle-component.ftl
index 673fcb3454..32fbaa999a 100644
--- a/Resources/Locale/en-US/buckle/components/buckle-component.ftl
+++ b/Resources/Locale/en-US/buckle/components/buckle-component.ftl
@@ -1,4 +1,3 @@
-buckle-component-cannot-do-that-message = You can't do that!
buckle-component-no-hands-message = You don't have hands!
buckle-component-already-buckled-message = You are already buckled in!
buckle-component-other-already-buckled-message = {$owner} is already buckled in!
diff --git a/Resources/Locale/en-US/components/base-computer-ui-component.ftl b/Resources/Locale/en-US/components/base-computer-ui-component.ftl
index dce198278b..8111c16e43 100644
--- a/Resources/Locale/en-US/components/base-computer-ui-component.ftl
+++ b/Resources/Locale/en-US/components/base-computer-ui-component.ftl
@@ -1,3 +1 @@
-base-computer-ui-component-cannot-interact = You can't interact with a computer right now.
-base-computer-ui-component-not-powered = The computer is not powered.
-
+base-computer-ui-component-not-powered = The computer is not powered.
\ No newline at end of file
diff --git a/Resources/Locale/en-US/disposal/unit/components/disposal-unit-component.ftl b/Resources/Locale/en-US/disposal/unit/components/disposal-unit-component.ftl
index 485f25deef..8ca17cfced 100644
--- a/Resources/Locale/en-US/disposal/unit/components/disposal-unit-component.ftl
+++ b/Resources/Locale/en-US/disposal/unit/components/disposal-unit-component.ftl
@@ -8,8 +8,4 @@ ui-disposal-unit-label-status = Ready
ui-disposal-unit-button-flush = Flush
ui-disposal-unit-button-eject = Eject Contents
-ui-disposal-unit-button-power = Power
-
-ui-disposal-unit-is-valid-interaction-cannot=interact = You can't do that!
-ui-disposal-unit-is-valid-interaction-cannot-reach = You can't reach there!
-ui-disposal-unit-is-valid-interaction-no-hands = You have no hands.
\ No newline at end of file
+ui-disposal-unit-button-power = Power
\ No newline at end of file