Interactable component system. (#9)

* InteractableComponent v1. Broken edition

* It works!
This commit is contained in:
Pieter-Jan Briers
2017-10-06 21:05:21 +02:00
committed by GitHub
parent 8c1fa84c6e
commit 7597cd9172
8 changed files with 174 additions and 22 deletions

View File

@@ -14,6 +14,7 @@ namespace Content.Client
factory.RegisterIgnore("Inventory");
factory.RegisterIgnore("Item");
factory.RegisterIgnore("Interactable");
factory.Register<HandsComponent>();
factory.RegisterReference<HandsComponent, IHandsComponent>();

View File

@@ -56,6 +56,8 @@
</ItemGroup>
<ItemGroup>
<Compile Include="EntryPoint.cs" />
<Compile Include="GameObjects\Components\Interactable\InteractableComponent.cs" />
<Compile Include="Interfaces\GameObjects\Components\Interactable\IInteractableComponent.cs" />
<Compile Include="Interfaces\GameObjects\Components\Items\IHandsComponent.cs" />
<Compile Include="Interfaces\GameObjects\Components\Items\IInventoryComponent.cs" />
<Compile Include="Interfaces\GameObjects\Components\Items\IItemComponent.cs" />

View File

@@ -20,6 +20,9 @@ namespace Content.Server
factory.Register<ItemComponent>();
factory.RegisterReference<ItemComponent, IItemComponent>();
factory.Register<InteractableComponent>();
factory.RegisterReference<InteractableComponent, IInteractableComponent>();
}
}
}

View File

@@ -0,0 +1,80 @@
using Content.Server.Interfaces.GameObjects;
using SS14.Server.Interfaces.GameObjects;
using SS14.Shared.GameObjects;
using SS14.Shared.Interfaces.GameObjects.Components;
using SS14.Shared.Log;
using System;
namespace Content.Server.GameObjects
{
public class InteractableComponent : Component, IInteractableComponent
{
public override string Name => "Interactable";
/// <inheritdoc />
public event EventHandler<AttackHandEventArgs> OnAttackHand;
/// <inheritdoc />
public event EventHandler<AttackByEventArgs> OnAttackBy;
private IClickableComponent clickableComponent;
private IServerTransformComponent transform;
private const float INTERACTION_RANGE = 2;
private const float INTERACTION_RANGE_SQUARED = INTERACTION_RANGE * INTERACTION_RANGE;
public override void Initialize()
{
transform = Owner.GetComponent<IServerTransformComponent>();
if (Owner.TryGetComponent<IClickableComponent>(out var component))
{
clickableComponent = component;
clickableComponent.OnClick += ClickableComponent_OnClick;
}
else
{
Logger.Error($"Interactable component must also have a clickable component to function! Prototype: {Owner.Prototype.ID}");
}
base.Initialize();
}
public override void Shutdown()
{
if (clickableComponent != null)
{
clickableComponent.OnClick -= ClickableComponent_OnClick;
clickableComponent = null;
}
transform = null;
base.Shutdown();
}
private void ClickableComponent_OnClick(object sender, ClickEventArgs e)
{
if (!e.User.TryGetComponent<IServerTransformComponent>(out var userTransform))
{
return;
}
var distance = (userTransform.WorldPosition - transform.WorldPosition).LengthSquared;
if (distance > INTERACTION_RANGE_SQUARED)
{
return;
}
if (!e.User.TryGetComponent<IHandsComponent>(out var hands))
{
return;
}
var item = hands.GetHand(hands.ActiveIndex);
if (item != null)
{
OnAttackBy?.Invoke(this, new AttackByEventArgs(Owner, e.User, item, hands.ActiveIndex));
}
else
{
OnAttackHand?.Invoke(this, new AttackHandEventArgs(Owner, e.User, hands.ActiveIndex));
}
}
}
}

View File

@@ -1,7 +1,8 @@
using Content.Server.Interfaces.GameObjects;
using SS14.Shared.GameObjects;
using SS14.Shared.Interfaces.GameObjects;
using SS14.Server.Interfaces.GameObjects;
using SS14.Shared.GameObjects;
using SS14.Shared.Interfaces.GameObjects.Components;
using SS14.Shared.Log;
using System;
namespace Content.Server.GameObjects
@@ -12,6 +13,7 @@ namespace Content.Server.GameObjects
/// <inheritdoc />
public IInventorySlot ContainingSlot { get; private set; }
private IInteractableComponent interactableComponent;
public void RemovedFromSlot()
{
@@ -42,5 +44,39 @@ namespace Content.Server.GameObjects
component.Visible = false;
}
}
public override void Initialize()
{
if (Owner.TryGetComponent<IInteractableComponent>(out var interactable))
{
interactableComponent = interactable;
interactableComponent.OnAttackHand += InteractableComponent_OnAttackHand;
}
else
{
Logger.Error($"Item component must have an interactable component to function! Prototype: {Owner.Prototype.ID}");
}
base.Initialize();
}
private void InteractableComponent_OnAttackHand(object sender, AttackHandEventArgs e)
{
if (ContainingSlot != null)
{
return;
}
var hands = e.User.GetComponent<IHandsComponent>();
hands.PutInHand(this, e.HandIndex, fallback: false);
}
public override void Shutdown()
{
if (interactableComponent != null)
{
interactableComponent.OnAttackHand -= InteractableComponent_OnAttackHand;
interactableComponent = null;
}
base.Shutdown();
}
}
}

View File

@@ -51,7 +51,6 @@ namespace Content.Server.GameObjects
}
Owner.SubscribeEvent<BoundKeyChangeEventArgs>(OnKeyChange, this);
Owner.SubscribeEvent<ClickedOnEntityEventArgs>(OnClick, this);
base.Initialize();
}
@@ -258,24 +257,6 @@ namespace Content.Server.GameObjects
ActiveIndex = orderedHands[index];
}
public void OnClick(object sender, EntityEventArgs uncast)
{
var cast = (ClickedOnEntityEventArgs)uncast;
if (cast.MouseButton != MouseClickType.Left || Owner.EntityManager.GetEntity(cast.Clicker) != Owner)
{
return;
}
var target = Owner.EntityManager.GetEntity(cast.Clicked);
var targetTransform = target.GetComponent<IServerTransformComponent>();
if (!target.TryGetComponent<IItemComponent>(out var item) || (targetTransform.WorldPosition - transform.WorldPosition).Length > PICKUP_RANGE)
{
return;
}
PutInHand(item, ActiveIndex, fallback: false);
}
public override void HandleNetworkMessage(IncomingEntityComponentMessage message, NetConnection sender)
{
if (message.MessageParameters.Count != 1)

View File

@@ -0,0 +1,48 @@
using SS14.Shared.Interfaces.GameObjects;
using System;
namespace Content.Server.Interfaces.GameObjects
{
public interface IInteractableComponent : IComponent
{
/// <summary>
/// Invoked when an entity is clicked with an empty hand.
/// </summary>
event EventHandler<AttackHandEventArgs> OnAttackHand;
/// <summary>
/// Invoked when an entity is clicked with an item.
/// </summary>
event EventHandler<AttackByEventArgs> OnAttackBy;
}
public class AttackByEventArgs : EventArgs
{
public readonly IEntity Target;
public readonly IEntity User;
public readonly IItemComponent Item;
public readonly string HandIndex;
public AttackByEventArgs(IEntity target, IEntity user, IItemComponent item, string handIndex)
{
Target = target;
User = user;
Item = item;
HandIndex = handIndex;
}
}
public class AttackHandEventArgs : EventArgs
{
public readonly IEntity Target;
public readonly IEntity User;
public readonly string HandIndex;
public AttackHandEventArgs(IEntity target, IEntity user, string handIndex)
{
Target = target;
User = user;
HandIndex = handIndex;
}
}
}

View File

@@ -4,6 +4,7 @@
id: ToolboxItem
components:
- type: Item
- type: Interactable
- type: entity
name: "Mop 2: Handle edition"
@@ -11,4 +12,4 @@
id: MopItem
components:
- type: Item
- type: Interactable