92 std::vector<std::pair<Position, float>>
FindPath(
93 const std::shared_ptr<World>& world,
95 const int dist_tolerance,
const int min_end_dist,
const int min_end_dist_xz,
96 const bool allow_jump,
const bool take_damage,
const float step_height
101 std::pair<Position, float> pos;
104 PathNode(
const std::pair<Position, float>& p,
const float s)
110 bool operator>(
const PathNode& rhs)
const
112 return score > rhs.score;
117 return static_cast<float>(std::abs(a.
x - b.
x) + std::abs(a.
y - b.
y) + std::abs(a.
z - b.
z));
121 constexpr int budget_visit = 15000;
123 const std::array<Position, 4> neighbour_offsets = {
Position(1, 0, 0),
Position(-1, 0, 0),
Position(0, 0, 1),
Position(0, 0, -1) };
124 std::priority_queue<PathNode, std::vector<PathNode>, std::greater<PathNode> > nodes_to_explore;
125 std::unordered_map<std::pair<Position, float>, std::pair<Position, float>,
PosFloatPairHash> came_from;
126 std::unordered_map<std::pair<Position, float>, float,
PosFloatPairHash> cost;
128 auto add_node_if_better = [&](
const std::pair<Position, float>& new_pos,
float new_cost,
const PathNode& from) {
129 auto it = cost.find(new_pos);
130 if (it == cost.end() || new_cost < it->second)
132 cost[new_pos] = new_cost;
133 nodes_to_explore.emplace(PathNode(new_pos, new_cost + PathNode::Heuristic(new_pos.first, end)));
134 came_from[new_pos] = from.pos;
138 const Blockstate* block = world->GetBlock(start);
140 came_from[nodes_to_explore.top().pos] = nodes_to_explore.top().pos;
141 cost[nodes_to_explore.top().pos] = 0.0f;
146 bool suitable_location_found =
false;
148 bool end_reached =
false;
150 bool end_is_inside_solid =
false;
151 block = world->GetBlock(end);
152 end_is_inside_solid = block !=
nullptr && block->
IsSolid();
154 while (!nodes_to_explore.empty())
157 PathNode current_node = nodes_to_explore.top();
158 nodes_to_explore.pop();
162 const float h = PathNode::Heuristic(current_node.pos.first, end);
163 if (cost[current_node.pos] + h < current_node.score)
169 end_reached |= current_node.pos.first == end;
170 suitable_location_found |=
171 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 &&
172 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 &&
173 std::abs(end.
x - current_node.pos.first.x) + std::abs(end.
z - current_node.pos.first.z) >= min_end_dist_xz;
176 count_visit > budget_visit ||
178 (suitable_location_found && (end_reached || end_is_inside_solid)))
184 std::array<PathfindingBlockstate, 6> vertical_surroundings;
194 block = world->GetBlock(pos);
196 pos = current_node.pos.first +
Position(0, 1, 0);
197 block = world->GetBlock(pos);
200 pos = current_node.pos.first;
201 block = world->GetBlock(pos);
203 const bool can_jump =
204 vertical_surroundings[2].GetBlockstate() !=
nullptr &&
205 vertical_surroundings[2].GetBlockstate()->CanJumpWhenFeetInside();
209 if (!vertical_surroundings[2].IsSolid() && !vertical_surroundings[2].IsHazardous())
213 pos = current_node.pos.first +
Position(0, -1, 0);
214 block = world->GetBlock(pos);
218 if (!vertical_surroundings[3].IsSolid() && !vertical_surroundings[3].IsHazardous())
220 pos = current_node.pos.first +
Position(0, -2, 0);
221 block = world->GetBlock(pos);
223 pos = current_node.pos.first +
Position(0, -3, 0);
224 block = world->GetBlock(pos);
237 if (vertical_surroundings[2].IsClimbable()
238 && !vertical_surroundings[1].IsSolid()
239 && !vertical_surroundings[1].IsHazardous()
240 && !vertical_surroundings[0].IsSolid()
241 && !vertical_surroundings[0].IsHazardous()
244 const float new_cost = cost[current_node.pos] + 1.0f;
245 const std::pair<Position, float> new_pos = {
246 current_node.pos.first +
Position(0, 1, 0),
247 current_node.pos.first.y + 1.0f
249 add_node_if_better(new_pos, new_cost, current_node);
259 && vertical_surroundings[1].IsClimbable()
260 && !vertical_surroundings[0].IsSolid()
261 && !vertical_surroundings[0].IsHazardous()
262 && (vertical_surroundings[2].IsSolid() ||
263 vertical_surroundings[3].IsSolid())
266 const float new_cost = cost[current_node.pos] + 1.5f;
267 const std::pair<Position, float> new_pos = {
268 current_node.pos.first +
Position(0, 1, 0),
269 current_node.pos.first.y + 1.0f
271 add_node_if_better(new_pos, new_cost, current_node);
280 if (!vertical_surroundings[2].IsSolid() &&
281 vertical_surroundings[3].IsClimbable()
284 const float new_cost = cost[current_node.pos] + 1.0f;
285 const std::pair<Position, float> new_pos = {
286 current_node.pos.first +
Position(0, -1, 0),
287 current_node.pos.first.y - 1.0f
289 add_node_if_better(new_pos, new_cost, current_node);
298 if (!vertical_surroundings[2].IsSolid() &&
299 vertical_surroundings[3].IsClimbable()
300 && vertical_surroundings[4].IsEmpty()
301 && !vertical_surroundings[5].IsEmpty()
302 && !vertical_surroundings[5].IsHazardous()
305 const bool above_block = vertical_surroundings[5].IsClimbable() || vertical_surroundings[5].GetHeight() + 1e-3f > current_node.pos.first.y - 2;
306 const float new_cost = cost[current_node.pos] + 3.0f - 1.0f * above_block;
307 const std::pair<Position, float> new_pos = {
308 current_node.pos.first +
Position(0, -3 + 1 * above_block, 0),
309 above_block ? std::max(current_node.pos.first.y - 2.0f, vertical_surroundings[5].GetHeight()) : vertical_surroundings[5].GetHeight()
311 add_node_if_better(new_pos, new_cost, current_node);
322 if (vertical_surroundings[2].IsClimbable()
323 && vertical_surroundings[3].IsEmpty()
324 && vertical_surroundings[4].IsEmpty()
325 && !vertical_surroundings[5].IsEmpty()
326 && !vertical_surroundings[5].IsHazardous()
329 const bool above_block = vertical_surroundings[5].IsClimbable() || vertical_surroundings[5].GetHeight() + 1e-3f > current_node.pos.first.y - 2;
330 const float new_cost = cost[current_node.pos] + 3.0f - 1.0f * above_block;
331 const std::pair<Position, float> new_pos = {
332 current_node.pos.first +
Position(0, -3 + 1 * above_block, 0),
333 above_block ? std::max(current_node.pos.first.y - 2.0f, vertical_surroundings[5].GetHeight()) : vertical_surroundings[5].GetHeight()
335 add_node_if_better(new_pos, new_cost, current_node);
347 if (!vertical_surroundings[2].IsSolid() &&
348 vertical_surroundings[3].IsClimbable()
349 && vertical_surroundings[4].IsEmpty()
350 && vertical_surroundings[5].IsEmpty()
353 for (
int y = -4; current_node.pos.first.y + y >= world->GetMinY(); --y)
355 pos = current_node.pos.first +
Position(0, y, 0);
356 block = world->GetBlock(pos);
366 const float new_cost = cost[current_node.pos] + std::abs(y);
367 const std::pair<Position, float> new_pos = {
368 current_node.pos.first +
Position(0, y + 1, 0),
369 current_node.pos.first.y + y + 1.0f
371 add_node_if_better(new_pos, new_cost, current_node);
381 for (
int i = 0; i < neighbour_offsets.size(); ++i)
383 const Position next_location = current_node.pos.first + neighbour_offsets[i];
384 const Position next_next_location = next_location + neighbour_offsets[i];
387 std::array<PathfindingBlockstate, 12> horizontal_surroundings;
399 pos = next_location +
Position(0, 2, 0);
400 block = world->GetBlock(pos);
402 pos = next_location +
Position(0, 1, 0);
403 block = world->GetBlock(pos);
405 const bool horizontal_movement =
406 (!horizontal_surroundings[1].IsSolid() ||
407 (horizontal_surroundings[1].GetHeight() - current_node.pos.second < 1.25f &&
408 !horizontal_surroundings[0].IsSolid() && !horizontal_surroundings[0].IsHazardous())
409 ) && !horizontal_surroundings[1].IsHazardous();
412 if (horizontal_movement)
415 block = world->GetBlock(pos);
417 pos = next_location +
Position(0, -1, 0);
418 block = world->GetBlock(pos);
420 pos = next_location +
Position(0, -2, 0);
421 block = world->GetBlock(pos);
423 pos = next_location +
Position(0, -3, 0);
424 block = world->GetBlock(pos);
430 if (allow_jump && can_jump)
432 pos = next_next_location +
Position(0, 2, 0);
433 block = world->GetBlock(pos);
435 pos = next_next_location +
Position(0, 1, 0);
436 block = world->GetBlock(pos);
438 pos = next_next_location;
439 block = world->GetBlock(pos);
441 pos = next_next_location +
Position(0, -1, 0);
442 block = world->GetBlock(pos);
444 pos = next_next_location +
Position(0, -2, 0);
445 block = world->GetBlock(pos);
447 pos = next_next_location +
Position(0, -3, 0);
448 block = world->GetBlock(pos);
463 if (!horizontal_surroundings[1].IsSolid()
464 && !horizontal_surroundings[1].IsHazardous()
465 && !horizontal_surroundings[2].IsSolid()
466 && !horizontal_surroundings[2].IsHazardous()
467 && !horizontal_surroundings[3].IsEmpty()
468 && !horizontal_surroundings[3].IsHazardous()
469 && (!horizontal_surroundings[3].IsFluid()
470 || !vertical_surroundings[3].IsFluid()
471 || horizontal_surroundings[2].IsFluid()
472 || vertical_surroundings[2].IsFluid())
475 const bool above_block = horizontal_surroundings[2].IsClimbable() || horizontal_surroundings[3].IsClimbable() || horizontal_surroundings[3].GetHeight() + 1e-3f > current_node.pos.first.y;
476 const float new_cost = cost[current_node.pos] + 2.0f - 1.0f * above_block;
477 const std::pair<Position, float> new_pos = {
478 next_location +
Position(0, -1 + 1 * above_block, 0),
479 above_block ? std::max(
static_cast<float>(next_location.
y), horizontal_surroundings[3].GetHeight()) : std::max(horizontal_surroundings[3].GetHeight(), horizontal_surroundings[4].GetHeight())
481 add_node_if_better(new_pos, new_cost, current_node);
492 && !vertical_surroundings[0].IsSolid()
493 && !vertical_surroundings[0].IsHazardous()
494 && vertical_surroundings[1].IsEmpty()
495 && (vertical_surroundings[2].IsSolid() || !vertical_surroundings[3].IsClimbable())
496 && !horizontal_surroundings[0].IsSolid()
497 && !horizontal_surroundings[0].IsHazardous()
498 && !horizontal_surroundings[1].IsEmpty()
499 && !horizontal_surroundings[1].IsHazardous()
500 && horizontal_surroundings[1].GetHeight() - current_node.pos.second < 1.25f
503 const float new_cost = cost[current_node.pos] + 2.5f;
504 const std::pair<Position, float> new_pos = {
506 std::max(horizontal_surroundings[1].GetHeight(), horizontal_surroundings[2].GetHeight())
508 add_node_if_better(new_pos, new_cost, current_node);
517 if ((can_jump || horizontal_surroundings[2].GetHeight() - current_node.pos.second < step_height)
518 && !vertical_surroundings[0].IsSolid()
519 && !vertical_surroundings[0].IsHazardous()
520 && vertical_surroundings[1].IsEmpty()
521 && (vertical_surroundings[2].IsSolid() || (vertical_surroundings[2].IsEmpty() && vertical_surroundings[3].IsSolid()))
522 && !horizontal_surroundings[0].IsSolid()
523 && !horizontal_surroundings[0].IsHazardous()
524 && !horizontal_surroundings[1].IsSolid()
525 && !horizontal_surroundings[1].IsHazardous()
526 && !horizontal_surroundings[2].IsEmpty()
527 && !horizontal_surroundings[2].IsHazardous()
528 && horizontal_surroundings[2].GetHeight() - current_node.pos.second < 1.25f
531 const bool above_block = horizontal_surroundings[1].IsClimbable() || horizontal_surroundings[2].IsClimbable() || horizontal_surroundings[2].GetHeight() + 1e-3f > current_node.pos.first.y + 1;
532 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);
533 const std::pair<Position, float> new_pos = {
534 next_location +
Position(0, 1 * above_block, 0),
535 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())
537 add_node_if_better(new_pos, new_cost, current_node);
546 if (!horizontal_surroundings[1].IsSolid()
547 && !horizontal_surroundings[1].IsHazardous()
548 && horizontal_surroundings[2].IsEmpty()
549 && horizontal_surroundings[3].IsEmpty()
550 && !horizontal_surroundings[4].IsEmpty()
551 && !horizontal_surroundings[4].IsHazardous()
554 const bool above_block = horizontal_surroundings[4].IsClimbable() || horizontal_surroundings[4].GetHeight() + 1e-3f > current_node.pos.first.y - 1;
555 const float new_cost = cost[current_node.pos] + 3.5f - 1.0f * above_block;
556 const std::pair<Position, float> new_pos = {
557 next_location +
Position(0, -2 + 1 * above_block, 0),
558 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())
560 add_node_if_better(new_pos, new_cost, current_node);
569 if (!horizontal_surroundings[1].IsSolid()
570 && !horizontal_surroundings[1].IsHazardous()
571 && horizontal_surroundings[2].IsEmpty()
572 && horizontal_surroundings[3].IsEmpty()
573 && horizontal_surroundings[4].IsEmpty()
574 && !horizontal_surroundings[5].IsEmpty()
575 && !horizontal_surroundings[5].IsHazardous()
578 const bool above_block = horizontal_surroundings[5].IsClimbable() || horizontal_surroundings[5].GetHeight() + 1e-3f > current_node.pos.first.y - 2;
579 const float new_cost = cost[current_node.pos] + 4.5f - 1.0f * above_block;
580 const std::pair<Position, float> new_pos = {
581 next_location +
Position(0, -3 + 1 * above_block, 0),
582 above_block ? std::max(current_node.pos.first.y - 2.0f, horizontal_surroundings[5].GetHeight()) : horizontal_surroundings[5].GetHeight()
584 add_node_if_better(new_pos, new_cost, current_node);
595 if (!horizontal_surroundings[1].IsSolid()
596 && !horizontal_surroundings[1].IsHazardous()
597 && horizontal_surroundings[2].IsEmpty()
598 && horizontal_surroundings[3].IsEmpty()
599 && horizontal_surroundings[4].IsEmpty()
600 && horizontal_surroundings[5].IsEmpty()
603 for (
int y = -4; next_location.
y + y >= world->GetMinY(); --y)
605 pos = next_location +
Position(0, y, 0);
606 block = world->GetBlock(pos);
616 const float new_cost = cost[current_node.pos] + std::abs(y) + 1.5f;
617 const std::pair<Position, float> new_pos = {
618 next_location +
Position(0, y + 1, 0),
619 next_location.
y + y + 1.0f
621 add_node_if_better(new_pos, new_cost, current_node);
632 || vertical_surroundings[0].IsSolid()
633 || vertical_surroundings[0].IsHazardous()
634 || vertical_surroundings[1].IsSolid()
635 || vertical_surroundings[1].IsHazardous()
636 || vertical_surroundings[3].IsFluid()
637 || (!vertical_surroundings[2].IsSolid() &&
638 vertical_surroundings[3].IsEmpty())
639 || horizontal_surroundings[0].IsSolid()
640 || horizontal_surroundings[0].IsHazardous()
641 || horizontal_surroundings[1].IsSolid()
642 || horizontal_surroundings[1].IsHazardous()
643 || horizontal_surroundings[2].IsSolid()
644 || horizontal_surroundings[2].IsHazardous()
645 || horizontal_surroundings[6].IsSolid()
646 || horizontal_surroundings[6].IsHazardous()
659 if (!horizontal_surroundings[7].IsEmpty()
660 && !horizontal_surroundings[7].IsHazardous()
661 && horizontal_surroundings[7].GetHeight() - current_node.pos.second < 1.25f
666 const float new_cost = cost[current_node.pos] + 5.0f;
667 const std::pair<Position, float> new_pos = {
668 next_next_location +
Position(0, 1, 0),
669 std::max(horizontal_surroundings[7].GetHeight(), horizontal_surroundings[8].GetHeight()),
671 add_node_if_better(new_pos, new_cost, current_node);
680 if (horizontal_surroundings[7].IsEmpty()
681 && !horizontal_surroundings[8].IsEmpty()
682 && !horizontal_surroundings[8].IsHazardous()
683 && horizontal_surroundings[8].GetHeight() - current_node.pos.second < 1.25f
686 const bool above_block = horizontal_surroundings[8].IsClimbable() || horizontal_surroundings[8].GetHeight() + 1e-3f > current_node.pos.first.y + 1;
689 const float new_cost = cost[current_node.pos] + 3.0f + 1.0f * above_block;
690 const std::pair<Position, float> new_pos = {
691 next_next_location +
Position(0, above_block * 1, 0),
692 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())
694 add_node_if_better(new_pos, new_cost, current_node);
703 if (horizontal_surroundings[7].IsEmpty()
704 && horizontal_surroundings[8].IsEmpty()
705 && !horizontal_surroundings[9].IsEmpty()
706 && !horizontal_surroundings[9].IsHazardous()
709 const bool above_block = horizontal_surroundings[9].IsClimbable() || horizontal_surroundings[9].GetHeight() + 1e-3f > current_node.pos.first.y;
710 const float new_cost = cost[current_node.pos] + 3.5f - 1.0f * above_block;
711 const std::pair<Position, float> new_pos = {
712 next_next_location +
Position(0, -1 + 1 * above_block, 0),
713 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())
715 add_node_if_better(new_pos, new_cost, current_node);
724 if (horizontal_surroundings[7].IsEmpty()
725 && horizontal_surroundings[8].IsEmpty()
726 && horizontal_surroundings[9].IsEmpty()
727 && !horizontal_surroundings[10].IsEmpty()
728 && !horizontal_surroundings[10].IsHazardous()
731 const bool above_block = horizontal_surroundings[10].IsClimbable() || horizontal_surroundings[10].GetHeight() + 1e-3f > current_node.pos.first.y - 1;
732 const float new_cost = cost[current_node.pos] + 4.5f - 1.0f * above_block;
733 const std::pair<Position, float> new_pos = {
734 next_next_location +
Position(0, -2 + 1 * above_block, 0),
735 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())
737 add_node_if_better(new_pos, new_cost, current_node);
746 if (horizontal_surroundings[7].IsEmpty()
747 && horizontal_surroundings[8].IsEmpty()
748 && horizontal_surroundings[9].IsEmpty()
749 && horizontal_surroundings[10].IsEmpty()
750 && !horizontal_surroundings[11].IsEmpty()
751 && !horizontal_surroundings[11].IsHazardous()
754 const bool above_block = horizontal_surroundings[11].IsClimbable() || horizontal_surroundings[11].GetHeight() + 1e-3f > current_node.pos.first.y - 2;
755 const float new_cost = cost[current_node.pos] + 6.5f - 1.0f * above_block;
756 const std::pair<Position, float> new_pos = {
757 next_next_location +
Position(0, -3 + 1 * above_block, 0),
758 above_block ? std::max(current_node.pos.first.y - 2.0f, horizontal_surroundings[11].GetHeight()) : horizontal_surroundings[11].GetHeight()
760 add_node_if_better(new_pos, new_cost, current_node);
765 auto it_end_path = came_from.begin();
772 int best_dist = std::numeric_limits<int>::max();
773 int best_dist_start = std::numeric_limits<int>::max();
774 for (
auto it = came_from.begin(); it != came_from.end(); ++it)
776 const Position diff = it->first.first - end;
777 const int d_xz = std::abs(diff.
x) + std::abs(diff.
z);
778 const int d = d_xz + std::abs(diff.
y);
779 const Position diff_start = it->first.first - start;
780 const int d_start = std::abs(diff_start.
x) + std::abs(diff_start.
y) + std::abs(diff_start.
z);
781 if (d <= dist_tolerance && d >= min_end_dist && d_xz >= min_end_dist_xz &&
782 (d_start < best_dist_start || (d_start == best_dist_start && d < best_dist))
786 best_dist_start = d_start;
794 if (best_dist == std::numeric_limits<int>::max())
796 for (
auto it = came_from.begin(); it != came_from.end(); ++it)
798 const Position diff = it->first.first - end;
799 const int d_xz = std::abs(diff.
x) + std::abs(diff.
z);
800 const int d = d_xz + std::abs(diff.
y);
801 const Position diff_start = it->first.first - start;
802 const int d_start = std::abs(diff_start.
x) + std::abs(diff_start.
y) + std::abs(diff_start.
z);
803 if (d >= min_end_dist && d_xz >= min_end_dist_xz && (d < best_dist || d == best_dist && d_start < best_dist_start))
806 best_dist_start = d_start;
812 std::deque<std::pair<Position, float>> output_deque;
813 output_deque.push_front(it_end_path->first);
814 while (it_end_path->second.first != start)
816 it_end_path = came_from.find(it_end_path->second);
817 output_deque.push_front(it_end_path->first);
820 return std::vector<std::pair<Position, float>>(output_deque.begin(), output_deque.end());
833 static_cast<int>(std::floor(target_position.
x)),
834 static_cast<int>(std::floor(target_position.
y)),
835 static_cast<int>(std::floor(target_position.
z))
838 const Vector3<double> motion_vector = target_position - local_player->GetPosition();
839 const double half_player_width = 0.5 * local_player->GetWidth();
840 const Vector3<double> horizontal_target_position(target_position.
x, 0.0, target_position.
z);
843 std::shared_ptr<World> world = client.
GetWorld();
845 if (speed_factor != 1.0f)
847 local_player->SetAttributeModifier(
859 local_player->LookAt(look_at_target,
true);
862 if (std::abs(motion_vector.
x) > 0.5 || std::abs(motion_vector.
z) > 0.5)
865 if (motion_vector.
y > 0.5 || std::abs(motion_vector.
x) > 1.5 || std::abs(motion_vector.
z) > 1.5)
868 if (std::abs(motion_vector.
x) < 1.5 && std::abs(motion_vector.
z) < 1.5)
870 local_player->SetInputsJump(
true);
874 return local_player->GetY() >= target_block.
y;
875 }, client, 40.0 * ms_per_tick))
884 std::floor(local_player->GetX()) + 0.5,
886 std::floor(local_player->GetZ()) + 0.5
891 if (local_player->GetDirtyInputs())
897 local_player->LookAt(look_at_target,
false);
898 local_player->SetInputsForward(1.0);
899 local_player->SetInputsSprint(sprint);
901 if (
Vector3<double>(local_player->GetX(), 0.0, local_player->GetZ()).
SqrDist(current_block_center_xz) > half_player_width * half_player_width)
904 local_player->SetInputsJump(
true);
909 }, client, 20.0 * ms_per_tick))
918 if (local_player->GetDirtyInputs())
924 const Vector3<double> current_motion_vector = target_position - current_pos;
926 if ((current_motion_vector.
x * motion_vector.
x + current_motion_vector.
z * motion_vector.
z) < 0.0 ||
927 Vector3<double>(current_pos.
x, 0.0, current_pos.
z).
SqrDist(horizontal_target_position) < (0.5 - half_player_width) * (0.5 - half_player_width))
932 local_player->LookAt(look_at_target,
false);
934 double forward = 1.0;
937 if (motion_vector.
y < -0.5 &&
938 static_cast<int>(std::floor(current_pos.
x)) == target_block.
x &&
939 static_cast<int>(std::floor(current_pos.
z)) == target_block.
z)
941 if (std::max(std::abs(speed.
x), std::abs(speed.
z)) > 0.12)
945 else if (std::max(std::abs(speed.
x), std::abs(speed.
z)) > 0.06)
950 local_player->SetInputsForward(forward);
951 local_player->SetInputsSprint(sprint && (forward == 1.0));
954 }, client, (std::abs(motion_vector.
x) + std::abs(motion_vector.
z) + (motion_vector.
y < -0.5)) * 20.0 * ms_per_tick))
966 if (local_player->GetDirtyInputs())
971 if (
static_cast<int>(std::floor(local_player->GetY())) <= target_block.
y &&
972 (local_player->GetOnGround() || local_player->IsClimbing() || local_player->IsInFluid()))
979 static_cast<int>(std::floor(current_pos.x)),
980 static_cast<int>(std::floor(current_pos.y)),
981 static_cast<int>(std::floor(current_pos.z))
983 local_player->SetInputsSneak(feet_block !=
nullptr &&
985 local_player->SetInputsJump(local_player->GetFlying());
988 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))
990 local_player->LookAt(look_at_target,
false);
991 local_player->SetInputsForward(1.0);
995 }, client, 20.0 * ms_per_tick * (1 + std::abs(motion_vector.
y))))
1004 if (local_player->GetDirtyInputs())
1010 if (
static_cast<int>(std::floor(current_pos.y)) >= target_block.
y)
1015 local_player->SetInputsJump(
true);
1018 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))
1020 local_player->LookAt(look_at_target,
false);
1021 local_player->SetInputsForward(1.0);
1025 }, client, 20.0 * ms_per_tick * (1 + std::abs(motion_vector.
y))))
1033 if (local_player->GetDirtyInputs())
1039 if (local_player->GetY() >= target_position.
y && local_player->GetY() - target_position.
y < 0.2)
1046 static_cast<int>(std::floor(current_pos.x)),
1047 static_cast<int>(std::floor(current_pos.y)),
1048 static_cast<int>(std::floor(current_pos.z))
1050 local_player->SetInputsSneak(feet_block !=
nullptr &&
1052 local_player->SetInputsJump(local_player->GetFlying());
1055 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))
1057 local_player->LookAt(look_at_target,
false);
1058 local_player->SetInputsForward(1.0);
1062 }, client, 20.0 * ms_per_tick);