92 std::vector<std::pair<Position, float>>
FindPath(
const BehaviourClient& client,
const Position& start,
const Position& end,
const int dist_tolerance,
const int min_end_dist,
const int min_end_dist_xz,
const bool allow_jump)
96 std::pair<Position, float> pos;
99 PathNode(
const std::pair<Position, float>& p,
const float s)
105 bool operator>(
const PathNode& rhs)
const
107 return score > rhs.score;
112 return static_cast<float>(std::abs(a.
x - b.
x) + std::abs(a.
y - b.
y) + std::abs(a.
z - b.
z));
116 constexpr int budget_visit = 15000;
118 const std::array<Position, 4> neighbour_offsets = {
Position(1, 0, 0),
Position(-1, 0, 0),
Position(0, 0, 1),
Position(0, 0, -1) };
119 std::priority_queue<PathNode, std::vector<PathNode>, std::greater<PathNode> > nodes_to_explore;
120 std::unordered_map<std::pair<Position, float>, std::pair<Position, float>,
PosFloatPairHash> came_from;
121 std::unordered_map<std::pair<Position, float>, float,
PosFloatPairHash> cost;
123 const bool takes_damage = !client.
GetLocalPlayer()->GetInvulnerable();
124 std::shared_ptr<World> world = client.
GetWorld();
125 const Blockstate* block = world->GetBlock(start);
127 came_from[nodes_to_explore.top().pos] = nodes_to_explore.top().pos;
128 cost[nodes_to_explore.top().pos] = 0.0f;
133 bool suitable_location_found =
false;
135 bool end_reached =
false;
137 bool end_is_inside_solid =
false;
138 block = world->GetBlock(end);
139 end_is_inside_solid = block !=
nullptr && block->
IsSolid();
141 while (!nodes_to_explore.empty())
144 PathNode current_node = nodes_to_explore.top();
145 nodes_to_explore.pop();
147 end_reached |= current_node.pos.first == end;
148 suitable_location_found |=
149 std::abs(end.
x - current_node.pos.first.x) + std::abs(end.
y - current_node.pos.first.y) + std::abs(end.
z - current_node.pos.first.z) <= dist_tolerance &&
150 std::abs(end.
x - current_node.pos.first.x) + std::abs(end.
y - current_node.pos.first.y) + std::abs(end.
z - current_node.pos.first.z) >= min_end_dist &&
151 std::abs(end.
x - current_node.pos.first.x) + std::abs(end.
z - current_node.pos.first.z) >= min_end_dist_xz;
154 count_visit > budget_visit ||
156 (suitable_location_found && (end_reached || end_is_inside_solid)))
162 std::array<PathfindingBlockstate, 6> vertical_surroundings;
172 block = world->GetBlock(pos);
174 pos = current_node.pos.first +
Position(0, 1, 0);
175 block = world->GetBlock(pos);
178 pos = current_node.pos.first;
179 block = world->GetBlock(pos);
184 if (!vertical_surroundings[2].IsSolid() && !vertical_surroundings[2].IsHazardous())
188 pos = current_node.pos.first +
Position(0, -1, 0);
189 block = world->GetBlock(pos);
193 if (!vertical_surroundings[3].IsSolid() && !vertical_surroundings[3].IsHazardous())
195 pos = current_node.pos.first +
Position(0, -2, 0);
196 block = world->GetBlock(pos);
198 pos = current_node.pos.first +
Position(0, -3, 0);
199 block = world->GetBlock(pos);
212 if (vertical_surroundings[2].IsClimbable()
213 && !vertical_surroundings[1].IsSolid()
214 && !vertical_surroundings[1].IsHazardous()
215 && !vertical_surroundings[0].IsSolid()
216 && !vertical_surroundings[0].IsHazardous()
219 const float new_cost = cost[current_node.pos] + 1.0f;
220 const std::pair<Position, float> new_pos = {
221 current_node.pos.first +
Position(0, 1, 0),
222 current_node.pos.first.y + 1.0f
224 auto it = cost.find(new_pos);
226 if (it == cost.end() ||
227 new_cost < it->second)
229 cost[new_pos] = new_cost;
230 nodes_to_explore.emplace(PathNode(
232 new_cost + PathNode::Heuristic(new_pos.first, end))
234 came_from[new_pos] = current_node.pos;
244 if (vertical_surroundings[1].IsClimbable()
245 && !vertical_surroundings[0].IsSolid()
246 && !vertical_surroundings[0].IsHazardous()
247 && (vertical_surroundings[2].IsSolid() ||
248 (!vertical_surroundings[2].IsClimbable() && vertical_surroundings[3].IsSolid())
252 const float new_cost = cost[current_node.pos] + 1.5f;
253 const std::pair<Position, float> new_pos = {
254 current_node.pos.first +
Position(0, 1, 0),
255 current_node.pos.first.y + 1.0f
257 auto it = cost.find(new_pos);
259 if (it == cost.end() ||
260 new_cost < it->second)
262 cost[new_pos] = new_cost;
263 nodes_to_explore.emplace(PathNode(
265 new_cost + PathNode::Heuristic(new_pos.first, end))
267 came_from[new_pos] = current_node.pos;
277 if (!vertical_surroundings[2].IsSolid() &&
278 vertical_surroundings[3].IsClimbable()
281 const float new_cost = cost[current_node.pos] + 1.0f;
282 const std::pair<Position, float> new_pos = {
283 current_node.pos.first +
Position(0, -1, 0),
284 current_node.pos.first.y - 1.0f
286 auto it = cost.find(new_pos);
288 if (it == cost.end() ||
289 new_cost < it->second)
291 cost[new_pos] = new_cost;
292 nodes_to_explore.emplace(PathNode(new_pos, new_cost + PathNode::Heuristic(new_pos.first, end)));
293 came_from[new_pos] = current_node.pos;
303 if (!vertical_surroundings[2].IsSolid() &&
304 vertical_surroundings[3].IsClimbable()
305 && vertical_surroundings[4].IsEmpty()
306 && !vertical_surroundings[5].IsEmpty()
307 && !vertical_surroundings[5].IsHazardous()
310 const bool above_block = vertical_surroundings[5].IsClimbable() || vertical_surroundings[5].GetHeight() + 1e-3f > current_node.pos.first.y - 2;
311 const float new_cost = cost[current_node.pos] + 3.0f - 1.0f * above_block;
312 const std::pair<Position, float> new_pos = {
313 current_node.pos.first +
Position(0, -3 + 1 * above_block, 0),
314 above_block ? std::max(current_node.pos.first.y - 2.0f, vertical_surroundings[5].GetHeight()) : vertical_surroundings[5].GetHeight()
316 auto it = cost.find(new_pos);
318 if (it == cost.end() ||
319 new_cost < it->second)
321 cost[new_pos] = new_cost;
322 nodes_to_explore.emplace(PathNode(
324 new_cost + PathNode::Heuristic(new_pos.first, end))
326 came_from[new_pos] = current_node.pos;
338 if (vertical_surroundings[2].IsClimbable()
339 && vertical_surroundings[3].IsEmpty()
340 && vertical_surroundings[4].IsEmpty()
341 && !vertical_surroundings[5].IsEmpty()
342 && !vertical_surroundings[5].IsHazardous()
345 const bool above_block = vertical_surroundings[5].IsClimbable() || vertical_surroundings[5].GetHeight() + 1e-3f > current_node.pos.first.y - 2;
346 const float new_cost = cost[current_node.pos] + 3.0f - 1.0f * above_block;
347 const std::pair<Position, float> new_pos = {
348 current_node.pos.first +
Position(0, -3 + 1 * above_block, 0),
349 above_block ? std::max(current_node.pos.first.y - 2.0f, vertical_surroundings[5].GetHeight()) : vertical_surroundings[5].GetHeight()
351 auto it = cost.find(new_pos);
353 if (it == cost.end() ||
354 new_cost < it->second)
356 cost[new_pos] = new_cost;
357 nodes_to_explore.emplace(PathNode(
359 new_cost + PathNode::Heuristic(new_pos.first, end))
361 came_from[new_pos] = current_node.pos;
374 if (!vertical_surroundings[2].IsSolid() &&
375 vertical_surroundings[3].IsClimbable()
376 && vertical_surroundings[4].IsEmpty()
377 && vertical_surroundings[5].IsEmpty()
380 for (
int y = -4; current_node.pos.first.y + y >= world->GetMinY(); --y)
382 pos = current_node.pos.first +
Position(0, y, 0);
383 block = world->GetBlock(pos);
393 const float new_cost = cost[current_node.pos] + std::abs(y);
394 const std::pair<Position, float> new_pos = {
395 current_node.pos.first +
Position(0, y + 1, 0),
396 current_node.pos.first.y + y + 1.0f
398 auto it = cost.find(new_pos);
400 if (it == cost.end() ||
401 new_cost < it->second)
403 cost[new_pos] = new_cost;
404 nodes_to_explore.emplace(PathNode(
406 new_cost + PathNode::Heuristic(new_pos.first, end))
408 came_from[new_pos] = current_node.pos;
419 for (
int i = 0; i < neighbour_offsets.size(); ++i)
421 const Position next_location = current_node.pos.first + neighbour_offsets[i];
422 const Position next_next_location = next_location + neighbour_offsets[i];
425 std::array<PathfindingBlockstate, 12> horizontal_surroundings;
437 pos = next_location +
Position(0, 2, 0);
438 block = world->GetBlock(pos);
440 pos = next_location +
Position(0, 1, 0);
441 block = world->GetBlock(pos);
443 const bool horizontal_movement =
444 (!horizontal_surroundings[1].IsSolid() ||
445 (horizontal_surroundings[1].GetHeight() - current_node.pos.second < 1.25f &&
446 !horizontal_surroundings[0].IsSolid() && !horizontal_surroundings[0].IsHazardous())
447 ) && !horizontal_surroundings[1].IsHazardous();
450 if (horizontal_movement)
453 block = world->GetBlock(pos);
455 pos = next_location +
Position(0, -1, 0);
456 block = world->GetBlock(pos);
458 pos = next_location +
Position(0, -2, 0);
459 block = world->GetBlock(pos);
461 pos = next_location +
Position(0, -3, 0);
462 block = world->GetBlock(pos);
468 if (allow_jump && !vertical_surroundings[2].IsClimbable())
470 pos = next_next_location +
Position(0, 2, 0);
471 block = world->GetBlock(pos);
473 pos = next_next_location +
Position(0, 1, 0);
474 block = world->GetBlock(pos);
476 pos = next_next_location;
477 block = world->GetBlock(pos);
479 pos = next_next_location +
Position(0, -1, 0);
480 block = world->GetBlock(pos);
482 pos = next_next_location +
Position(0, -2, 0);
483 block = world->GetBlock(pos);
485 pos = next_next_location +
Position(0, -3, 0);
486 block = world->GetBlock(pos);
501 if (!horizontal_surroundings[1].IsSolid()
502 && !horizontal_surroundings[1].IsHazardous()
503 && !horizontal_surroundings[2].IsSolid()
504 && !horizontal_surroundings[2].IsHazardous()
505 && !horizontal_surroundings[3].IsEmpty()
506 && !horizontal_surroundings[3].IsHazardous()
507 && (!horizontal_surroundings[3].IsFluid()
508 || !vertical_surroundings[3].IsFluid()
509 || horizontal_surroundings[2].IsFluid()
510 || vertical_surroundings[2].IsFluid())
513 const bool above_block = horizontal_surroundings[2].IsClimbable() || horizontal_surroundings[3].IsClimbable() || horizontal_surroundings[3].GetHeight() + 1e-3f > current_node.pos.first.y;
514 const float new_cost = cost[current_node.pos] + 2.0f - 1.0f * above_block;
515 const std::pair<Position, float> new_pos = {
516 next_location +
Position(0, 1 - 1 * above_block, 0),
517 above_block ? std::max(
static_cast<float>(next_location.
y), horizontal_surroundings[3].GetHeight()) : std::max(horizontal_surroundings[3].GetHeight(), horizontal_surroundings[4].GetHeight())
519 auto it = cost.find(new_pos);
521 if (it == cost.end() ||
522 new_cost < it->second)
524 cost[new_pos] = new_cost;
525 nodes_to_explore.emplace(PathNode(
527 new_cost + PathNode::Heuristic(new_pos.first, end))
529 came_from[new_pos] = current_node.pos;
540 if (!vertical_surroundings[0].IsSolid()
541 && !vertical_surroundings[0].IsHazardous()
542 && vertical_surroundings[1].IsEmpty()
543 && !vertical_surroundings[2].IsClimbable()
544 && (vertical_surroundings[2].IsSolid() || !vertical_surroundings[3].IsClimbable())
545 && !horizontal_surroundings[0].IsSolid()
546 && !horizontal_surroundings[0].IsHazardous()
547 && !horizontal_surroundings[1].IsEmpty()
548 && !horizontal_surroundings[1].IsHazardous()
549 && horizontal_surroundings[1].GetHeight() - current_node.pos.second < 1.25f
552 const float new_cost = cost[current_node.pos] + 2.5f;
553 const std::pair<Position, float> new_pos = {
555 std::max(horizontal_surroundings[1].GetHeight(), horizontal_surroundings[2].GetHeight())
557 auto it = cost.find(new_pos);
559 if (it == cost.end() ||
560 new_cost < it->second)
562 cost[new_pos] = new_cost;
563 nodes_to_explore.emplace(PathNode(
565 new_cost + PathNode::Heuristic(new_pos.first, end))
567 came_from[new_pos] = current_node.pos;
577 if (!vertical_surroundings[0].IsSolid()
578 && !vertical_surroundings[0].IsHazardous()
579 && vertical_surroundings[1].IsEmpty()
580 && (vertical_surroundings[2].IsSolid() || (vertical_surroundings[2].IsEmpty() && vertical_surroundings[3].IsSolid()))
581 && !horizontal_surroundings[0].IsSolid()
582 && !horizontal_surroundings[0].IsHazardous()
583 && !horizontal_surroundings[1].IsSolid()
584 && !horizontal_surroundings[1].IsHazardous()
585 && !horizontal_surroundings[2].IsEmpty()
586 && !horizontal_surroundings[2].IsHazardous()
587 && horizontal_surroundings[2].GetHeight() - current_node.pos.second < 1.25f
590 const bool above_block = horizontal_surroundings[1].IsClimbable() || horizontal_surroundings[2].IsClimbable() || horizontal_surroundings[2].GetHeight() + 1e-3f > current_node.pos.first.y + 1;
591 const float new_cost = cost[current_node.pos] + 1.0f + 1.0f * above_block + 0.5f * (horizontal_surroundings[1].IsClimbable() || horizontal_surroundings[2].GetHeight() - vertical_surroundings[2].GetHeight() > 0.5);
592 const std::pair<Position, float> new_pos = {
593 next_location +
Position(0, 1 * above_block, 0),
594 above_block ? std::max(current_node.pos.first.y + 1.0f, horizontal_surroundings[2].GetHeight()) : std::max(horizontal_surroundings[2].GetHeight(), horizontal_surroundings[3].GetHeight())
596 auto it = cost.find(new_pos);
598 if (it == cost.end() ||
599 new_cost < it->second)
601 cost[new_pos] = new_cost;
602 nodes_to_explore.emplace(PathNode(
604 new_cost + PathNode::Heuristic(new_pos.first, end))
606 came_from[new_pos] = current_node.pos;
616 if (!horizontal_surroundings[1].IsSolid()
617 && !horizontal_surroundings[1].IsHazardous()
618 && horizontal_surroundings[2].IsEmpty()
619 && horizontal_surroundings[3].IsEmpty()
620 && !horizontal_surroundings[4].IsEmpty()
621 && !horizontal_surroundings[4].IsHazardous()
624 const bool above_block = horizontal_surroundings[4].IsClimbable() || horizontal_surroundings[4].GetHeight() + 1e-3f > current_node.pos.first.y - 1;
625 const float new_cost = cost[current_node.pos] + 3.5f - 1.0f * above_block;
626 const std::pair<Position, float> new_pos = {
627 next_location +
Position(0, -2 + 1 * above_block, 0),
628 above_block ? std::max(current_node.pos.first.y - 1.0f, horizontal_surroundings[4].GetHeight()) : std::max(horizontal_surroundings[4].GetHeight(), horizontal_surroundings[5].GetHeight())
630 auto it = cost.find(new_pos);
632 if (it == cost.end() ||
633 new_cost < it->second)
635 cost[new_pos] = new_cost;
636 nodes_to_explore.emplace(PathNode(
638 new_cost + PathNode::Heuristic(new_pos.first, end))
640 came_from[new_pos] = current_node.pos;
650 if (!horizontal_surroundings[1].IsSolid()
651 && !horizontal_surroundings[1].IsHazardous()
652 && horizontal_surroundings[2].IsEmpty()
653 && horizontal_surroundings[3].IsEmpty()
654 && horizontal_surroundings[4].IsEmpty()
655 && !horizontal_surroundings[5].IsEmpty()
656 && !horizontal_surroundings[5].IsHazardous()
659 const bool above_block = horizontal_surroundings[5].IsClimbable() || horizontal_surroundings[5].GetHeight() + 1e-3f > current_node.pos.first.y - 2;
660 const float new_cost = cost[current_node.pos] + 4.5f - 1.0f * above_block;
661 const std::pair<Position, float> new_pos = {
662 next_location +
Position(0, -3 + 1 * above_block, 0),
663 above_block ? std::max(current_node.pos.first.y - 2.0f, horizontal_surroundings[5].GetHeight()) : horizontal_surroundings[5].GetHeight()
665 auto it = cost.find(new_pos);
667 if (it == cost.end() ||
668 new_cost < it->second)
670 cost[new_pos] = new_cost;
671 nodes_to_explore.emplace(PathNode(
673 new_cost + PathNode::Heuristic(new_pos.first, end))
675 came_from[new_pos] = current_node.pos;
687 if (!horizontal_surroundings[1].IsSolid()
688 && !horizontal_surroundings[1].IsHazardous()
689 && horizontal_surroundings[2].IsEmpty()
690 && horizontal_surroundings[3].IsEmpty()
691 && horizontal_surroundings[4].IsEmpty()
692 && horizontal_surroundings[5].IsEmpty()
695 for (
int y = -4; next_location.
y + y >= world->GetMinY(); --y)
697 pos = next_location +
Position(0, y, 0);
698 block = world->GetBlock(pos);
708 const float new_cost = cost[current_node.pos] + std::abs(y) + 1.5f;
709 const std::pair<Position, float> new_pos = {
710 next_location +
Position(0, y + 1, 0),
711 next_location.
y + y + 1.0f
713 auto it = cost.find(new_pos);
715 if (it == cost.end() ||
716 new_cost < it->second)
718 cost[new_pos] = new_cost;
719 nodes_to_explore.emplace(PathNode(
721 new_cost + PathNode::Heuristic(new_pos.first, end))
723 came_from[new_pos] = current_node.pos;
734 || vertical_surroundings[0].IsSolid()
735 || vertical_surroundings[0].IsHazardous()
736 || !vertical_surroundings[1].IsEmpty()
737 || vertical_surroundings[2].IsClimbable()
738 || vertical_surroundings[3].IsFluid()
739 || vertical_surroundings[3].IsEmpty()
740 || horizontal_surroundings[0].IsSolid()
741 || horizontal_surroundings[0].IsHazardous()
742 || !horizontal_surroundings[1].IsEmpty()
743 || !horizontal_surroundings[2].IsEmpty()
744 || horizontal_surroundings[6].IsSolid()
745 || horizontal_surroundings[6].IsHazardous()
758 if (!horizontal_surroundings[7].IsEmpty()
759 && !horizontal_surroundings[7].IsHazardous()
760 && horizontal_surroundings[7].GetHeight() - current_node.pos.second < 1.25f
765 const float new_cost = cost[current_node.pos] + 5.0f;
766 const std::pair<Position, float> new_pos = {
767 next_next_location +
Position(0, 1, 0),
768 std::max(horizontal_surroundings[7].GetHeight(), horizontal_surroundings[8].GetHeight()),
770 auto it = cost.find(new_pos);
772 if (it == cost.end() ||
773 new_cost < it->second)
775 cost[new_pos] = new_cost;
776 nodes_to_explore.emplace(PathNode(
778 new_cost + PathNode::Heuristic(new_pos.first, end))
780 came_from[new_pos] = current_node.pos;
790 if (horizontal_surroundings[7].IsEmpty()
791 && !horizontal_surroundings[8].IsEmpty()
792 && !horizontal_surroundings[8].IsHazardous()
793 && horizontal_surroundings[8].GetHeight() - current_node.pos.second < 1.25f
796 const bool above_block = horizontal_surroundings[8].IsClimbable() || horizontal_surroundings[8].GetHeight() + 1e-3f > current_node.pos.first.y + 1;
799 const float new_cost = cost[current_node.pos] + 3.0f + 1.0f * above_block;
800 const std::pair<Position, float> new_pos = {
801 next_next_location +
Position(0, above_block * 1, 0),
802 above_block ? std::max(current_node.pos.first.y + 1.0f, horizontal_surroundings[8].GetHeight()) : std::max(horizontal_surroundings[8].GetHeight(), horizontal_surroundings[9].GetHeight())
804 auto it = cost.find(new_pos);
806 if (it == cost.end() ||
807 new_cost < it->second)
809 cost[new_pos] = new_cost;
810 nodes_to_explore.emplace(PathNode(
812 new_cost + PathNode::Heuristic(new_pos.first, end))
814 came_from[new_pos] = current_node.pos;
824 if (horizontal_surroundings[7].IsEmpty()
825 && horizontal_surroundings[8].IsEmpty()
826 && !horizontal_surroundings[9].IsEmpty()
827 && !horizontal_surroundings[9].IsHazardous()
830 const bool above_block = horizontal_surroundings[9].IsClimbable() || horizontal_surroundings[9].GetHeight() + 1e-3f > current_node.pos.first.y;
831 const float new_cost = cost[current_node.pos] + 3.5f - 1.0f * above_block;
832 const std::pair<Position, float> new_pos = {
833 next_next_location +
Position(0, -1 + 1 * above_block, 0),
834 above_block ? std::max(
static_cast<float>(current_node.pos.first.y), horizontal_surroundings[9].GetHeight()) : std::max(horizontal_surroundings[9].GetHeight(), horizontal_surroundings[10].GetHeight())
836 auto it = cost.find(new_pos);
838 if (it == cost.end() ||
839 new_cost < it->second)
841 cost[new_pos] = new_cost;
842 nodes_to_explore.emplace(PathNode(
844 new_cost + PathNode::Heuristic(new_pos.first, end))
846 came_from[new_pos] = current_node.pos;
856 if (horizontal_surroundings[7].IsEmpty()
857 && horizontal_surroundings[8].IsEmpty()
858 && horizontal_surroundings[9].IsEmpty()
859 && !horizontal_surroundings[10].IsEmpty()
860 && !horizontal_surroundings[10].IsHazardous()
863 const bool above_block = horizontal_surroundings[10].IsClimbable() || horizontal_surroundings[10].GetHeight() + 1e-3f > current_node.pos.first.y - 1;
864 const float new_cost = cost[current_node.pos] + 4.5f - 1.0f * above_block;
865 const std::pair<Position, float> new_pos = {
866 next_next_location +
Position(0, -2 + 1 * above_block, 0),
867 above_block ? std::max(current_node.pos.first.y - 1.0f, horizontal_surroundings[10].GetHeight()) : std::max(horizontal_surroundings[10].GetHeight(), horizontal_surroundings[11].GetHeight())
869 auto it = cost.find(new_pos);
871 if (it == cost.end() ||
872 new_cost < it->second)
874 cost[new_pos] = new_cost;
875 nodes_to_explore.emplace(PathNode(
877 new_cost + PathNode::Heuristic(new_pos.first, end))
879 came_from[new_pos] = current_node.pos;
889 if (horizontal_surroundings[7].IsEmpty()
890 && horizontal_surroundings[8].IsEmpty()
891 && horizontal_surroundings[9].IsEmpty()
892 && horizontal_surroundings[10].IsEmpty()
893 && !horizontal_surroundings[11].IsEmpty()
894 && !horizontal_surroundings[11].IsHazardous()
897 const bool above_block = horizontal_surroundings[11].IsClimbable() || horizontal_surroundings[11].GetHeight() + 1e-3f > current_node.pos.first.y - 2;
898 const float new_cost = cost[current_node.pos] + 6.5f - 1.0f * above_block;
899 const std::pair<Position, float> new_pos = {
900 next_next_location +
Position(0, -3 + 1 * above_block, 0),
901 above_block ? std::max(current_node.pos.first.y - 2.0f, horizontal_surroundings[11].GetHeight()) : horizontal_surroundings[1].GetHeight()
903 auto it = cost.find(new_pos);
905 if (it == cost.end() ||
906 new_cost < it->second)
908 cost[new_pos] = new_cost;
909 nodes_to_explore.emplace(PathNode(
911 new_cost + PathNode::Heuristic(new_pos.first, end))
913 came_from[new_pos] = current_node.pos;
919 auto it_end_path = came_from.begin();
926 int best_dist = std::numeric_limits<int>::max();
927 int best_dist_start = std::numeric_limits<int>::max();
928 for (
auto it = came_from.begin(); it != came_from.end(); ++it)
930 const Position diff = it->first.first - end;
931 const int d_xz = std::abs(diff.
x) + std::abs(diff.
z);
932 const int d = d_xz + std::abs(diff.
y);
933 const Position diff_start = it->first.first - start;
934 const int d_start = std::abs(diff_start.
x) + std::abs(diff_start.
y) + std::abs(diff_start.
z);
935 if (d <= dist_tolerance && d >= min_end_dist && d_xz >= min_end_dist_xz &&
936 (d_start < best_dist_start || (d_start == best_dist_start && d < best_dist))
940 best_dist_start = d_start;
948 if (best_dist == std::numeric_limits<int>::max())
950 for (
auto it = came_from.begin(); it != came_from.end(); ++it)
952 const Position diff = it->first.first - end;
953 const int d_xz = std::abs(diff.
x) + std::abs(diff.
z);
954 const int d = d_xz + std::abs(diff.
y);
955 const Position diff_start = it->first.first - start;
956 const int d_start = std::abs(diff_start.
x) + std::abs(diff_start.
y) + std::abs(diff_start.
z);
957 if (d < best_dist || (d == best_dist && d_start < best_dist_start))
960 best_dist_start = d_start;
966 std::deque<std::pair<Position, float>> output_deque;
967 output_deque.push_front(it_end_path->first);
968 while (it_end_path->second.first != start)
970 it_end_path = came_from.find(it_end_path->second);
971 output_deque.push_front(it_end_path->first);
974 return std::vector<std::pair<Position, float>>(output_deque.begin(), output_deque.end());
987 static_cast<int>(std::floor(target_position.
x)),
988 static_cast<int>(std::floor(target_position.
y)),
989 static_cast<int>(std::floor(target_position.
z))
992 const Vector3<double> motion_vector = target_position - local_player->GetPosition();
993 const double half_player_width = 0.5 * local_player->GetWidth();
994 const Vector3<double> horizontal_target_position(target_position.
x, 0.0, target_position.
z);
997 std::shared_ptr<World> world = client.
GetWorld();
999 if (speed_factor != 1.0f)
1001 local_player->SetAttributeModifier(
1005 speed_factor - 1.0f,
1013 local_player->LookAt(look_at_target,
true);
1016 if (std::abs(motion_vector.
x) > 0.5 || std::abs(motion_vector.
z) > 0.5)
1019 if (motion_vector.
y > 0.5 || std::abs(motion_vector.
x) > 1.5 || std::abs(motion_vector.
z) > 1.5)
1022 if (std::abs(motion_vector.
x) < 1.5 && std::abs(motion_vector.
z) < 1.5)
1024 local_player->SetInputsJump(
true);
1028 return local_player->GetY() >= target_block.
y;
1029 }, client, 40.0 * ms_per_tick))
1038 std::floor(local_player->GetX()) + 0.5,
1040 std::floor(local_player->GetZ()) + 0.5
1045 if (local_player->GetDirtyInputs())
1051 local_player->LookAt(look_at_target,
false);
1052 local_player->SetInputsForward(1.0);
1053 local_player->SetInputsSprint(sprint);
1055 if (
Vector3<double>(local_player->GetX(), 0.0, local_player->GetZ()).
SqrDist(current_block_center_xz) > half_player_width * half_player_width)
1058 local_player->SetInputsJump(
true);
1063 }, client, 20.0 * ms_per_tick))
1072 if (local_player->GetDirtyInputs())
1078 if (
Vector3<double>(current_pos.
x, 0.0, current_pos.
z).
SqrDist(horizontal_target_position) < (0.5 - half_player_width) * (0.5 - half_player_width))
1083 local_player->LookAt(look_at_target,
false);
1085 double forward = 1.0;
1088 if (motion_vector.
y < -0.5 &&
1089 static_cast<int>(std::floor(current_pos.
x)) == target_block.
x &&
1090 static_cast<int>(std::floor(current_pos.
z)) == target_block.
z)
1092 if (std::max(std::abs(speed.
x), std::abs(speed.
z)) > 0.12)
1096 else if (std::max(std::abs(speed.
x), std::abs(speed.
z)) > 0.06)
1101 local_player->SetInputsForward(forward);
1102 local_player->SetInputsSprint(sprint && (forward == 1.0));
1105 }, client, (std::abs(motion_vector.
x) + std::abs(motion_vector.
z) + (motion_vector.
y < -0.5)) * 20.0 * ms_per_tick))
1117 if (local_player->GetDirtyInputs())
1122 if (
static_cast<int>(std::floor(local_player->GetY())) <= target_block.
y &&
1123 (local_player->GetOnGround() || local_player->IsClimbing() || local_player->IsInFluid()))
1130 static_cast<int>(std::floor(current_pos.x)),
1131 static_cast<int>(std::floor(current_pos.y)),
1132 static_cast<int>(std::floor(current_pos.z))
1134 local_player->SetInputsSneak(feet_block !=
nullptr &&
1136 local_player->SetInputsJump(local_player->GetFlying());
1139 if (
Vector3<double>(current_pos.x, 0.0, current_pos.z).
SqrDist(horizontal_target_position) > (0.5 - half_player_width) * (0.5 - half_player_width))
1141 local_player->LookAt(look_at_target,
false);
1142 local_player->SetInputsForward(1.0);
1146 }, client, 20.0 * ms_per_tick + (1 + std::abs(motion_vector.
y))))
1155 if (local_player->GetDirtyInputs())
1161 if (
static_cast<int>(std::floor(current_pos.y)) >= target_block.
y)
1166 local_player->SetInputsJump(
true);
1169 if (
Vector3<double>(current_pos.x, 0.0, current_pos.z).
SqrDist(horizontal_target_position) > (0.5 - half_player_width) * (0.5 - half_player_width))
1171 local_player->LookAt(look_at_target,
false);
1172 local_player->SetInputsForward(1.0);
1176 }, client, 20.0 * ms_per_tick * (1 + std::abs(motion_vector.
y))))
1184 if (local_player->GetDirtyInputs())
1190 if (local_player->GetY() >= target_position.
y && local_player->GetY() - target_position.
y < 0.2)
1197 static_cast<int>(std::floor(current_pos.x)),
1198 static_cast<int>(std::floor(current_pos.y)),
1199 static_cast<int>(std::floor(current_pos.z))
1201 local_player->SetInputsSneak(feet_block !=
nullptr &&
1203 local_player->SetInputsJump(local_player->GetFlying());
1206 if (
Vector3<double>(current_pos.x, 0.0, current_pos.z).
SqrDist(horizontal_target_position) > (0.5 - half_player_width) * (0.5 - half_player_width))
1208 local_player->LookAt(look_at_target,
false);
1209 local_player->SetInputsForward(1.0);
1213 }, client, 20.0 * ms_per_tick);