using System;
using System.Collections.Generic;
using Content.Shared.BodySystem;
using Robust.Shared.ViewVariables;
namespace Content.Server.BodySystem {
///
/// This class is a data capsule representing the standard format of a . For instance, the "humanoid" BodyTemplate
/// defines two arms, each connected to a torso and so on. Capable of loading data from a .
///
public class BodyTemplate {
[ViewVariables]
public string Name;
///
/// The name of the center BodyPart. For humans, this is set to "torso". Used in many calculations.
///
[ViewVariables]
public string CenterSlot { get; set; }
///
/// Maps all parts on this template to its BodyPartType. For instance, "right arm" is mapped to "BodyPartType.arm" on the humanoid template.
///
[ViewVariables]
public Dictionary Slots { get; set; }
///
/// Maps limb name to the list of their connections to other limbs. For instance, on the humanoid template "torso" is mapped to a list containing "right arm", "left arm",
/// "left leg", and "right leg". This is mapped both ways during runtime, but in the prototype only one way has to be defined, i.e., "torso" to "left arm" will automatically
/// map "left arm" to "torso".
///
[ViewVariables]
public Dictionary> Connections { get; set; }
public BodyTemplate()
{
Name = "empty";
Slots = new Dictionary();
Connections = new Dictionary>();
CenterSlot = "";
}
public BodyTemplate(BodyTemplatePrototype data)
{
LoadFromPrototype(data);
}
public bool Equals(BodyTemplate other)
{
return GetHashCode() == other.GetHashCode();
}
///
/// Returns whether the given slot exists in this BodyTemplate.
///
public bool SlotExists(string slotName)
{
foreach (string slot in Slots.Keys)
{
if (slot == slotName) //string comparison xd
return true;
}
return false;
}
///
/// Returns an integer unique to this BodyTemplate's layout. It does not matter in which order the Connections or Slots are defined.
///
public override int GetHashCode()
{
int slotsHash = 0;
int connectionsHash = 0;
foreach (var(key, value) in Slots)
{
int slot = key.GetHashCode();
slot = HashCode.Combine(slot, value.GetHashCode());
slotsHash = slotsHash ^ slot;
}
List connections = new List();
foreach (var (key, value) in Connections)
{
foreach (var targetBodyPart in value)
{
int connection = key.GetHashCode() ^ targetBodyPart.GetHashCode();
if (!connections.Contains(connection))
connections.Add(connection);
}
}
foreach (int connection in connections)
{
connectionsHash = connectionsHash ^ connection;
}
int hash = HashCode.Combine(slotsHash, connectionsHash, CenterSlot.GetHashCode());
if (hash == 0) //One of the unit tests considers 0 to be an error, but it will be 0 if the BodyTemplate is empty, so let's shift that up to 1.
hash++;
return hash;
}
public virtual void LoadFromPrototype(BodyTemplatePrototype data)
{
Name = data.Name;
CenterSlot = data.CenterSlot;
Slots = data.Slots;
Connections = data.Connections;
}
}
}