Files
RobustToolbox/SS14.Server/GameObjects/Component/Item/BasicItemComponent.cs
Pieter-Jan Briers 13ae3647be Entity prototype & YAML cleanup, prototypes unified. (#268)
* gotta go

* Work cleaning up entity prototypes.

Added handling for the data field in entity prototypes. Closes #131.
Cleaned up a bunch of the YAML handling.
Made missing components throw errors and added a (to be done) error ignore
list.

This'll allow me to unify the prototypes of client and server later.

* Unify client and server prototypes.
2017-07-11 00:44:28 +02:00

326 lines
15 KiB
C#

using SS14.Server.GameObjects.Item.ItemCapability;
using SS14.Shared;
using SS14.Shared.GameObjects;
using SS14.Shared.GameObjects.Components.Item;
using SS14.Shared.Interfaces.GameObjects;
using SS14.Shared.IoC;
using SS14.Shared.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using YamlDotNet.RepresentationModel;
namespace SS14.Server.GameObjects
{
public class BasicItemComponent : Component
{
public override string Name => "BasicItem";
private readonly Dictionary<string, ItemCapability> capabilities;
public InventoryLocation HoldingHand = InventoryLocation.None;
public bool CanBePickedUp = true;
public IEntity CurrentHolder { get; set; }
public BasicItemComponent()
{
Family = ComponentFamily.Item;
capabilities = new Dictionary<string, ItemCapability>();
}
public override ComponentReplyMessage RecieveMessage(object sender, ComponentMessageType type,
params object[] list)
{
ComponentReplyMessage reply = base.RecieveMessage(sender, type, list);
if (sender == this)
return ComponentReplyMessage.Empty;
switch (type)
{
/*case ComponentMessageType.ReceiveEmptyHandToItemInteraction:
HandleEmptyHandToItemInteraction((Entity) list[0]);
// param 0 is the actor entity, param 1 is the source actor entity
break;*/
case ComponentMessageType.ReceiveItemToItemInteraction:
//This message means we were clicked on by an actor with an item in hand
HandleItemToItemInteraction((IEntity)list[0]);
// param 0 is the actor entity, param 1 is the source actor entity
break;
case ComponentMessageType.EnactItemToActorInteraction:
ApplyTo((IEntity)list[0], InteractsWith.Actor, (IEntity)list[1]);
break;
case ComponentMessageType.EnactItemToItemInteraction:
ApplyTo((IEntity)list[0], InteractsWith.Item, (IEntity)list[1]);
break;
case ComponentMessageType.EnactItemToLargeObjectInteraction:
ApplyTo((IEntity)list[0], InteractsWith.LargeObject, (IEntity)list[1]);
break;
/*case ComponentMessageType.PickedUp:
HandlePickedUp((IEntity) list[0], (Hand) list[1]);
break;*/
case ComponentMessageType.Dropped:
HandleDropped();
break;
case ComponentMessageType.ItemGetCapability:
ItemCapability[] itemcaps = GetCapability((ItemCapabilityType)list[0]);
if (itemcaps != null)
reply = new ComponentReplyMessage(ComponentMessageType.ItemReturnCapability, itemcaps);
break;
case ComponentMessageType.ItemGetCapabilityVerbPairs:
var verbpairs = new List<KeyValuePair<ItemCapabilityType, ItemCapabilityVerb>>();
foreach (ItemCapability capability in capabilities.Values)
{
foreach (
ItemCapabilityVerb verb in
(from v in capability.verbs orderby v.Key descending select v.Value))
{
verbpairs.Add(
new KeyValuePair<ItemCapabilityType, ItemCapabilityVerb>(capability.CapabilityType, verb));
}
}
//if(verbpairs.Count > 0)
reply = new ComponentReplyMessage(ComponentMessageType.ItemReturnCapabilityVerbPairs,
verbpairs.ToLookup(v => v.Key, v => v.Value));
break;
case ComponentMessageType.CheckItemHasCapability:
reply = new ComponentReplyMessage(ComponentMessageType.ItemHasCapability,
HasCapability((ItemCapabilityType)list[0]));
break;
case ComponentMessageType.ItemGetAllCapabilities:
reply = new ComponentReplyMessage(ComponentMessageType.ItemReturnCapability,
(object)GetAllCapabilities());
break;
case ComponentMessageType.Activate:
Activate();
break;
case ComponentMessageType.ClickedInHand:
Activate();
break;
case ComponentMessageType.ItemEquipped:
HandleDropped();
break;
}
return reply;
}
/// <summary>
/// Applies this item to the target entity.
/// </summary>
/// <param name="targetEntity">Target entity</param>
/// <param name="targetType">Type of entity, Item, LargeObject, or Actor</param>
public virtual void ApplyTo(IEntity targetEntity, InteractsWith targetType, IEntity sourceActor)
{
//can be overridden in children to sort of bypass the capability system if needed.
ApplyCapabilities(targetEntity, targetType, sourceActor);
}
public void HandleDropped()
{
CurrentHolder = null;
HoldingHand = InventoryLocation.None;
}
public void HandlePickedUp(IEntity entity, InventoryLocation holdingHand)
{
CurrentHolder = entity;
HoldingHand = holdingHand;
/*Owner.AddComponent(ComponentFamily.Mover,
Owner.EntityManager.ComponentFactory.GetComponent("SlaveMoverComponent"));
Owner.SendMessage(this, ComponentMessageType.SlaveAttach, entity.Uid);
Owner.SendDirectedComponentNetworkMessage(this, NetDeliveryMethod.ReliableOrdered, null,
ItemComponentNetMessage.PickedUp, entity.Uid, holdingHand);*/
}
/// <summary>
/// Entry point for interactions between an item and this item
/// Basically, the actor uses an item on this item
/// </summary>
/// <param name="entity">The actor entity</param>
protected virtual void HandleItemToItemInteraction(IEntity actor)
{
//Get the item
//Apply actions based on the item's types
//Message the item to tell it to apply whatever it needs to do as well
}
/// <summary>
/// Entry point for interactions between an empty hand and this item
/// Basically, the actor touches this item with an empty hand
/// </summary>
/// <param name="actor"></param>
public virtual void HandleEmptyHandToItemInteraction(IEntity actor)
{
//Pick up the item
actor.SendMessage(this, ComponentMessageType.PickUpItem, Owner);
}
private void Activate()
{
Owner.SendMessage(this, ComponentMessageType.Activate);
ActivateCapabilities();
}
/// <summary>
/// Apply this item's capabilities to a target entity
/// This finds all onboard capability modules that can interact with a given object type,
/// sorted by priority. Only one thing will actually execute, depending on priority.
/// ApplyTo returns true if it successfully interacted with the target, false if not.
/// </summary>
/// <param name="target">Target entity for interaction</param>
protected virtual void ApplyCapabilities(IEntity target, InteractsWith targetType, IEntity sourceActor)
{
IOrderedEnumerable<ItemCapability> capstoapply = from c in capabilities.Values
where (c.interactsWith & targetType) == targetType
orderby c.priority descending
select c;
foreach (ItemCapability capability in capstoapply)
{
if (capability.ApplyTo(target, sourceActor))
break;
}
}
/// <summary>
/// Executes a query to get the capabilities of this item.
/// This enables us to ask things like, "is the item a tool?"
/// You can have items that have more than one tool capability module, and return them both via a query.
/// This is mostly useful for the object that is receiving an action from the item.
/// </summary>
/// <param name="query">ItemCapabilityQuery object</param>
/// <returns></returns>
protected ItemCapabilityQueryResult ExecuteCapabilityQuery(ItemCapabilityQuery query)
{
var result = new ItemCapabilityQueryResult();
result.ResultStatus = ItemCapabilityQueryResult.ItemCapabilityQueryResultType.Error;
switch (query.queryType)
{
case ItemCapabilityQuery.ItemCapabilityQueryType.GetAllCapabilities:
//Get all the capabilities of the object. Not particularly useful.
foreach (ItemCapability c in capabilities.Values)
result.AddCapability(c);
if (capabilities.Any())
result.ResultStatus = ItemCapabilityQueryResult.ItemCapabilityQueryResultType.Success;
else
result.ResultStatus = ItemCapabilityQueryResult.ItemCapabilityQueryResultType.Empty;
break;
case ItemCapabilityQuery.ItemCapabilityQueryType.GetCapability:
//Get the capabilities that match a particular capability type
IEnumerable<ItemCapability> caps = from c in capabilities.Values
where (c.CapabilityType == query.capabilityType)
select c;
foreach (ItemCapability c in caps)
result.AddCapability(c);
if (caps.Any())
result.ResultStatus = ItemCapabilityQueryResult.ItemCapabilityQueryResultType.Success;
else
result.ResultStatus = ItemCapabilityQueryResult.ItemCapabilityQueryResultType.Empty;
break;
case ItemCapabilityQuery.ItemCapabilityQueryType.HasCapability:
//Check if the item has a capability of a certain type.
IEnumerable<ItemCapability> hascap = from c in capabilities.Values
where (c.CapabilityType == query.capabilityType)
select c;
if (hascap.Any())
result.ResultStatus = ItemCapabilityQueryResult.ItemCapabilityQueryResultType.True;
else
result.ResultStatus = ItemCapabilityQueryResult.ItemCapabilityQueryResultType.False;
break;
}
if (result.ResultStatus == ItemCapabilityQueryResult.ItemCapabilityQueryResultType.Error)
result.ErrorMessage = "No Result";
return result;
}
private ItemCapability[] GetCapability(ItemCapabilityType type)
{
ItemCapabilityQueryResult result =
ExecuteCapabilityQuery(new ItemCapabilityQuery(
ItemCapabilityQuery.ItemCapabilityQueryType.GetCapability, type));
if (result.ResultStatus == ItemCapabilityQueryResult.ItemCapabilityQueryResultType.Success)
return result.Capabilities;
else
return null;
}
private ItemCapability[] GetAllCapabilities()
{
ItemCapabilityQueryResult result =
ExecuteCapabilityQuery(
new ItemCapabilityQuery(ItemCapabilityQuery.ItemCapabilityQueryType.GetAllCapabilities,
ItemCapabilityType.None));
if (result.ResultStatus == ItemCapabilityQueryResult.ItemCapabilityQueryResultType.Empty)
return new ItemCapability[0];
else
return result.Capabilities;
}
private void ActivateCapabilities()
{
foreach (ItemCapability c in GetAllCapabilities())
{
c.Activate();
}
}
private bool HasCapability(ItemCapabilityType type)
{
ItemCapabilityQueryResult result =
ExecuteCapabilityQuery(new ItemCapabilityQuery(
ItemCapabilityQuery.ItemCapabilityQueryType.HasCapability, type));
if (result.ResultStatus == ItemCapabilityQueryResult.ItemCapabilityQueryResultType.True)
return true;
else
return false;
}
public void AddCapability(ItemCapability cap)
{
capabilities.Add(cap.capabilityName, cap);
cap.owner = this;
}
public override void LoadParameters(YamlMappingNode yaml)
{
/*
TODO: figure something out for this cancerous mess.
Yeah it's basically ANOTHER FUCKING COMPONENT SYSTEM built into the item component.
foreach (XElement itemcapability in extendedParameters.Descendants("ItemCapability"))
{
IEnumerable<XElement> Verbs = itemcapability.Descendants("ItemCapabilityVerb");
IEnumerable<XElement> Parameters = itemcapability.Descendants("ItemCapabilityParameter");
ItemCapability cap = null;
if (cap == null) // TODO: make this method actually do something because right now it always returns
return;
foreach (XElement verb in Verbs)
{
cap.AddVerb(int.Parse(verb.Attribute("priority").Value),
(ItemCapabilityVerb)
Enum.Parse(typeof (ItemCapabilityVerb), verb.Attribute("name").Value));
}
foreach (XElement parameter in Parameters)
{
string name = parameter.Attribute("name").Value;
Type type = EntityTemplate.TranslateType(parameter.Attribute("type").Value);
object value = Convert.ChangeType(parameter.Attribute("value").Value, type);
var cparam = new ComponentParameter(name, value);
cap.SetParameter(cparam);
}
AddCapability(cap);
}
*/
}
public override ComponentState GetComponentState()
{
return new ItemComponentState(CurrentHolder != null ? (int?)CurrentHolder.Uid : null, HoldingHand);
}
}
}