ConstructionSystem.Pathfinding.cs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. using Content.Server.Construction.Components;
  2. using Content.Shared.Construction;
  3. using Content.Shared.Construction.Prototypes;
  4. namespace Content.Server.Construction
  5. {
  6. public sealed partial class ConstructionSystem
  7. {
  8. /// <summary>
  9. /// Sets or clears a pathfinding target node for a given construction entity.
  10. /// </summary>
  11. /// <param name="uid">The target entity.</param>
  12. /// <param name="targetNodeId">The target node to pathfind, or null to clear the current pathfinding node.</param>
  13. /// <param name="construction">The construction component of the target entity. Will be resolved if null.</param>
  14. /// <returns>Whether we could set/clear the pathfinding target node.</returns>
  15. public bool SetPathfindingTarget(EntityUid uid, string? targetNodeId, ConstructionComponent? construction = null)
  16. {
  17. if (!Resolve(uid, ref construction))
  18. return false;
  19. // Clear current target, just in case.
  20. ClearPathfinding(uid, construction);
  21. // Null means clear pathfinding target only.
  22. if (targetNodeId == null)
  23. {
  24. return true;
  25. }
  26. if (GetCurrentGraph(uid, construction) is not {} graph)
  27. return false;
  28. if (GetNodeFromGraph(graph, construction.Node) is not { } node)
  29. return false;
  30. if (GetNodeFromGraph(graph, targetNodeId) is not {} targetNode)
  31. return false;
  32. return UpdatePathfinding(uid, graph, node, targetNode, GetCurrentEdge(uid, construction), construction);
  33. }
  34. /// <summary>
  35. /// Updates the pathfinding state for the current construction state of an entity.
  36. /// </summary>
  37. /// <param name="uid">The target entity.</param>
  38. /// <param name="construction">The construction component of the target entity. Will be resolved if null.</param>
  39. /// <returns>Whether we could update the pathfinding state correctly.</returns>
  40. public bool UpdatePathfinding(EntityUid uid, ConstructionComponent? construction = null)
  41. {
  42. if (!Resolve(uid, ref construction))
  43. return false;
  44. if (construction.TargetNode is not {} targetNodeId)
  45. return false;
  46. if (GetCurrentGraph(uid, construction) is not {} graph
  47. || GetNodeFromGraph(graph, construction.Node) is not {} node
  48. || GetNodeFromGraph(graph, targetNodeId) is not {} targetNode)
  49. return false;
  50. return UpdatePathfinding(uid, graph, node, targetNode, GetCurrentEdge(uid, construction), construction);
  51. }
  52. /// <summary>
  53. /// Internal version of <see cref="UpdatePathfinding"/>, which expects a valid construction state and
  54. /// actually performs the pathfinding update logic.
  55. /// </summary>
  56. /// <param name="uid">The target entity.</param>
  57. /// <param name="graph">The construction graph the entity is at.</param>
  58. /// <param name="currentNode">The current construction node the entity is at.</param>
  59. /// <param name="targetNode">The target node we are trying to reach on the graph.</param>
  60. /// <param name="currentEdge">The current edge the entity is at, or null if none.</param>
  61. /// <param name="construction">The construction component of the target entity. Will be resolved if null.</param>
  62. /// <returns>Whether we could update the pathfinding state correctly.</returns>
  63. private bool UpdatePathfinding(EntityUid uid, ConstructionGraphPrototype graph,
  64. ConstructionGraphNode currentNode, ConstructionGraphNode targetNode,
  65. ConstructionGraphEdge? currentEdge,
  66. ConstructionComponent? construction = null)
  67. {
  68. if (!Resolve(uid, ref construction))
  69. return false;
  70. construction.TargetNode = targetNode.Name;
  71. // Check if we reached the target node.
  72. if (currentNode == targetNode)
  73. {
  74. ClearPathfinding(uid, construction);
  75. return true;
  76. }
  77. // If we don't have a path, generate it.
  78. if (construction.NodePathfinding == null)
  79. {
  80. var path = graph.PathId(currentNode.Name, targetNode.Name);
  81. if (path == null || path.Length == 0)
  82. {
  83. // No path.
  84. ClearPathfinding(uid, construction);
  85. return false;
  86. }
  87. construction.NodePathfinding = new Queue<string>(path);
  88. }
  89. // If the next pathfinding node is the one we're at, dequeue it.
  90. if (construction.NodePathfinding.Peek() == currentNode.Name)
  91. {
  92. construction.NodePathfinding.Dequeue();
  93. }
  94. if (currentEdge != null && construction.TargetEdgeIndex is {} targetEdgeIndex)
  95. {
  96. if (currentNode.Edges.Count >= targetEdgeIndex)
  97. {
  98. // Target edge is incorrect.
  99. construction.TargetEdgeIndex = null;
  100. }
  101. else if (currentNode.Edges[targetEdgeIndex] != currentEdge)
  102. {
  103. // We went the wrong way, clean up!
  104. ClearPathfinding(uid, construction);
  105. return false;
  106. }
  107. }
  108. if (construction.EdgeIndex == null
  109. && construction.TargetEdgeIndex == null
  110. && construction.NodePathfinding != null)
  111. construction.TargetEdgeIndex = (currentNode.GetEdgeIndex(construction.NodePathfinding.Peek()));
  112. return true;
  113. }
  114. /// <summary>
  115. /// Clears the pathfinding targets on a construction entity.
  116. /// </summary>
  117. /// <param name="uid">The target entity.</param>
  118. /// <param name="construction">The construction component of the target entity. Will be resolved if null.</param>
  119. public void ClearPathfinding(EntityUid uid, ConstructionComponent? construction = null)
  120. {
  121. if (!Resolve(uid, ref construction))
  122. return;
  123. construction.TargetNode = null;
  124. construction.TargetEdgeIndex = null;
  125. construction.NodePathfinding = null;
  126. }
  127. }
  128. }