Click Drag Functionality + Refactor Interaction Interfaces (#1125)

Co-authored-by: Víctor Aguilera Puerto <6766154+Zumorica@users.noreply.github.com>
Co-authored-by: ComicIronic <comicironic@gmail.com>
Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com>
This commit is contained in:
chairbender
2020-07-06 14:27:03 -07:00
committed by GitHub
parent c019d428a7
commit b35333d366
184 changed files with 1792 additions and 895 deletions

View File

@@ -0,0 +1,53 @@
using System;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
namespace Content.Server.Interfaces.GameObjects.Components.Interaction
{
/// <summary>
/// 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 who is in range.
/// </summary>
void Activate(ActivateEventArgs eventArgs);
}
public class ActivateEventArgs : EventArgs, ITargetedInteractEventArgs
{
public IEntity User { get; set; }
public IEntity Target { get; set; }
}
/// <summary>
/// Raised when an entity is activated in the world.
/// </summary>
[PublicAPI]
public class ActivateInWorldMessage : EntitySystemMessage
{
/// <summary>
/// If this message has already been "handled" by a previous system.
/// </summary>
public bool Handled { get; set; }
/// <summary>
/// Entity that activated the world entity.
/// </summary>
public IEntity User { get; }
/// <summary>
/// Entity that was activated in the world.
/// </summary>
public IEntity Activated { get; }
public ActivateInWorldMessage(IEntity user, IEntity activated)
{
User = user;
Activated = activated;
}
}
}

View File

@@ -0,0 +1,68 @@
using System;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Map;
namespace Content.Server.Interfaces.GameObjects.Components.Interaction
{
/// <summary>
/// This interface gives components a behavior when clicking on another object and no interaction occurs,
/// at any range.
/// </summary>
public interface IAfterInteract
{
/// <summary>
/// Called when we interact with nothing, or when we interact with an entity out of range that has no behavior
/// </summary>
void AfterInteract(AfterInteractEventArgs eventArgs);
}
public class AfterInteractEventArgs : EventArgs
{
public IEntity User { get; set; }
public GridCoordinates ClickLocation { get; set; }
public IEntity Target { get; set; }
}
/// <summary>
/// Raised when clicking on another object and no attack event was handled.
/// </summary>
[PublicAPI]
public class AfterInteractMessage : EntitySystemMessage
{
/// <summary>
/// If this message has already been "handled" by a previous system.
/// </summary>
public bool Handled { get; set; }
/// <summary>
/// Entity that triggered the attack.
/// </summary>
public IEntity User { get; }
/// <summary>
/// Entity that the User attacked with.
/// </summary>
public IEntity ItemInHand { get; set; }
/// <summary>
/// Entity that was attacked. This can be null if the attack did not click on an entity.
/// </summary>
public IEntity Attacked { get; }
/// <summary>
/// Location that the user clicked outside of their interaction range.
/// </summary>
public GridCoordinates ClickLocation { get; }
public AfterInteractMessage(IEntity user, IEntity itemInHand, IEntity attacked, GridCoordinates clickLocation)
{
User = user;
Attacked = attacked;
ClickLocation = clickLocation;
ItemInHand = itemInHand;
}
}
}

View File

@@ -0,0 +1,26 @@
using System;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Map;
namespace Content.Server.Interfaces.GameObjects.Components.Interaction
{
/// <summary>
/// This interface gives components behavior when being used to "attack".
/// </summary>
public interface IAttack
{
void Attack(AttackEventArgs eventArgs);
}
public class AttackEventArgs : EventArgs
{
public AttackEventArgs(IEntity user, GridCoordinates clickLocation)
{
User = user;
ClickLocation = clickLocation;
}
public IEntity User { get; }
public GridCoordinates ClickLocation { get; }
}
}

View File

@@ -0,0 +1,40 @@
using System;
using Content.Server.Interfaces.GameObjects.Components.Interaction;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Map;
namespace Content.Server.Interfaces.GameObjects.Components.Interaction
{
/// <summary>
/// This interface allows the component's entity to be dragged and dropped by mouse onto another entity and gives it
/// behavior when that occurs.
/// </summary>
public interface IDragDrop
{
/// <summary>
/// Invoked server-side when this component's entity is being dragged and dropped on another.
///
/// There is no other server-side drag and drop check other than a range check, so make sure to validate
/// if this object can be dropped on the target object!
/// </summary>
/// <returns>true iff an interaction occurred and no further interaction should
/// be processed for this drop.</returns>
bool DragDrop(DragDropEventArgs eventArgs);
}
public class DragDropEventArgs : EventArgs
{
public DragDropEventArgs(IEntity user, GridCoordinates dropLocation, IEntity dropped, IEntity target)
{
User = user;
DropLocation = dropLocation;
Dropped = dropped;
Target = target;
}
public IEntity User { get; }
public GridCoordinates DropLocation { get; }
public IEntity Dropped { get; }
public IEntity Target { get; }
}
}

View File

@@ -0,0 +1,24 @@
using System;
using Content.Server.Interfaces.GameObjects.Components.Interaction;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Map;
namespace Content.Server.Interfaces.GameObjects.Components.Interaction
{
/// <summary>
/// This interface allows the component's entity to be dragged and dropped onto by another entity and gives it
/// behavior when that occurs.
/// </summary>
public interface IDragDropOn
{
/// <summary>
/// Invoked server-side when another entity is being dragged and dropped onto this one
///
/// There is no other server-side drag and drop check other than a range check, so make sure to validate
/// if this object can be dropped on the dropped object!
/// </summary>
/// <returns>true iff an interaction occurred and no further interaction should
/// be processed for this drop.</returns>
bool DragDropOn(DragDropEventArgs eventArgs);
}
}

View File

@@ -0,0 +1,53 @@
using System;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
namespace Content.Server.Interfaces.GameObjects.Components.Interaction
{
/// <summary>
/// This interface gives components behavior when they're dropped by a mob.
/// </summary>
public interface IDropped
{
void Dropped(DroppedEventArgs eventArgs);
}
public class DroppedEventArgs : EventArgs
{
public DroppedEventArgs(IEntity user)
{
User = user;
}
public IEntity User { get; }
}
/// <summary>
/// Raised when an entity is dropped
/// </summary>
[PublicAPI]
public class DroppedMessage : EntitySystemMessage
{
/// <summary>
/// If this message has already been "handled" by a previous system.
/// </summary>
public bool Handled { get; set; }
/// <summary>
/// Entity that dropped the item.
/// </summary>
public IEntity User { get; }
/// <summary>
/// Item that was dropped.
/// </summary>
public IEntity Dropped { get; }
public DroppedMessage(IEntity user, IEntity dropped)
{
User = user;
Dropped = dropped;
}
}
}

View File

@@ -0,0 +1,62 @@
using System;
using Content.Shared.GameObjects.Components.Inventory;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
namespace Content.Server.Interfaces.GameObjects.Components.Interaction
{
/// <summary>
/// This interface gives components behavior when their owner is put in an inventory slot.
/// </summary>
public interface IEquipped
{
void Equipped(EquippedEventArgs eventArgs);
}
public class EquippedEventArgs : EventArgs
{
public EquippedEventArgs(IEntity user, EquipmentSlotDefines.Slots slot)
{
User = user;
Slot = slot;
}
public IEntity User { get; }
public EquipmentSlotDefines.Slots Slot { get; }
}
/// <summary>
/// Raised when equipping the entity in an inventory slot.
/// </summary>
[PublicAPI]
public class EquippedMessage : EntitySystemMessage
{
/// <summary>
/// If this message has already been "handled" by a previous system.
/// </summary>
public bool Handled { get; set; }
/// <summary>
/// Entity that equipped the item.
/// </summary>
public IEntity User { get; }
/// <summary>
/// Item that was equipped.
/// </summary>
public IEntity Equipped { get; }
/// <summary>
/// Slot where the item was placed.
/// </summary>
public EquipmentSlotDefines.Slots Slot { get; }
public EquippedMessage(IEntity user, IEntity equipped, EquipmentSlotDefines.Slots slot)
{
User = user;
Equipped = equipped;
Slot = slot;
}
}
}

View File

@@ -0,0 +1,53 @@
using System;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
namespace Content.Server.Interfaces.GameObjects.Components.Interaction
{
/// <summary>
/// This interface gives components behavior when they're held on a deselected hand.
/// </summary>
public interface IHandDeselected
{
void HandDeselected(HandDeselectedEventArgs eventArgs);
}
public class HandDeselectedEventArgs : EventArgs
{
public HandDeselectedEventArgs(IEntity user)
{
User = user;
}
public IEntity User { get; }
}
/// <summary>
/// Raised when an entity item in a hand is deselected.
/// </summary>
[PublicAPI]
public class HandDeselectedMessage : EntitySystemMessage
{
/// <summary>
/// If this message has already been "handled" by a previous system.
/// </summary>
public bool Handled { get; set; }
/// <summary>
/// Entity that owns the deselected hand.
/// </summary>
public IEntity User { get; }
/// <summary>
/// The item in question.
/// </summary>
public IEntity Item { get; }
public HandDeselectedMessage(IEntity user, IEntity item)
{
User = user;
Item = item;
}
}
}

View File

@@ -0,0 +1,53 @@
using System;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
namespace Content.Server.Interfaces.GameObjects.Components.Interaction
{
/// <summary>
/// This interface gives components behavior when they're held on the selected hand.
/// </summary>
public interface IHandSelected
{
void HandSelected(HandSelectedEventArgs eventArgs);
}
public class HandSelectedEventArgs : EventArgs
{
public HandSelectedEventArgs(IEntity user)
{
User = user;
}
public IEntity User { get; }
}
/// <summary>
/// Raised when an entity item in a hand is selected.
/// </summary>
[PublicAPI]
public class HandSelectedMessage : EntitySystemMessage
{
/// <summary>
/// If this message has already been "handled" by a previous system.
/// </summary>
public bool Handled { get; set; }
/// <summary>
/// Entity that owns the selected hand.
/// </summary>
public IEntity User { get; }
/// <summary>
/// The item in question.
/// </summary>
public IEntity Item { get; }
public HandSelectedMessage(IEntity user, IEntity item)
{
User = user;
Item = item;
}
}
}

View File

@@ -0,0 +1,54 @@
using System;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
namespace Content.Server.Interfaces.GameObjects.Components.Interaction
{
/// <summary>
/// This interface gives components behavior when being clicked on 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 IInteractHand
{
/// <summary>
/// Called when a player directly interacts with an empty hand when user is in range of the target entity.
/// </summary>
bool InteractHand(InteractHandEventArgs eventArgs);
}
public class InteractHandEventArgs : EventArgs, ITargetedInteractEventArgs
{
public IEntity User { get; set; }
public IEntity Target { get; set; }
}
/// <summary>
/// Raised when being clicked on or "attacked" by a user with an empty hand.
/// </summary>
[PublicAPI]
public class AttackHandMessage : EntitySystemMessage
{
/// <summary>
/// If this message has already been "handled" by a previous system.
/// </summary>
public bool Handled { get; set; }
/// <summary>
/// Entity that triggered the attack.
/// </summary>
public IEntity User { get; }
/// <summary>
/// Entity that was attacked.
/// </summary>
public IEntity Attacked { get; }
public AttackHandMessage(IEntity user, IEntity attacked)
{
User = user;
Attacked = attacked;
}
}
}

View File

@@ -0,0 +1,68 @@
using System;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Map;
namespace Content.Server.Interfaces.GameObjects.Components.Interaction
{
/// <summary>
/// This interface gives components behavior when being clicked on 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 IInteractUsing
{
/// <summary>
/// Called when using one object on another when user is in range of the target entity.
/// </summary>
bool InteractUsing(InteractUsingEventArgs eventArgs);
}
public class InteractUsingEventArgs : EventArgs, ITargetedInteractEventArgs
{
public IEntity User { get; set; }
public GridCoordinates ClickLocation { get; set; }
public IEntity Using { get; set; }
public IEntity Target { get; set; }
}
/// <summary>
/// Raised when being clicked on or "attacked" by a user with an object in their hand
/// </summary>
[PublicAPI]
public class InteractUsingMessage : EntitySystemMessage
{
/// <summary>
/// If this message has already been "handled" by a previous system.
/// </summary>
public bool Handled { get; set; }
/// <summary>
/// Entity that triggered the attack.
/// </summary>
public IEntity User { get; }
/// <summary>
/// Entity that the User attacked with.
/// </summary>
public IEntity ItemInHand { get; }
/// <summary>
/// Entity that was attacked.
/// </summary>
public IEntity Attacked { get; }
/// <summary>
/// The original location that was clicked by the user.
/// </summary>
public GridCoordinates ClickLocation { get; }
public InteractUsingMessage(IEntity user, IEntity itemInHand, IEntity attacked, GridCoordinates clickLocation)
{
User = user;
ItemInHand = itemInHand;
Attacked = attacked;
ClickLocation = clickLocation;
}
}
}

View File

@@ -0,0 +1,62 @@
using System;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Map;
namespace Content.Server.Interfaces.GameObjects.Components.Interaction
{
/// <summary>
/// This interface gives components behavior when landing after being thrown.
/// </summary>
public interface ILand
{
void Land(LandEventArgs eventArgs);
}
public class LandEventArgs : EventArgs
{
public LandEventArgs(IEntity user, GridCoordinates landingLocation)
{
User = user;
LandingLocation = landingLocation;
}
public IEntity User { get; }
public GridCoordinates LandingLocation { get; }
}
/// <summary>
/// Raised when an entity that was thrown lands.
/// </summary>
[PublicAPI]
public class LandMessage : EntitySystemMessage
{
/// <summary>
/// If this message has already been "handled" by a previous system.
/// </summary>
public bool Handled { get; set; }
/// <summary>
/// Entity that threw the item.
/// </summary>
public IEntity User { get; }
/// <summary>
/// Item that was thrown.
/// </summary>
public IEntity Thrown { get; }
/// <summary>
/// Location where the item landed.
/// </summary>
public GridCoordinates LandLocation { get; }
public LandMessage(IEntity user, IEntity thrown, GridCoordinates landLocation)
{
User = user;
Thrown = thrown;
LandLocation = landLocation;
}
}
}

View File

@@ -0,0 +1,69 @@
using System;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Map;
namespace Content.Server.Interfaces.GameObjects.Components.Interaction
{
/// <summary>
/// This interface gives components behavior when being clicked on by a user with an object
/// outside the range of direct use
/// </summary>
public interface IRangedInteract
{
/// <summary>
/// Called when we try to interact with an entity out of range
/// </summary>
/// <returns></returns>
bool RangedInteract(RangedInteractEventArgs eventArgs);
}
[PublicAPI]
public class RangedInteractEventArgs : EventArgs
{
public IEntity User { get; set; }
public IEntity Using { get; set; }
public GridCoordinates ClickLocation { get; set; }
}
/// <summary>
/// Raised when being clicked by objects outside the range of direct use.
/// </summary>
[PublicAPI]
public class RangedInteractMessage : EntitySystemMessage
{
/// <summary>
/// If this message has already been "handled" by a previous system.
/// </summary>
public bool Handled { get; set; }
/// <summary>
/// Entity that triggered the attack.
/// </summary>
public IEntity User { get; }
/// <summary>
/// Entity that the User attacked with.
/// </summary>
public IEntity ItemInHand { get; set; }
/// <summary>
/// Entity that was attacked.
/// </summary>
public IEntity Attacked { get; }
/// <summary>
/// Location that the user clicked outside of their interaction range.
/// </summary>
public GridCoordinates ClickLocation { get; }
public RangedInteractMessage(IEntity user, IEntity itemInHand, IEntity attacked, GridCoordinates clickLocation)
{
User = user;
ItemInHand = itemInHand;
ClickLocation = clickLocation;
Attacked = attacked;
}
}
}

View File

@@ -0,0 +1,17 @@
using Robust.Shared.Interfaces.GameObjects;
namespace Content.Server.Interfaces.GameObjects.Components.Interaction
{
public interface ITargetedInteractEventArgs
{
/// <summary>
/// Performer of the attack
/// </summary>
IEntity User { get; }
/// <summary>
/// Target of the attack
/// </summary>
IEntity Target { get; }
}
}

View File

@@ -0,0 +1,53 @@
using System;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
namespace Content.Server.Interfaces.GameObjects.Components.Interaction
{
/// <summary>
/// This interface gives components behavior when thrown.
/// </summary>
public interface IThrown
{
void Thrown(ThrownEventArgs eventArgs);
}
public class ThrownEventArgs : EventArgs
{
public ThrownEventArgs(IEntity user)
{
User = user;
}
public IEntity User { get; }
}
/// <summary>
/// Raised when throwing the entity in your hands.
/// </summary>
[PublicAPI]
public class ThrownMessage : EntitySystemMessage
{
/// <summary>
/// If this message has already been "handled" by a previous system.
/// </summary>
public bool Handled { get; set; }
/// <summary>
/// Entity that threw the item.
/// </summary>
public IEntity User { get; }
/// <summary>
/// Item that was thrown.
/// </summary>
public IEntity Thrown { get; }
public ThrownMessage(IEntity user, IEntity thrown)
{
User = user;
Thrown = thrown;
}
}
}

View File

@@ -0,0 +1,64 @@
using System;
using Content.Shared.GameObjects.Components.Inventory;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
namespace Content.Server.Interfaces.GameObjects.Components.Interaction
{
/// <summary>
/// This interface gives components behavior when their owner is removed from an inventory slot.
/// </summary>
public interface IUnequipped
{
void Unequipped(UnequippedEventArgs eventArgs);
}
public class UnequippedEventArgs : EventArgs
{
public UnequippedEventArgs(IEntity user, EquipmentSlotDefines.Slots slot)
{
User = user;
Slot = slot;
}
public IEntity User { get; }
public EquipmentSlotDefines.Slots Slot { get; }
}
/// <summary>
/// Raised when removing the entity from an inventory slot.
/// </summary>
[PublicAPI]
public class UnequippedMessage : EntitySystemMessage
{
/// <summary>
/// If this message has already been "handled" by a previous system.
/// </summary>
public bool Handled { get; set; }
/// <summary>
/// Entity that equipped the item.
/// </summary>
public IEntity User { get; }
/// <summary>
/// Item that was equipped.
/// </summary>
public IEntity Equipped { get; }
/// <summary>
/// Slot where the item was removed from.
/// </summary>
public EquipmentSlotDefines.Slots Slot { get; }
public UnequippedMessage(IEntity user, IEntity equipped, EquipmentSlotDefines.Slots slot)
{
User = user;
Equipped = equipped;
Slot = slot;
}
}
}

View File

@@ -0,0 +1,52 @@
using System;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
namespace Content.Server.Interfaces.GameObjects.Components.Interaction
{
/// <summary>
/// This interface gives components behavior when using the entity in your hands
/// </summary>
public interface IUse
{
/// <summary>
/// Called when we activate an object we are holding to use it
/// </summary>
/// <returns></returns>
bool UseEntity(UseEntityEventArgs eventArgs);
}
public class UseEntityEventArgs : EventArgs
{
public IEntity User { get; set; }
}
/// <summary>
/// Raised when using the entity in your hands.
/// </summary>
[PublicAPI]
public class UseInHandMessage : EntitySystemMessage
{
/// <summary>
/// If this message has already been "handled" by a previous system.
/// </summary>
public bool Handled { get; set; }
/// <summary>
/// Entity holding the item in their hand.
/// </summary>
public IEntity User { get; }
/// <summary>
/// Item that was used.
/// </summary>
public IEntity Used { get; }
public UseInHandMessage(IEntity user, IEntity used)
{
User = user;
Used = used;
}
}
}