HandsComponent.cs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. using Content.Shared.DisplacementMap;
  2. using Content.Shared.Hands.EntitySystems;
  3. using Robust.Shared.Containers;
  4. using Robust.Shared.GameStates;
  5. using Robust.Shared.Serialization;
  6. namespace Content.Shared.Hands.Components;
  7. [RegisterComponent, NetworkedComponent, AutoGenerateComponentPause]
  8. [Access(typeof(SharedHandsSystem))]
  9. public sealed partial class HandsComponent : Component
  10. {
  11. /// <summary>
  12. /// The currently active hand.
  13. /// </summary>
  14. [ViewVariables]
  15. public Hand? ActiveHand;
  16. /// <summary>
  17. /// The item currently held in the active hand.
  18. /// </summary>
  19. [ViewVariables]
  20. public EntityUid? ActiveHandEntity => ActiveHand?.HeldEntity;
  21. [ViewVariables]
  22. public Dictionary<string, Hand> Hands = new();
  23. public int Count => Hands.Count;
  24. /// <summary>
  25. /// List of hand-names. These are keys for <see cref="Hands"/>. The order of this list determines the order in which hands are iterated over.
  26. /// </summary>
  27. public List<string> SortedHands = new();
  28. /// <summary>
  29. /// If true, the items in the hands won't be affected by explosions.
  30. /// </summary>
  31. [DataField]
  32. public bool DisableExplosionRecursion = false;
  33. /// <summary>
  34. /// Modifies the speed at which items are thrown.
  35. /// </summary>
  36. [DataField]
  37. [ViewVariables(VVAccess.ReadWrite)]
  38. public float BaseThrowspeed { get; set; } = 11f;
  39. /// <summary>
  40. /// Distance after which longer throw targets stop increasing throw impulse.
  41. /// </summary>
  42. [DataField("throwRange")]
  43. [ViewVariables(VVAccess.ReadWrite)]
  44. public float ThrowRange { get; set; } = 8f;
  45. /// <summary>
  46. /// Whether or not to add in-hand sprites for held items. Some entities (e.g., drones) don't want these.
  47. /// Used by the client.
  48. /// </summary>
  49. [DataField("showInHands")]
  50. public bool ShowInHands = true;
  51. /// <summary>
  52. /// Data about the current sprite layers that the hand is contributing to the owner entity. Used for sprite in-hands.
  53. /// Used by the client.
  54. /// </summary>
  55. public readonly Dictionary<HandLocation, HashSet<string>> RevealedLayers = new();
  56. /// <summary>
  57. /// The time at which throws will be allowed again.
  58. /// </summary>
  59. [DataField, ViewVariables(VVAccess.ReadWrite)]
  60. [AutoPausedField]
  61. public TimeSpan NextThrowTime;
  62. /// <summary>
  63. /// The minimum time inbetween throws.
  64. /// </summary>
  65. [DataField, ViewVariables(VVAccess.ReadWrite)]
  66. public TimeSpan ThrowCooldown = TimeSpan.FromSeconds(0.5f);
  67. /// <summary>
  68. /// Fallback displacement map applied to all sprites in the hand, unless otherwise specified
  69. /// </summary>
  70. [DataField]
  71. public DisplacementData? HandDisplacement;
  72. /// <summary>
  73. /// If defined, applies to all sprites in the left hand, ignoring <see cref="HandDisplacement"/>
  74. /// </summary>
  75. [DataField]
  76. public DisplacementData? LeftHandDisplacement;
  77. /// <summary>
  78. /// If defined, applies to all sprites in the right hand, ignoring <see cref="HandDisplacement"/>
  79. /// </summary>
  80. [DataField]
  81. public DisplacementData? RightHandDisplacement;
  82. /// <summary>
  83. /// If false, hands cannot be stripped, and they do not show up in the stripping menu.
  84. /// </summary>
  85. [DataField]
  86. public bool CanBeStripped = true;
  87. }
  88. [Serializable, NetSerializable]
  89. public sealed class Hand //TODO: This should definitely be a struct - Jezi
  90. {
  91. [ViewVariables]
  92. public string Name { get; }
  93. [ViewVariables]
  94. public HandLocation Location { get; }
  95. /// <summary>
  96. /// The container used to hold the contents of this hand. Nullable because the client must get the containers via <see cref="ContainerManagerComponent"/>,
  97. /// which may not be synced with the server when the client hands are created.
  98. /// </summary>
  99. [ViewVariables, NonSerialized]
  100. public ContainerSlot? Container;
  101. [ViewVariables]
  102. public EntityUid? HeldEntity => Container?.ContainedEntity;
  103. public bool IsEmpty => HeldEntity == null;
  104. public Hand(string name, HandLocation location, ContainerSlot? container = null)
  105. {
  106. Name = name;
  107. Location = location;
  108. Container = container;
  109. }
  110. }
  111. [Serializable, NetSerializable]
  112. public sealed class HandsComponentState : ComponentState
  113. {
  114. public readonly List<Hand> Hands;
  115. public readonly List<string> HandNames;
  116. public readonly string? ActiveHand;
  117. public HandsComponentState(HandsComponent handComp)
  118. {
  119. // cloning lists because of test networking.
  120. Hands = new(handComp.Hands.Values);
  121. HandNames = new(handComp.SortedHands);
  122. ActiveHand = handComp.ActiveHand?.Name;
  123. }
  124. }
  125. /// <summary>
  126. /// What side of the body this hand is on.
  127. /// </summary>
  128. /// <seealso cref="HandUILocation"/>
  129. /// <seealso cref="HandLocationExt"/>
  130. public enum HandLocation : byte
  131. {
  132. Left,
  133. Middle,
  134. Right
  135. }
  136. /// <summary>
  137. /// What side of the UI a hand is on.
  138. /// </summary>
  139. /// <seealso cref="HandLocationExt"/>
  140. /// <seealso cref="HandLocation"/>
  141. public enum HandUILocation : byte
  142. {
  143. Left,
  144. Right
  145. }
  146. /// <summary>
  147. /// Helper functions for working with <see cref="HandLocation"/>.
  148. /// </summary>
  149. public static class HandLocationExt
  150. {
  151. /// <summary>
  152. /// Convert a <see cref="HandLocation"/> into the appropriate <see cref="HandUILocation"/>.
  153. /// This maps "middle" hands to <see cref="HandUILocation.Right"/>.
  154. /// </summary>
  155. public static HandUILocation GetUILocation(this HandLocation location)
  156. {
  157. return location switch
  158. {
  159. HandLocation.Left => HandUILocation.Left,
  160. HandLocation.Middle => HandUILocation.Right,
  161. HandLocation.Right => HandUILocation.Right,
  162. _ => throw new ArgumentOutOfRangeException(nameof(location), location, null)
  163. };
  164. }
  165. }