Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import com.destroystokyo.paper.entity.Pathfinder;
- import lombok.NonNull;
- import org.bukkit.Location;
- import org.bukkit.entity.Mob;
- import javax.annotation.Nullable;
- import java.util.function.Predicate;
- // По неизвестной причине обычный навигатор не доводит моба до точки назначения 4-5 блоков.
- // Подозреваю, что это сделано с целью оптимизации расхода оперативной памяти.
- // Скорее всего, для всего пути может создаться лишь определённое кол-во точек,
- // поэтому на больших расстояниях дистанция между точками увеличивается,
- // что и приводит к большой погрешности.
- // Таким образом, при достижении последней точки необходимо запустить навигацию ещё раз.
- // Расстояние между точками станет меньше, погрешность уменьшится до допустимого значения в 1 блок.
- // Почему такой метод не использует сама игра - неясно. Возможно не нужна такая точность,
- // а, возможно, и нет необходимости "запускать" мобов на столь большое расстояние.
- // Поскольку нам нужна точность - используем этот прекрасный класс
- // Author: Dymeth.Ru
- public class ExactNavigator {
- private final Mob mob;
- private final Location target;
- private final double movingSpeed;
- private final Predicate<ExactNavigator> continueOnFail;
- private long lastDistanceCalculatedAt;
- private boolean failed;
- public ExactNavigator(@NonNull Mob mob, @NonNull Location target, double movingSpeed, @Nullable Predicate<ExactNavigator> continueOnFail) {
- this.mob = mob;
- this.target = target;
- this.movingSpeed = movingSpeed;
- this.continueOnFail = continueOnFail;
- this.lastDistanceCalculatedAt = 0;
- this.failed = false;
- this.mob.getPathfinder().moveTo(this.target, this.movingSpeed);
- }
- @NonNull
- public Mob getMob() {
- return this.mob;
- }
- @NonNull
- public Location getTarget() {
- return this.target;
- }
- public boolean isPathCompleteSuccessfully() {
- Pathfinder.PathResult path = this.mob.getPathfinder().getCurrentPath();
- if (path == null) return true;
- if (path.getNextPoint() != null) return false;
- long now = System.currentTimeMillis();
- if (now - this.lastDistanceCalculatedAt > 1_000) {
- this.lastDistanceCalculatedAt = now;
- if (this.mob.getLocation().distanceSquared(this.target) < 1) return true;
- this.mob.getPathfinder().moveTo(this.target, this.movingSpeed);
- return false;
- }
- // Моб не смог найти путь до цели
- boolean continuePathfinding;
- if (this.continueOnFail == null) continuePathfinding = false;
- else continuePathfinding = this.continueOnFail.test(this);
- if (continuePathfinding) return false;
- this.mob.getPathfinder().stopPathfinding();
- this.failed = true;
- return false;
- }
- public boolean isPathFailed() {
- return this.failed;
- }
- public boolean isPathCompleteOrFailed() {
- return this.failed || this.isPathCompleteSuccessfully();
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment