1
0

SharedTabletopSystem.cs 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. using System.Diagnostics.CodeAnalysis;
  2. using System.Numerics;
  3. using Content.Shared.ActionBlocker;
  4. using Content.Shared.Hands.Components;
  5. using Content.Shared.Interaction;
  6. using Content.Shared.Tabletop.Components;
  7. using Content.Shared.Tabletop.Events;
  8. using Robust.Shared.Map;
  9. using Robust.Shared.Network;
  10. using Robust.Shared.Serialization;
  11. namespace Content.Shared.Tabletop
  12. {
  13. public abstract class SharedTabletopSystem : EntitySystem
  14. {
  15. [Dependency] protected readonly ActionBlockerSystem ActionBlockerSystem = default!;
  16. [Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
  17. [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
  18. [Dependency] protected readonly SharedTransformSystem Transforms = default!;
  19. [Dependency] private readonly IMapManager _mapMan = default!;
  20. public override void Initialize()
  21. {
  22. SubscribeAllEvent<TabletopDraggingPlayerChangedEvent>(OnDraggingPlayerChanged);
  23. SubscribeAllEvent<TabletopMoveEvent>(OnTabletopMove);
  24. }
  25. /// <summary>
  26. /// Move an entity which is dragged by the user, but check if they are allowed to do so and to these coordinates
  27. /// </summary>
  28. protected virtual void OnTabletopMove(TabletopMoveEvent msg, EntitySessionEventArgs args)
  29. {
  30. if (args.SenderSession is not { AttachedEntity: { } playerEntity } playerSession)
  31. return;
  32. var table = GetEntity(msg.TableUid);
  33. var moved = GetEntity(msg.MovedEntityUid);
  34. if (!CanSeeTable(playerEntity, table) || !CanDrag(playerEntity, moved, out _))
  35. return;
  36. // Move the entity and dirty it (we use the map ID from the entity so noone can try to be funny and move the item to another map)
  37. var transform = EntityManager.GetComponent<TransformComponent>(moved);
  38. Transforms.SetParent(moved, transform, _mapMan.GetMapEntityId(transform.MapID));
  39. Transforms.SetLocalPositionNoLerp(transform, msg.Coordinates.Position);
  40. }
  41. private void OnDraggingPlayerChanged(TabletopDraggingPlayerChangedEvent msg, EntitySessionEventArgs args)
  42. {
  43. var dragged = GetEntity(msg.DraggedEntityUid);
  44. if (!TryComp(dragged, out TabletopDraggableComponent? draggableComponent))
  45. return;
  46. draggableComponent.DraggingPlayer = msg.IsDragging ? args.SenderSession.UserId : null;
  47. Dirty(dragged, draggableComponent);
  48. if (!TryComp(dragged, out AppearanceComponent? appearance))
  49. return;
  50. if (draggableComponent.DraggingPlayer != null)
  51. {
  52. _appearance.SetData(dragged, TabletopItemVisuals.Scale, new Vector2(1.25f, 1.25f), appearance);
  53. _appearance.SetData(dragged, TabletopItemVisuals.DrawDepth, (int) DrawDepth.DrawDepth.Items + 1, appearance);
  54. }
  55. else
  56. {
  57. _appearance.SetData(dragged, TabletopItemVisuals.Scale, Vector2.One, appearance);
  58. _appearance.SetData(dragged, TabletopItemVisuals.DrawDepth, (int) DrawDepth.DrawDepth.Items, appearance);
  59. }
  60. }
  61. [Serializable, NetSerializable]
  62. public sealed class TabletopDraggableComponentState : ComponentState
  63. {
  64. public NetUserId? DraggingPlayer;
  65. public TabletopDraggableComponentState(NetUserId? draggingPlayer)
  66. {
  67. DraggingPlayer = draggingPlayer;
  68. }
  69. }
  70. [Serializable, NetSerializable]
  71. public sealed class TabletopRequestTakeOut : EntityEventArgs
  72. {
  73. public NetEntity Entity;
  74. public NetEntity TableUid;
  75. }
  76. #region Utility
  77. /// <summary>
  78. /// Whether the table exists, and the player can interact with it.
  79. /// </summary>
  80. /// <param name="playerEntity">The player entity to check.</param>
  81. /// <param name="table">The table entity to check.</param>
  82. protected bool CanSeeTable(EntityUid playerEntity, EntityUid? table)
  83. {
  84. // Table may have been deleted, hence TryComp
  85. if (!TryComp(table, out MetaDataComponent? meta)
  86. || meta.EntityLifeStage >= EntityLifeStage.Terminating
  87. || (meta.Flags & MetaDataFlags.InContainer) == MetaDataFlags.InContainer)
  88. {
  89. return false;
  90. }
  91. return _interactionSystem.InRangeUnobstructed(playerEntity, table.Value) && ActionBlockerSystem.CanInteract(playerEntity, table);
  92. }
  93. protected bool CanDrag(EntityUid playerEntity, EntityUid target, [NotNullWhen(true)] out TabletopDraggableComponent? draggable)
  94. {
  95. if (!TryComp(target, out draggable))
  96. return false;
  97. // CanSeeTable checks interaction action blockers. So no need to check them here.
  98. // If this ever changes, so that ghosts can spectate games, then the check needs to be moved here.
  99. return TryComp(playerEntity, out HandsComponent? hands) && hands.Hands.Count > 0;
  100. }
  101. #endregion
  102. }
  103. }