Adjust interaction ordering & interaction conditions (#6387)
This commit is contained in:
@@ -138,10 +138,7 @@ namespace Content.Server.Chemistry.Components
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!eventArgs.InRangeUnobstructed(ignoreInsideBlocker: true, popup: true))
|
if (!eventArgs.CanReach)
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!EntitySystem.Get<ActionBlockerSystem>().CanInteract(eventArgs.User))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var solutionsSys = EntitySystem.Get<SolutionContainerSystem>();
|
var solutionsSys = EntitySystem.Get<SolutionContainerSystem>();
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ namespace Content.Server.Chemistry.Components
|
|||||||
{
|
{
|
||||||
var solutionsSys = EntitySystem.Get<SolutionContainerSystem>();
|
var solutionsSys = EntitySystem.Get<SolutionContainerSystem>();
|
||||||
|
|
||||||
if (!eventArgs.InRangeUnobstructed() || eventArgs.Target == null)
|
if (!eventArgs.CanReach || eventArgs.Target == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!_entities.HasComponent<SolutionContainerManagerComponent>(Owner))
|
if (!_entities.HasComponent<SolutionContainerManagerComponent>(Owner))
|
||||||
|
|||||||
@@ -33,7 +33,8 @@ namespace Content.Server.Construction
|
|||||||
if (!EntityManager.TryGetComponent(args.Used, out ToolComponent? usedTool))
|
if (!EntityManager.TryGetComponent(args.Used, out ToolComponent? usedTool))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
args.Handled = await TryToggleAnchor(uid, args.User, args.Used, anchorable, usingTool:usedTool);
|
args.Handled = true;
|
||||||
|
await TryToggleAnchor(uid, args.User, args.Used, anchorable, usingTool:usedTool);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ namespace Content.Server.Crayon
|
|||||||
|
|
||||||
async Task<bool> IAfterInteract.AfterInteract(AfterInteractEventArgs eventArgs)
|
async Task<bool> IAfterInteract.AfterInteract(AfterInteractEventArgs eventArgs)
|
||||||
{
|
{
|
||||||
if (!eventArgs.InRangeUnobstructed(ignoreInsideBlocker: false, popup: true,
|
if (!eventArgs.User.InRangeUnobstructed(eventArgs.ClickLocation, ignoreInsideBlocker: false, popup: true,
|
||||||
collisionMask: Shared.Physics.CollisionGroup.MobImpassable))
|
collisionMask: Shared.Physics.CollisionGroup.MobImpassable))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ namespace Content.Server.Cuffs.Components
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!eventArgs.InRangeUnobstructed(ignoreInsideBlocker: true))
|
if (!eventArgs.CanReach)
|
||||||
{
|
{
|
||||||
eventArgs.User.PopupMessage(Loc.GetString("handcuff-component-too-far-away-error"));
|
eventArgs.User.PopupMessage(Loc.GetString("handcuff-component-too-far-away-error"));
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -63,8 +63,7 @@ namespace Content.Server.Disposal.Unit.EntitySystems
|
|||||||
|
|
||||||
// Interactions
|
// Interactions
|
||||||
SubscribeLocalEvent<DisposalUnitComponent, ActivateInWorldEvent>(HandleActivate);
|
SubscribeLocalEvent<DisposalUnitComponent, ActivateInWorldEvent>(HandleActivate);
|
||||||
SubscribeLocalEvent<DisposalUnitComponent, InteractHandEvent>(HandleInteractHand);
|
SubscribeLocalEvent<DisposalUnitComponent, AfterInteractUsingEvent>(HandleAfterInteractUsing);
|
||||||
SubscribeLocalEvent<DisposalUnitComponent, InteractUsingEvent>(HandleInteractUsing);
|
|
||||||
SubscribeLocalEvent<DisposalUnitComponent, DragDropEvent>(HandleDragDropOn);
|
SubscribeLocalEvent<DisposalUnitComponent, DragDropEvent>(HandleDragDropOn);
|
||||||
SubscribeLocalEvent<DisposalUnitComponent, DestructionEventArgs>(HandleDestruction);
|
SubscribeLocalEvent<DisposalUnitComponent, DestructionEventArgs>(HandleDestruction);
|
||||||
|
|
||||||
@@ -223,19 +222,11 @@ namespace Content.Server.Disposal.Unit.EntitySystems
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleInteractHand(EntityUid uid, DisposalUnitComponent component, InteractHandEvent args)
|
private void HandleAfterInteractUsing(EntityUid uid, DisposalUnitComponent component, AfterInteractUsingEvent args)
|
||||||
{
|
{
|
||||||
if (!EntityManager.TryGetComponent(args.User, out ActorComponent? actor)) return;
|
if (args.Handled || !args.CanReach)
|
||||||
|
return;
|
||||||
|
|
||||||
// Duplicated code here, not sure how else to get actor inside to make UserInterface happy.
|
|
||||||
|
|
||||||
if (!IsValidInteraction(args)) return;
|
|
||||||
component.Owner.GetUIOrNull(SharedDisposalUnitComponent.DisposalUnitUiKey.Key)?.Open(actor.PlayerSession);
|
|
||||||
args.Handled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void HandleInteractUsing(EntityUid uid, DisposalUnitComponent component, InteractUsingEvent args)
|
|
||||||
{
|
|
||||||
if (!EntityManager.TryGetComponent(args.User, out HandsComponent? hands))
|
if (!EntityManager.TryGetComponent(args.User, out HandsComponent? hands))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -103,14 +103,13 @@ namespace Content.Server.Fluids.Components
|
|||||||
var solutionSystem = EntitySystem.Get<SolutionContainerSystem>();
|
var solutionSystem = EntitySystem.Get<SolutionContainerSystem>();
|
||||||
var spillableSystem = EntitySystem.Get<SpillableSystem>();
|
var spillableSystem = EntitySystem.Get<SpillableSystem>();
|
||||||
|
|
||||||
if (!solutionSystem.TryGetSolution(Owner, SolutionName, out var contents ) ||
|
if (!eventArgs.CanReach ||
|
||||||
Mopping ||
|
!solutionSystem.TryGetSolution(Owner, SolutionName, out var contents ) ||
|
||||||
!eventArgs.InRangeUnobstructed(ignoreInsideBlocker: true, popup: true))
|
Mopping)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (eventArgs.Target is not {Valid: true} target)
|
if (eventArgs.Target is not {Valid: true} target)
|
||||||
{
|
{
|
||||||
// Drop the liquid on the mop on to the ground
|
// Drop the liquid on the mop on to the ground
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ namespace Content.Server.Guardian
|
|||||||
|
|
||||||
private void OnCreatorInteract(EntityUid uid, GuardianCreatorComponent component, AfterInteractEvent args)
|
private void OnCreatorInteract(EntityUid uid, GuardianCreatorComponent component, AfterInteractEvent args)
|
||||||
{
|
{
|
||||||
if (args.Handled || args.Target == null) return;
|
if (args.Handled || args.Target == null || !args.CanReach) return;
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
UseCreator(args.User, args.Target.Value, component);
|
UseCreator(args.User, args.Target.Value, component);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -234,10 +234,10 @@ namespace Content.Server.Interaction
|
|||||||
/// Finds components with the InteractHand interface and calls their function
|
/// Finds components with the InteractHand interface and calls their function
|
||||||
/// NOTE: Does not have an InRangeUnobstructed check
|
/// NOTE: Does not have an InRangeUnobstructed check
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public override void InteractHand(EntityUid user, EntityUid target)
|
public override void InteractHand(EntityUid user, EntityUid target, bool checkActionBlocker = true)
|
||||||
{
|
{
|
||||||
// TODO PREDICTION move server-side interaction logic into the shared system for interaction prediction.
|
// TODO PREDICTION move server-side interaction logic into the shared system for interaction prediction.
|
||||||
if (!_actionBlockerSystem.CanInteract(user))
|
if (checkActionBlocker && !_actionBlockerSystem.CanInteract(user))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// all interactions should only happen when in range / unobstructed, so no range check is needed
|
// all interactions should only happen when in range / unobstructed, so no range check is needed
|
||||||
@@ -270,7 +270,7 @@ namespace Content.Server.Interaction
|
|||||||
public override async Task<bool> InteractUsingRanged(EntityUid user, EntityUid used, EntityUid? target, EntityCoordinates clickLocation, bool inRangeUnobstructed)
|
public override async Task<bool> 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.
|
// TODO PREDICTION move server-side interaction logic into the shared system for interaction prediction.
|
||||||
if (InteractDoBefore(user, used, inRangeUnobstructed ? target : null, clickLocation, false))
|
if (InteractDoBefore(user, used, target, clickLocation, inRangeUnobstructed))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (target != null)
|
if (target != null)
|
||||||
@@ -282,7 +282,7 @@ namespace Content.Server.Interaction
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return await InteractDoAfter(user, used, inRangeUnobstructed ? target : null, clickLocation, false);
|
return await InteractDoAfter(user, used, target, clickLocation, inRangeUnobstructed);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void DoAttack(EntityUid user, EntityCoordinates coordinates, bool wideAttack, EntityUid? target = null)
|
public override void DoAttack(EntityUid user, EntityCoordinates coordinates, bool wideAttack, EntityUid? target = null)
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ namespace Content.Server.Labels
|
|||||||
|
|
||||||
private void AfterInteractOn(EntityUid uid, HandLabelerComponent handLabeler, AfterInteractEvent args)
|
private void AfterInteractOn(EntityUid uid, HandLabelerComponent handLabeler, AfterInteractEvent args)
|
||||||
{
|
{
|
||||||
if (args.Target is not {Valid: true} target || !handLabeler.Whitelist.IsValid(target))
|
if (args.Target is not {Valid: true} target || !handLabeler.Whitelist.IsValid(target) || !args.CanReach)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
AddLabelTo(uid, handLabeler, target, out string? result);
|
AddLabelTo(uid, handLabeler, target, out string? result);
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ namespace Content.Server.Medical.Components
|
|||||||
|
|
||||||
async Task<bool> IAfterInteract.AfterInteract(AfterInteractEventArgs eventArgs)
|
async Task<bool> IAfterInteract.AfterInteract(AfterInteractEventArgs eventArgs)
|
||||||
{
|
{
|
||||||
if (eventArgs.Target == null)
|
if (eventArgs.Target == null || !eventArgs.CanReach)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -54,12 +54,6 @@ namespace Content.Server.Medical.Components
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eventArgs.User != eventArgs.Target &&
|
|
||||||
!eventArgs.InRangeUnobstructed(ignoreInsideBlocker: true, popup: true))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_entMan.TryGetComponent<SharedStackComponent?>(Owner, out var stack) && !EntitySystem.Get<StackSystem>().Use(Owner, 1, stack))
|
if (_entMan.TryGetComponent<SharedStackComponent?>(Owner, out var stack) && !EntitySystem.Get<StackSystem>().Use(Owner, 1, stack))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -130,30 +130,15 @@ namespace Content.Server.Nutrition.EntitySystems
|
|||||||
|
|
||||||
private void AfterInteract(EntityUid uid, DrinkComponent component, AfterInteractEvent args)
|
private void AfterInteract(EntityUid uid, DrinkComponent component, AfterInteractEvent args)
|
||||||
{
|
{
|
||||||
if (args.Handled || args.Target == null)
|
if (args.Handled || args.Target == null || !args.CanReach)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!_actionBlockerSystem.CanInteract(args.User) || !_actionBlockerSystem.CanUse(args.User))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!args.User.InRangeUnobstructed(uid, popup: true))
|
|
||||||
{
|
|
||||||
args.Handled = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.User == args.Target)
|
if (args.User == args.Target)
|
||||||
{
|
{
|
||||||
args.Handled = TryUseDrink(uid, args.User);
|
args.Handled = TryUseDrink(uid, args.User);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!args.User.InRangeUnobstructed(args.Target.Value, popup: true))
|
|
||||||
{
|
|
||||||
args.Handled = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.User == args.Target)
|
if (args.User == args.Target)
|
||||||
args.Handled = TryUseDrink(uid, args.User, component);
|
args.Handled = TryUseDrink(uid, args.User, component);
|
||||||
else
|
else
|
||||||
@@ -164,15 +149,6 @@ namespace Content.Server.Nutrition.EntitySystems
|
|||||||
{
|
{
|
||||||
if (args.Handled) return;
|
if (args.Handled) return;
|
||||||
|
|
||||||
if (!_actionBlockerSystem.CanInteract(args.User) || !_actionBlockerSystem.CanUse(args.User))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!args.User.InRangeUnobstructed(uid, popup: true))
|
|
||||||
{
|
|
||||||
args.Handled = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!component.Opened)
|
if (!component.Opened)
|
||||||
{
|
{
|
||||||
//Do the opening stuff like playing the sounds.
|
//Do the opening stuff like playing the sounds.
|
||||||
|
|||||||
@@ -77,15 +77,6 @@ namespace Content.Server.Nutrition.EntitySystems
|
|||||||
if (ev.Handled)
|
if (ev.Handled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!_actionBlockerSystem.CanInteract(ev.User) || !_actionBlockerSystem.CanUse(ev.User))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!ev.User.InRangeUnobstructed(uid, popup: true))
|
|
||||||
{
|
|
||||||
ev.Handled = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ev.Handled = TryUseFood(uid, ev.User);
|
ev.Handled = TryUseFood(uid, ev.User);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,30 +85,15 @@ namespace Content.Server.Nutrition.EntitySystems
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void OnFeedFood(EntityUid uid, FoodComponent foodComponent, AfterInteractEvent args)
|
private void OnFeedFood(EntityUid uid, FoodComponent foodComponent, AfterInteractEvent args)
|
||||||
{
|
{
|
||||||
if (args.Handled || args.Target == null)
|
if (args.Handled || args.Target == null || !args.CanReach)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!_actionBlockerSystem.CanInteract(args.User) || !_actionBlockerSystem.CanUse(args.User))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!args.User.InRangeUnobstructed(uid, popup: true))
|
|
||||||
{
|
|
||||||
args.Handled = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.User == args.Target)
|
if (args.User == args.Target)
|
||||||
{
|
{
|
||||||
args.Handled = TryUseFood(uid, args.User);
|
args.Handled = TryUseFood(uid, args.User);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!args.User.InRangeUnobstructed(args.Target.Value, popup: true))
|
|
||||||
{
|
|
||||||
args.Handled = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
args.Handled = TryForceFeed(uid, args.User, args.Target.Value);
|
args.Handled = TryForceFeed(uid, args.User, args.Target.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ namespace Content.Server.Nutrition.EntitySystems
|
|||||||
{
|
{
|
||||||
var targetEntity = args.Target;
|
var targetEntity = args.Target;
|
||||||
if (targetEntity == null ||
|
if (targetEntity == null ||
|
||||||
|
!args.CanReach ||
|
||||||
!EntityManager.TryGetComponent(uid, out SmokableComponent? smokable) ||
|
!EntityManager.TryGetComponent(uid, out SmokableComponent? smokable) ||
|
||||||
smokable.State == SmokableState.Lit)
|
smokable.State == SmokableState.Lit)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ namespace Content.Server.Nutrition.EntitySystems
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void OnAfterInteract(EntityUid uid, UtensilComponent component, AfterInteractEvent ev)
|
private void OnAfterInteract(EntityUid uid, UtensilComponent component, AfterInteractEvent ev)
|
||||||
{
|
{
|
||||||
if (ev.Target == null)
|
if (ev.Target == null || !ev.CanReach)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (TryUseUtensil(ev.User, ev.Target.Value, component))
|
if (TryUseUtensil(ev.User, ev.Target.Value, component))
|
||||||
|
|||||||
@@ -16,13 +16,10 @@ public sealed partial class CableSystem
|
|||||||
|
|
||||||
private void OnCablePlacerAfterInteract(EntityUid uid, CablePlacerComponent component, AfterInteractEvent args)
|
private void OnCablePlacerAfterInteract(EntityUid uid, CablePlacerComponent component, AfterInteractEvent args)
|
||||||
{
|
{
|
||||||
if (args.Handled) return;
|
if (args.Handled || !args.CanReach) return;
|
||||||
|
|
||||||
if (component.CablePrototypeId == null) return;
|
if (component.CablePrototypeId == null) return;
|
||||||
|
|
||||||
if (!args.InRangeUnobstructed(ignoreInsideBlocker: true, popup: true))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(!_mapManager.TryGetGrid(args.ClickLocation.GetGridId(EntityManager), out var grid))
|
if(!_mapManager.TryGetGrid(args.ClickLocation.GetGridId(EntityManager), out var grid))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ namespace Content.Server.RCD.Systems
|
|||||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||||
|
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
||||||
|
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
|
||||||
|
|
||||||
private readonly RcdMode[] _modes = (RcdMode[]) Enum.GetValues(typeof(RcdMode));
|
private readonly RcdMode[] _modes = (RcdMode[]) Enum.GetValues(typeof(RcdMode));
|
||||||
|
|
||||||
@@ -60,7 +61,7 @@ namespace Content.Server.RCD.Systems
|
|||||||
|
|
||||||
private async void OnAfterInteract(EntityUid uid, RCDComponent rcd, AfterInteractEvent args)
|
private async void OnAfterInteract(EntityUid uid, RCDComponent rcd, AfterInteractEvent args)
|
||||||
{
|
{
|
||||||
if (args.Handled)
|
if (args.Handled || !args.CanReach)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// FIXME: Make this work properly. Right now it relies on the click location being on a grid, which is bad.
|
// FIXME: Make this work properly. Right now it relies on the click location being on a grid, which is bad.
|
||||||
@@ -159,7 +160,8 @@ namespace Content.Server.RCD.Systems
|
|||||||
}
|
}
|
||||||
|
|
||||||
var coordinates = mapGrid.ToCoordinates(tile.GridIndices);
|
var coordinates = mapGrid.ToCoordinates(tile.GridIndices);
|
||||||
if (coordinates == EntityCoordinates.Invalid || !eventArgs.InRangeUnobstructed(ignoreInsideBlocker: true, popup: true))
|
if (coordinates == EntityCoordinates.Invalid ||
|
||||||
|
!_interactionSystem.InRangeUnobstructed(eventArgs.User, coordinates, ignoreInsideBlocker: true, popup: true))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -558,7 +558,7 @@ namespace Content.Server.Storage.Components
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
async Task<bool> IAfterInteract.AfterInteract(AfterInteractEventArgs eventArgs)
|
async Task<bool> IAfterInteract.AfterInteract(AfterInteractEventArgs eventArgs)
|
||||||
{
|
{
|
||||||
if (!eventArgs.InRangeUnobstructed(ignoreInsideBlocker: true, popup: true)) return false;
|
if (!eventArgs.CanReach) return false;
|
||||||
|
|
||||||
// Pick up all entities in a radius around the clicked location.
|
// Pick up all entities in a radius around the clicked location.
|
||||||
// The last half of the if is because carpets exist and this is terrible
|
// The last half of the if is because carpets exist and this is terrible
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ namespace Content.Server.Tiles
|
|||||||
|
|
||||||
async Task<bool> IAfterInteract.AfterInteract(AfterInteractEventArgs eventArgs)
|
async Task<bool> IAfterInteract.AfterInteract(AfterInteractEventArgs eventArgs)
|
||||||
{
|
{
|
||||||
if (!eventArgs.InRangeUnobstructed(ignoreInsideBlocker: true, popup: true))
|
if (!eventArgs.CanReach)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!_entMan.TryGetComponent(Owner, out StackComponent? stack))
|
if (!_entMan.TryGetComponent(Owner, out StackComponent? stack))
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ public sealed partial class ToolSystem
|
|||||||
|
|
||||||
private void OnTilePryingAfterInteract(EntityUid uid, TilePryingComponent component, AfterInteractEvent args)
|
private void OnTilePryingAfterInteract(EntityUid uid, TilePryingComponent component, AfterInteractEvent args)
|
||||||
{
|
{
|
||||||
if (args.Handled) return;
|
if (args.Handled || !args.CanReach) return;
|
||||||
|
|
||||||
if (TryPryTile(args.User, component, args.ClickLocation))
|
if (TryPryTile(args.User, component, args.ClickLocation))
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace Content.Server.Traitor.Uplink.Telecrystal
|
|||||||
|
|
||||||
private void OnAfterInteract(EntityUid uid, TelecrystalComponent component, AfterInteractEvent args)
|
private void OnAfterInteract(EntityUid uid, TelecrystalComponent component, AfterInteractEvent args)
|
||||||
{
|
{
|
||||||
if (args.Handled)
|
if (args.Handled || !args.CanReach)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (args.Target == null || !EntityManager.TryGetComponent(args.Target.Value, out UplinkComponent? uplink))
|
if (args.Target == null || !EntityManager.TryGetComponent(args.Target.Value, out UplinkComponent? uplink))
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ namespace Content.Server.Weapon.Melee
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void OnAfterInteract(EntityUid owner, MeleeWeaponComponent comp, AfterInteractEvent args)
|
private void OnAfterInteract(EntityUid owner, MeleeWeaponComponent comp, AfterInteractEvent args)
|
||||||
{
|
{
|
||||||
if (!args.CanReach)
|
if (args.Handled || !args.CanReach)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var curTime = _gameTiming.CurTime;
|
var curTime = _gameTiming.CurTime;
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ public sealed partial class GunSystem
|
|||||||
|
|
||||||
private void OnSpeedLoaderAfterInteract(EntityUid uid, SpeedLoaderComponent component, AfterInteractEvent args)
|
private void OnSpeedLoaderAfterInteract(EntityUid uid, SpeedLoaderComponent component, AfterInteractEvent args)
|
||||||
{
|
{
|
||||||
if (args.Handled) return;
|
if (args.Handled || !args.CanReach) return;
|
||||||
|
|
||||||
if (args.Target == null)
|
if (args.Target == null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -31,8 +31,7 @@ namespace Content.Shared.Interaction
|
|||||||
public EntityCoordinates ClickLocation { get; }
|
public EntityCoordinates ClickLocation { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Is the click location close enough to reach by the player? This does not check for obstructions, just that the target is within
|
/// Is the click location in range and unobstructed?
|
||||||
/// reach radius around the user.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool CanReach { get; }
|
public bool CanReach { get; }
|
||||||
|
|
||||||
|
|||||||
@@ -403,24 +403,6 @@ namespace Content.Shared.Interaction.Helpers
|
|||||||
{
|
{
|
||||||
return SharedInteractionSystem.InRangeUnobstructed(args.User, args.Target, range, collisionMask, predicate, ignoreInsideBlocker, popup);
|
return SharedInteractionSystem.InRangeUnobstructed(args.User, args.Target, range, collisionMask, predicate, ignoreInsideBlocker, popup);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool InRangeUnobstructed(
|
|
||||||
this AfterInteractEventArgs args,
|
|
||||||
float range = InteractionRange,
|
|
||||||
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
|
||||||
Ignored? predicate = null,
|
|
||||||
bool ignoreInsideBlocker = false,
|
|
||||||
bool popup = false)
|
|
||||||
{
|
|
||||||
var user = args.User;
|
|
||||||
var target = args.Target;
|
|
||||||
|
|
||||||
if (target == null)
|
|
||||||
return SharedInteractionSystem.InRangeUnobstructed(user, args.ClickLocation, range, collisionMask, predicate, ignoreInsideBlocker, popup);
|
|
||||||
else
|
|
||||||
return SharedInteractionSystem.InRangeUnobstructed(user, target.Value, range, collisionMask, predicate, ignoreInsideBlocker, popup);
|
|
||||||
|
|
||||||
}
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region EntityEventArgs
|
#region EntityEventArgs
|
||||||
@@ -444,23 +426,6 @@ namespace Content.Shared.Interaction.Helpers
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool InRangeUnobstructed(
|
|
||||||
this AfterInteractEvent args,
|
|
||||||
float range = InteractionRange,
|
|
||||||
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
|
||||||
Ignored? predicate = null,
|
|
||||||
bool ignoreInsideBlocker = false,
|
|
||||||
bool popup = false)
|
|
||||||
{
|
|
||||||
var user = args.User;
|
|
||||||
var target = args.Target;
|
|
||||||
|
|
||||||
if (target == null)
|
|
||||||
return SharedInteractionSystem.InRangeUnobstructed(user, args.ClickLocation, range, collisionMask, predicate, ignoreInsideBlocker, popup);
|
|
||||||
else
|
|
||||||
return SharedInteractionSystem.InRangeUnobstructed(user, target.Value, range, collisionMask, predicate, ignoreInsideBlocker, popup);
|
|
||||||
}
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,11 +45,8 @@ namespace Content.Shared.Interaction
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Raised directed on the used object when clicking on another object and no attack event was handled.
|
|
||||||
/// </summary>
|
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public class AfterInteractEvent : HandledEntityEventArgs
|
public abstract class InteractEvent : HandledEntityEventArgs
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Entity that triggered the interaction.
|
/// Entity that triggered the interaction.
|
||||||
@@ -62,7 +59,7 @@ namespace Content.Shared.Interaction
|
|||||||
public EntityUid Used { get; }
|
public EntityUid Used { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Entity that was interacted on. This can be null if the attack did not click on an entity.
|
/// Entity that was interacted on. This can be null if there was no target (e.g., clicking on tiles).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public EntityUid? Target { get; }
|
public EntityUid? Target { get; }
|
||||||
|
|
||||||
@@ -72,12 +69,11 @@ namespace Content.Shared.Interaction
|
|||||||
public EntityCoordinates ClickLocation { get; }
|
public EntityCoordinates ClickLocation { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Is the click location close enough to reach by the player? This does not check for obstructions, just that the target is within
|
/// Is the click location in range without obstructions?
|
||||||
/// reach radius around the user.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool CanReach { get; }
|
public bool CanReach { get; }
|
||||||
|
|
||||||
public AfterInteractEvent(EntityUid user, EntityUid used, EntityUid? target,
|
public InteractEvent(EntityUid user, EntityUid used, EntityUid? target,
|
||||||
EntityCoordinates clickLocation, bool canReach)
|
EntityCoordinates clickLocation, bool canReach)
|
||||||
{
|
{
|
||||||
User = user;
|
User = user;
|
||||||
@@ -87,4 +83,26 @@ namespace Content.Shared.Interaction
|
|||||||
CanReach = canReach;
|
CanReach = canReach;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raised directed on the used object when clicking on another object and no standard interaction occurred.
|
||||||
|
/// Used for low-priority interactions facilitated by the used entity.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class AfterInteractEvent : InteractEvent
|
||||||
|
{
|
||||||
|
public AfterInteractEvent(EntityUid user, EntityUid used, EntityUid? target,
|
||||||
|
EntityCoordinates clickLocation, bool canReach) : base(user, used, target, clickLocation, canReach)
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raised directed on the target when clicking on another object and no standard interaction occurred. Used for
|
||||||
|
/// low-priority interactions facilitated by the target entity.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class AfterInteractUsingEvent : InteractEvent
|
||||||
|
{
|
||||||
|
public AfterInteractUsingEvent(EntityUid user, EntityUid used, EntityUid? target,
|
||||||
|
EntityCoordinates clickLocation, bool canReach) : base(user, used, target, clickLocation, canReach)
|
||||||
|
{ }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ using Robust.Shared.Maths;
|
|||||||
using Robust.Shared.Physics;
|
using Robust.Shared.Physics;
|
||||||
using Robust.Shared.Players;
|
using Robust.Shared.Players;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
|
using Robust.Shared.Player;
|
||||||
|
|
||||||
#pragma warning disable 618
|
#pragma warning disable 618
|
||||||
|
|
||||||
@@ -42,6 +43,7 @@ namespace Content.Shared.Interaction
|
|||||||
[Dependency] private readonly SharedVerbSystem _verbSystem = default!;
|
[Dependency] private readonly SharedVerbSystem _verbSystem = default!;
|
||||||
[Dependency] private readonly SharedAdminLogSystem _adminLogSystem = default!;
|
[Dependency] private readonly SharedAdminLogSystem _adminLogSystem = default!;
|
||||||
[Dependency] private readonly RotateToFaceSystem _rotateToFaceSystem = default!;
|
[Dependency] private readonly RotateToFaceSystem _rotateToFaceSystem = default!;
|
||||||
|
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
|
||||||
[Dependency] protected readonly SharedContainerSystem ContainerSystem = default!;
|
[Dependency] protected readonly SharedContainerSystem ContainerSystem = default!;
|
||||||
|
|
||||||
public const float InteractionRange = 2;
|
public const float InteractionRange = 2;
|
||||||
@@ -166,14 +168,16 @@ namespace Content.Shared.Interaction
|
|||||||
var inRangeUnobstructed = user.InRangeUnobstructed(coordinates, ignoreInsideBlocker: true);
|
var inRangeUnobstructed = user.InRangeUnobstructed(coordinates, ignoreInsideBlocker: true);
|
||||||
if (target == null || !inRangeUnobstructed)
|
if (target == null || !inRangeUnobstructed)
|
||||||
{
|
{
|
||||||
if (!hands.TryGetActiveHeldEntity(out var heldEntity))
|
if (!hands.TryGetActiveHeldEntity(out var heldEntity) || !_actionBlockerSystem.CanUse(user))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!await InteractUsingRanged(user, heldEntity.Value, target, coordinates, inRangeUnobstructed) &&
|
if (await InteractUsingRanged(user, heldEntity.Value, target, coordinates, inRangeUnobstructed))
|
||||||
!inRangeUnobstructed)
|
return;
|
||||||
|
|
||||||
|
// Generate popup only if user actually tried to click on something.
|
||||||
|
if (!inRangeUnobstructed && target != null)
|
||||||
{
|
{
|
||||||
var message = Loc.GetString("interaction-system-user-interaction-cannot-reach");
|
_popupSystem.PopupCursor(Loc.GetString("interaction-system-user-interaction-cannot-reach"), Filter.Entities(user));
|
||||||
user.PopupMessage(message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -188,15 +192,15 @@ namespace Content.Shared.Interaction
|
|||||||
else if (!hands.TryGetActiveHeldEntity(out var heldEntity))
|
else if (!hands.TryGetActiveHeldEntity(out var heldEntity))
|
||||||
{
|
{
|
||||||
// Since our hand is empty we will use InteractHand/Activate
|
// Since our hand is empty we will use InteractHand/Activate
|
||||||
InteractHand(user, target.Value);
|
InteractHand(user, target.Value, checkActionBlocker: false);
|
||||||
}
|
}
|
||||||
else if (heldEntity != target)
|
else if (heldEntity != target && _actionBlockerSystem.CanUse(user))
|
||||||
{
|
{
|
||||||
await InteractUsing(user, heldEntity.Value, target.Value, coordinates);
|
await InteractUsing(user, heldEntity.Value, target.Value, coordinates, checkActionBlocker: false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void InteractHand(EntityUid user, EntityUid target)
|
public virtual void InteractHand(EntityUid user, EntityUid target, bool checkActionBlocker = true)
|
||||||
{
|
{
|
||||||
// TODO PREDICTION move server-side interaction logic into the shared system for interaction prediction.
|
// TODO PREDICTION move server-side interaction logic into the shared system for interaction prediction.
|
||||||
}
|
}
|
||||||
@@ -561,9 +565,9 @@ namespace Content.Shared.Interaction
|
|||||||
/// Finds components with the InteractUsing interface and calls their function
|
/// Finds components with the InteractUsing interface and calls their function
|
||||||
/// NOTE: Does not have an InRangeUnobstructed check
|
/// NOTE: Does not have an InRangeUnobstructed check
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public async Task InteractUsing(EntityUid user, EntityUid used, EntityUid target, EntityCoordinates clickLocation, bool predicted = false)
|
public async Task InteractUsing(EntityUid user, EntityUid used, EntityUid target, EntityCoordinates clickLocation, bool predicted = false, bool checkActionBlocker = true)
|
||||||
{
|
{
|
||||||
if (!_actionBlockerSystem.CanInteract(user))
|
if (checkActionBlocker && (!_actionBlockerSystem.CanInteract(user) || !_actionBlockerSystem.CanUse(user)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (InteractDoBefore(user, used, target, clickLocation, true))
|
if (InteractDoBefore(user, used, target, clickLocation, true))
|
||||||
@@ -585,12 +589,11 @@ namespace Content.Shared.Interaction
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we aren't directly interacting with the nearby object, lets see if our item has an after interact we can do
|
|
||||||
await InteractDoAfter(user, used, target, clickLocation, true);
|
await InteractDoAfter(user, used, target, clickLocation, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// We didn't click on any entity, try doing an AfterInteract on the click location
|
/// Used when clicking on an entity resulted in no other interaction. Used for low-priority interactions.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public async Task<bool> InteractDoAfter(EntityUid user, EntityUid used, EntityUid? target, EntityCoordinates clickLocation, bool canReach)
|
public async Task<bool> InteractDoAfter(EntityUid user, EntityUid used, EntityUid? target, EntityCoordinates clickLocation, bool canReach)
|
||||||
{
|
{
|
||||||
@@ -611,7 +614,12 @@ namespace Content.Shared.Interaction
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
if (target == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var afterInteractUsingEvent = new AfterInteractUsingEvent(user, used, target, clickLocation, canReach);
|
||||||
|
RaiseLocalEvent(target.Value, afterInteractUsingEvent, false);
|
||||||
|
return afterInteractEvent.Handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
#region ActivateItemInWorld
|
#region ActivateItemInWorld
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ namespace Content.Shared.Placeable
|
|||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
SubscribeLocalEvent<PlaceableSurfaceComponent, InteractUsingEvent>(OnInteractUsing);
|
SubscribeLocalEvent<PlaceableSurfaceComponent, AfterInteractUsingEvent>(OnAfterInteractUsing);
|
||||||
SubscribeLocalEvent<PlaceableSurfaceComponent, ComponentHandleState>(OnHandleState);
|
SubscribeLocalEvent<PlaceableSurfaceComponent, ComponentHandleState>(OnHandleState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,9 +44,9 @@ namespace Content.Shared.Placeable
|
|||||||
surface.Dirty();
|
surface.Dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnInteractUsing(EntityUid uid, PlaceableSurfaceComponent surface, InteractUsingEvent args)
|
private void OnAfterInteractUsing(EntityUid uid, PlaceableSurfaceComponent surface, AfterInteractUsingEvent args)
|
||||||
{
|
{
|
||||||
if (args.Handled)
|
if (args.Handled || !args.CanReach)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!surface.IsPlaceable)
|
if (!surface.IsPlaceable)
|
||||||
@@ -55,14 +55,11 @@ namespace Content.Shared.Placeable
|
|||||||
if(!EntityManager.TryGetComponent<SharedHandsComponent?>(args.User, out var handComponent))
|
if(!EntityManager.TryGetComponent<SharedHandsComponent?>(args.User, out var handComponent))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!args.ClickLocation.IsValid(EntityManager))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(!handComponent.TryDropEntity(args.Used, EntityManager.GetComponent<TransformComponent>(surface.Owner).Coordinates))
|
if(!handComponent.TryDropEntity(args.Used, EntityManager.GetComponent<TransformComponent>(surface.Owner).Coordinates))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (surface.PlaceCentered)
|
if (surface.PlaceCentered)
|
||||||
EntityManager.GetComponent<TransformComponent>(args.Used).LocalPosition = EntityManager.GetComponent<TransformComponent>(args.Target).LocalPosition + surface.PositionOffset;
|
EntityManager.GetComponent<TransformComponent>(args.Used).LocalPosition = EntityManager.GetComponent<TransformComponent>(uid).LocalPosition + surface.PositionOffset;
|
||||||
else
|
else
|
||||||
EntityManager.GetComponent<TransformComponent>(args.Used).Coordinates = args.ClickLocation;
|
EntityManager.GetComponent<TransformComponent>(args.Used).Coordinates = args.ClickLocation;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user