Add interaction checks to all interactions (#923)

This commit is contained in:
chairbender
2020-05-23 02:27:31 -07:00
committed by GitHub
parent af0ec2aeb9
commit 6a4d78cfac
63 changed files with 311 additions and 101 deletions

View File

@@ -11,6 +11,7 @@ using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Reflection;
using Robust.Shared.IoC;
using Robust.Shared.Utility;
namespace Content.Server.GameObjects.EntitySystems
{
@@ -101,7 +102,7 @@ namespace Content.Server.GameObjects.EntitySystems
var processorId = args[0];
var entId = new EntityUid(int.Parse(args[1]));
var ent = IoCManager.Resolve<IEntityManager>().GetEntity(entId);
var aiSystem = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<AiSystem>();
var aiSystem = EntitySystem.Get<AiSystem>();
if (!aiSystem.ProcessorTypeExists(processorId))
{

View File

@@ -3,6 +3,7 @@ using System.Linq;
using Content.Server.GameObjects.Components.Mobs;
using Content.Server.GameObjects.Components.Timing;
using Content.Server.Interfaces.GameObjects;
using Content.Server.Utility;
using Content.Shared.GameObjects.Components.Inventory;
using Content.Shared.Input;
using Content.Shared.Physics;
@@ -18,6 +19,7 @@ using Robust.Shared.Interfaces.GameObjects.Components;
using Robust.Shared.Interfaces.Map;
using Robust.Shared.Interfaces.Physics;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Log;
using Robust.Shared.Map;
using Robust.Shared.Maths;
@@ -27,36 +29,53 @@ namespace Content.Server.GameObjects.EntitySystems
{
/// <summary>
/// This interface gives components behavior when being clicked on or "attacked" by a user with an object in their hand
/// who is in range and has unobstructed reach of the target entity (allows inside blockers).
/// </summary>
public interface IAttackBy
{
/// <summary>
/// Called when using one object on another
/// Called when using one object on another when user is in range of the target entity.
/// </summary>
bool AttackBy(AttackByEventArgs eventArgs);
}
public class AttackByEventArgs : EventArgs
public class AttackByEventArgs : EventArgs, ITargetedAttackEventArgs
{
public IEntity User { get; set; }
public GridCoordinates ClickLocation { get; set; }
public IEntity AttackWith { get; set; }
public IEntity Attacked { get; set; }
}
public interface ITargetedAttackEventArgs
{
/// <summary>
/// Performer of the attack
/// </summary>
IEntity User { get; }
/// <summary>
/// Target of the attack
/// </summary>
IEntity Attacked { get; }
}
/// <summary>
/// This interface gives components behavior when being clicked on or "attacked" by a user with an empty hand
/// who is in range and has unobstructed reach of the target entity (allows inside blockers).
/// </summary>
public interface IAttackHand
{
/// <summary>
/// Called when a player directly interacts with an empty hand
/// Called when a player directly interacts with an empty hand when user is in range of the target entity.
/// </summary>
bool AttackHand(AttackHandEventArgs eventArgs);
}
public class AttackHandEventArgs : EventArgs
public class AttackHandEventArgs : EventArgs, ITargetedAttackEventArgs
{
public IEntity User { get; set; }
public IEntity Attacked { get; set; }
}
/// <summary>
@@ -80,8 +99,8 @@ namespace Content.Server.GameObjects.EntitySystems
}
/// <summary>
/// This interface gives components a behavior when clicking on another object and no interaction occurs
/// Doesn't pass what you clicked on as an argument, but if it becomes necessary we can add it later
/// This interface gives components a behavior when clicking on another object and no interaction occurs,
/// at any range.
/// </summary>
public interface IAfterAttack
{
@@ -116,19 +135,21 @@ namespace Content.Server.GameObjects.EntitySystems
}
/// <summary>
/// This interface gives components behavior when being activated in the world.
/// This interface gives components behavior when being activated in the world when the user
/// is in range and has unobstructed access to the target entity (allows inside blockers).
/// </summary>
public interface IActivate
{
/// <summary>
/// Called when this component is activated by another entity.
/// Called when this component is activated by another entity who is in range.
/// </summary>
void Activate(ActivateEventArgs eventArgs);
}
public class ActivateEventArgs : EventArgs
public class ActivateEventArgs : EventArgs, ITargetedAttackEventArgs
{
public IEntity User { get; set; }
public IEntity Attacked { get; set; }
}
/// <summary>
@@ -292,6 +313,7 @@ namespace Content.Server.GameObjects.EntitySystems
#pragma warning disable 649
[Dependency] private readonly IMapManager _mapManager;
[Dependency] private readonly IPhysicsManager _physicsManager;
[Dependency] private readonly ILocalizationManager _localizationManager;
#pragma warning restore 649
public const float InteractionRange = 2;
@@ -359,7 +381,12 @@ namespace Content.Server.GameObjects.EntitySystems
return;
}
activateComp.Activate(new ActivateEventArgs {User = user});
// all activates should only fire when in range / unbostructed
var activateEventArgs = new ActivateEventArgs {User = user, Attacked = used};
if (InteractionChecks.InRangeUnobstructed(activateEventArgs))
{
activateComp.Activate(activateEventArgs);
}
}
private bool HandleWideAttack(ICommonSession session, GridCoordinates coords, EntityUid uid)
@@ -556,15 +583,19 @@ namespace Content.Server.GameObjects.EntitySystems
var attackBys = attacked.GetAllComponents<IAttackBy>().ToList();
var attackByEventArgs = new AttackByEventArgs
{
User = user, ClickLocation = clickLocation, AttackWith = weapon
User = user, ClickLocation = clickLocation, AttackWith = weapon, Attacked = attacked
};
foreach (var attackBy in attackBys)
// all AttackBys should only happen when in range / unobstructed, so no range check is needed
if (InteractionChecks.InRangeUnobstructed(attackByEventArgs))
{
if (attackBy.AttackBy(attackByEventArgs))
foreach (var attackBy in attackBys)
{
// If an AttackBy returns a status completion we finish our attack
return;
if (attackBy.AttackBy(attackByEventArgs))
{
// If an AttackBy returns a status completion we finish our attack
return;
}
}
}
@@ -602,14 +633,18 @@ namespace Content.Server.GameObjects.EntitySystems
}
var attackHands = attacked.GetAllComponents<IAttackHand>().ToList();
var attackHandEventArgs = new AttackHandEventArgs {User = user};
var attackHandEventArgs = new AttackHandEventArgs {User = user, Attacked = attacked};
foreach (var attackHand in attackHands)
// all attackHands should only fire when in range / unbostructed
if (InteractionChecks.InRangeUnobstructed(attackHandEventArgs))
{
if (attackHand.AttackHand(attackHandEventArgs))
foreach (var attackHand in attackHands)
{
// If an AttackHand returns a status completion we finish our attack
return;
if (attackHand.AttackHand(attackHandEventArgs))
{
// If an AttackHand returns a status completion we finish our attack
return;
}
}
}

View File

@@ -30,6 +30,7 @@ using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Physics;
using Robust.Shared.Players;
using Robust.Shared.Utility;
namespace Content.Server.GameObjects.EntitySystems
{
@@ -105,7 +106,7 @@ namespace Content.Server.GameObjects.EntitySystems
if (!TryGetAttachedComponent(session as IPlayerSession, out HandsComponent handsComp))
return;
var interactionSystem = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<InteractionSystem>();
var interactionSystem = EntitySystem.Get<InteractionSystem>();
var oldItem = handsComp.GetActiveHand;
@@ -133,9 +134,8 @@ namespace Content.Server.GameObjects.EntitySystems
if (handsComp.GetActiveHand == null)
return false;
var interactionSystem = _entitySystemManager.GetEntitySystem<InteractionSystem>();
if(interactionSystem.InRangeUnobstructed(coords.ToMap(_mapManager), ent.Transform.WorldPosition, ignoredEnt: ent))
if(EntitySystem.Get<SharedInteractionSystem>().InRangeUnobstructed(coords.ToMap(_mapManager), ent.Transform.WorldPosition, ignoredEnt: ent))
if (coords.InRange(_mapManager, ent.Transform.GridPosition, InteractionSystem.InteractionRange))
{
handsComp.Drop(handsComp.ActiveIndex, coords);