diff options
| author | syeyoung <cyoung06@naver.com> | 2023-01-25 20:36:08 +0900 |
|---|---|---|
| committer | syeyoung <cyoung06@naver.com> | 2023-01-25 20:36:08 +0900 |
| commit | b844a5d4665daa27c1450a35c020fdd59e6316ee (patch) | |
| tree | a3ff102a5bf048645136290415fdbaaf3c21a687 | |
| parent | 7483d19f603790bf565fa65519d530cca6e6c144 (diff) | |
| download | Skyblock-Dungeons-Guide-b844a5d4665daa27c1450a35c020fdd59e6316ee.tar.gz Skyblock-Dungeons-Guide-b844a5d4665daa27c1450a35c020fdd59e6316ee.tar.bz2 Skyblock-Dungeons-Guide-b844a5d4665daa27c1450a35c020fdd59e6316ee.zip | |
- coroutinish pathfinder
Signed-off-by: syeyoung <cyoung06@naver.com>
15 files changed, 784 insertions, 979 deletions
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/DungeonContext.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/DungeonContext.java index 62c557d7..42fa664c 100755 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/DungeonContext.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/DungeonContext.java @@ -29,6 +29,7 @@ import kr.syeyoung.dungeonsguide.mod.dungeon.map.DungeonMapConstantRetriever; import kr.syeyoung.dungeonsguide.mod.dungeon.map.DungeonMapLayout; import kr.syeyoung.dungeonsguide.mod.dungeon.map.DungeonRoomScaffoldParser; import kr.syeyoung.dungeonsguide.mod.dungeon.map.MapPlayerProcessor; +import kr.syeyoung.dungeonsguide.mod.dungeon.pathfinding.algorithms.PathfinderExecutor; import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.RoomProcessor; import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bossfight.BossfightProcessor; @@ -54,6 +55,7 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.concurrent.CopyOnWriteArrayList; public class DungeonContext { @Getter @Setter @@ -67,6 +69,9 @@ public class DungeonContext { @Getter private DungeonEventRecorder recorder = new DungeonEventRecorder(); + @Getter + private List<PathfinderExecutor> executors = new CopyOnWriteArrayList<>(); + @Getter private final List<RoomProcessor> globalRoomProcessors = new ArrayList<>(); @@ -92,6 +97,8 @@ public class DungeonContext { @Getter @Setter public int percentage; + private PathfinderExecutorExecutor executor = new PathfinderExecutorExecutor(this); + public void setGotMimic(boolean gotMimic) { this.gotMimic = gotMimic; @@ -130,6 +137,8 @@ public class DungeonContext { init = System.currentTimeMillis(); + + executor.start(); } @@ -202,6 +211,10 @@ public class DungeonContext { } } + public void cleanup() { + executor.interrupt(); + } + @Getter private boolean ended = false; @Getter diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/DungeonFacade.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/DungeonFacade.java index cfa4e0cb..9ee4a55a 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/DungeonFacade.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/DungeonFacade.java @@ -34,9 +34,14 @@ import java.security.NoSuchAlgorithmException; public class DungeonFacade { @Getter - @Setter private DungeonContext context; + public void setContext(DungeonContext context) { + if (this.context != null) + this.context.cleanup(); + this.context = context; + } + public void init() { try { DungeonRoomInfoRegistry.loadAll(Main.getConfigDir()); diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/PathfinderExecutorExecutor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/PathfinderExecutorExecutor.java new file mode 100644 index 00000000..676dd017 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/PathfinderExecutorExecutor.java @@ -0,0 +1,56 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2023 cyoung06 (syeyoung) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.mod.dungeon; + +import kr.syeyoung.dungeonsguide.mod.DungeonsGuide; +import kr.syeyoung.dungeonsguide.mod.dungeon.pathfinding.algorithms.PathfinderExecutor; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import net.minecraft.client.Minecraft; + +import java.awt.*; + +public class PathfinderExecutorExecutor extends Thread{ + public PathfinderExecutorExecutor(DungeonContext context) { + super(DungeonsGuide.THREAD_GROUP, "DG Pathfinder"); + this.context =context; + } + private DungeonContext context; + @Override + public void run() { + while(!isInterrupted()) { + if (context.getScaffoldParser() != null) { + Point roomPt = context.getScaffoldParser().getDungeonMapLayout().worldPointToRoomPoint(Minecraft.getMinecraft().thePlayer.getPosition()); + + DungeonRoom dungeonRoom = context.getScaffoldParser().getRoomMap().get(roomPt); + try { + for (PathfinderExecutor executor : context.getExecutors()) { + if (executor.getDungeonRoom() == dungeonRoom) + executor.doStep(); + } + } catch (Exception e) { + e.printStackTrace(); // wtf? + try { + Thread.sleep(1000); + } catch (InterruptedException ex) { + } + } + } + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionMove.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionMove.java index b56cc05d..426c75ae 100755 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionMove.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionMove.java @@ -21,6 +21,7 @@ package kr.syeyoung.dungeonsguide.mod.dungeon.actions; import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; import kr.syeyoung.dungeonsguide.mod.dungeon.actions.tree.ActionRouteProperties; +import kr.syeyoung.dungeonsguide.mod.dungeon.pathfinding.algorithms.PathfinderExecutor; import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; @@ -34,8 +35,6 @@ import net.minecraft.util.Vec3; import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; @Data @EqualsAndHashCode(callSuper=false) @@ -90,31 +89,27 @@ public class ActionMove extends AbstractAction { private int tick = -1; private List<Vec3> poses; - private Future<List<Vec3>> latestFuture; + private PathfinderExecutor executor; @Override public void onTick(DungeonRoom dungeonRoom, ActionRouteProperties actionRouteProperties) { tick = (tick+1) % Math.max(1, actionRouteProperties.getLineRefreshRate()); - if (latestFuture != null && latestFuture.isDone()) { - try { - poses = latestFuture.get(); - latestFuture = null; - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } + if (executor == null) { + executor = dungeonRoom.createEntityPathTo(target.getBlockPos(dungeonRoom)); + } + if (executor != null) { + poses = executor.getRoute(Minecraft.getMinecraft().thePlayer.getPositionVector()); } - if (tick == 0 && actionRouteProperties.isPathfind() && latestFuture == null) { + if (tick == 0 && actionRouteProperties.isPathfind() && executor != null) { if (!FeatureRegistry.SECRET_FREEZE_LINES.isEnabled() || poses == null || actionRouteProperties.getLineRefreshRate() != -1) { - latestFuture = dungeonRoom.createEntityPathTo(dungeonRoom.getContext().getWorld(), Minecraft.getMinecraft().thePlayer, target.getBlockPos(dungeonRoom), Integer.MAX_VALUE, 10000); + executor.setTarget(Minecraft.getMinecraft().thePlayer.getPositionVector()); } } } public void forceRefresh(DungeonRoom dungeonRoom) { - if (latestFuture == null) { - latestFuture = dungeonRoom.createEntityPathTo(dungeonRoom.getContext().getWorld(), Minecraft.getMinecraft().thePlayer, target.getBlockPos(dungeonRoom), Integer.MAX_VALUE, 10000); - } + if (executor != null) executor.setTarget(Minecraft.getMinecraft().thePlayer.getPositionVector()); } @Override public String toString() { diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionMoveNearestAir.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionMoveNearestAir.java index 08487d81..c12d1ffd 100755 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionMoveNearestAir.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionMoveNearestAir.java @@ -21,6 +21,7 @@ package kr.syeyoung.dungeonsguide.mod.dungeon.actions; import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; import kr.syeyoung.dungeonsguide.mod.dungeon.actions.tree.ActionRouteProperties; +import kr.syeyoung.dungeonsguide.mod.dungeon.pathfinding.algorithms.PathfinderExecutor; import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; import lombok.Data; @@ -31,8 +32,6 @@ import net.minecraft.util.Vec3; import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; @Data @EqualsAndHashCode(callSuper=false) @@ -60,31 +59,26 @@ public class ActionMoveNearestAir extends AbstractAction { private int tick = -1; private List<Vec3> poses; - private Future<List<Vec3>> latestFuture; + private PathfinderExecutor executor; @Override public void onTick(DungeonRoom dungeonRoom, ActionRouteProperties actionRouteProperties) { tick = (tick+1) % Math.max(1, actionRouteProperties.getLineRefreshRate()); - if (latestFuture != null && latestFuture.isDone()) { - try { - poses = latestFuture.get(); - latestFuture = null; - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } + if (executor == null) { + executor = dungeonRoom.createEntityPathTo(target.getBlockPos(dungeonRoom)); + } + if (executor != null) { + poses = executor.getRoute(Minecraft.getMinecraft().thePlayer.getPositionVector()); } - if (tick == 0 && actionRouteProperties.isPathfind() && latestFuture == null) { + if (tick == 0 && actionRouteProperties.isPathfind() && executor != null) { if (!FeatureRegistry.SECRET_FREEZE_LINES.isEnabled() || poses == null || actionRouteProperties.getLineRefreshRate() != -1) { - latestFuture = dungeonRoom.createEntityPathTo(dungeonRoom.getContext().getWorld(), Minecraft.getMinecraft().thePlayer, target.getBlockPos(dungeonRoom), Integer.MAX_VALUE, 10000); + executor.setTarget(Minecraft.getMinecraft().thePlayer.getPositionVector()); } } } - public void forceRefresh(DungeonRoom dungeonRoom) { - if (latestFuture == null) { - latestFuture = dungeonRoom.createEntityPathTo(dungeonRoom.getContext().getWorld(), Minecraft.getMinecraft().thePlayer, target.getBlockPos(dungeonRoom), Integer.MAX_VALUE, 10000); - } + if (executor != null) executor.setTarget(Minecraft.getMinecraft().thePlayer.getPositionVector()); } @Override public String toString() { diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/pathfinding/AStarCornerCut.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/pathfinding/AStarCornerCut.java deleted file mode 100644 index a21bffd5..00000000 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/pathfinding/AStarCornerCut.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod - * Copyright (C) 2021 cyoung06 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. - */ - -package kr.syeyoung.dungeonsguide.mod.dungeon.pathfinding; - -import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import net.minecraft.util.AxisAlignedBB; -import net.minecraft.util.BlockPos; -import net.minecraft.util.MathHelper; -import net.minecraft.util.Vec3; -import net.minecraft.world.World; - -import java.util.*; - -public class AStarCornerCut { - private final BlockPos min, max; - private final World world; - - int lastSx, lastSy, lastSz; - final int dx, dy, dz; - private DungeonRoom dungeonRoom; - - @Getter - private AxisAlignedBB destinationBB; - - public AStarCornerCut(DungeonRoom dungeonRoom, Vec3 destination) { - this.min = new BlockPos(dungeonRoom.getMinx(), 0, dungeonRoom.getMinz()); - this.max = new BlockPos(dungeonRoom.getMaxx(), 255, dungeonRoom.getMaxz()); - - this.world = dungeonRoom.getCachedWorld(); - this.dungeonRoom = dungeonRoom; - - this.dx = (int) (destination.xCoord * 2); - this.dy = (int) (destination.yCoord * 2); - this.dz = (int) (destination.zCoord * 2); - destinationBB = AxisAlignedBB.fromBounds(dx-2, dy-2, dz-2, dx+2, dy+2, dz+2); - } - - private Map<Node.Coordinate, Node> nodeMap = new HashMap<>(); - - private Node openNode(int x, int y, int z) - { - Node.Coordinate coordinate = new Node.Coordinate(x,y,z); - Node node = this.nodeMap.get(coordinate); - - if (node == null) - { - node = new Node(coordinate); - this.nodeMap.put(coordinate, node); - } - - return node; - } - - @Getter - private LinkedList<Vec3> route = new LinkedList<>(); - - @Getter - private PriorityQueue<Node> open = new PriorityQueue<>(Comparator.comparing((Node a) -> a == null ? Float.MAX_VALUE : a.f).thenComparing(a -> a == null ? Float.MAX_VALUE : a.coordinate.x).thenComparing(a -> a == null ? Float.MAX_VALUE : a.coordinate.y).thenComparing(a -> a == null ? Float.MAX_VALUE : a.coordinate.z)); - - private int pfindIdx = 0; - - public boolean pathfind(Vec3 from, long timeout) { - pfindIdx ++; - if (lastSx != (int)Math.round(from.xCoord * 2) || lastSy != (int)Math.round(from.yCoord*2) || lastSz != (int)Math.round(from.zCoord * 2)) - open.clear(); - - this.lastSx = (int) Math.round(from.xCoord * 2); - this.lastSy = (int) Math.round(from.yCoord * 2); - this.lastSz = (int) Math.round(from.zCoord * 2); - - Node startNode = openNode(dx, dy, dz); - Node goalNode = openNode(lastSx, lastSy, lastSz); - - if (goalNode.parent != null) { - LinkedList<Vec3> route = new LinkedList<>(); - Node curr =goalNode; - while(curr.parent != null) { - route.addLast(new Vec3(curr.coordinate.x / 2.0, curr.coordinate.y / 2.0 + 0.1, curr.coordinate.z/ 2.0)); - curr = curr.parent; - } - route.addLast(new Vec3(curr.coordinate.x / 2.0, curr.coordinate.y / 2.0 + 0.1, curr.coordinate.z/ 2.0)); - this.route = route; - return true; - } - - startNode.g = 0; - startNode.f = 0; - goalNode.g = Integer.MAX_VALUE; goalNode.f = Integer.MAX_VALUE; - - - open.add(startNode); - - long end = System.currentTimeMillis() + timeout; - - while (!open.isEmpty()) { - if (System.currentTimeMillis() > end) { - return false; - } - - Node n = open.poll(); - if (n.lastVisited == pfindIdx) continue; - n.lastVisited = pfindIdx; - - if (n == goalNode) { - // route = reconstructPath(startNode) - LinkedList<Vec3> route = new LinkedList<>(); - Node curr =goalNode; - while(curr.parent != null) { - route.addLast(new Vec3(curr.coordinate.x / 2.0, curr.coordinate.y / 2.0 + 0.1, curr.coordinate.z/ 2.0)); - curr = curr.parent; - } - route.addLast(new Vec3(curr.coordinate.x / 2.0, curr.coordinate.y / 2.0 + 0.1, curr.coordinate.z/ 2.0)); - this.route = route; - return true; - } - - for (int z = -1; z <= 1; z++) {for (int y = -1; y <= 1; y ++) { for(int x = -1; x <= 1; x++) { - if (x == 0 && y == 0 && z == 0) continue; - Node neighbor = openNode(n.coordinate.x +x, n.coordinate.y +y, n.coordinate.z + z); - - // check blocked. - if (!((destinationBB.minX <= neighbor.coordinate.x && neighbor.coordinate.x <= destinationBB.maxX && - destinationBB.minY <= neighbor.coordinate.y && neighbor.coordinate.y <= destinationBB.maxY && - destinationBB.minZ <= neighbor.coordinate.z && neighbor.coordinate.z <= destinationBB.maxZ) // near destination - || !dungeonRoom.isBlocked(neighbor.coordinate.x, neighbor.coordinate.y, neighbor.coordinate.z))) { // not blocked - continue; - } - if (neighbor.lastVisited == pfindIdx) continue; - - - float gScore = n.g + MathHelper.sqrt_float(x*x + y*y + z*z); // altho it's sq, it should be fine - if (gScore < neighbor.g ) { - neighbor.parent = n; - neighbor.g = gScore; - neighbor.f = gScore + distSq(goalNode.coordinate.x - neighbor.coordinate.x, goalNode.coordinate.y - neighbor.coordinate.y, goalNode.coordinate.z - neighbor.coordinate.z); - open.add(neighbor); - } else if (neighbor.lastVisited != pfindIdx) { - neighbor.f = gScore + distSq(goalNode.coordinate.x - neighbor.coordinate.x, goalNode.coordinate.y - neighbor.coordinate.y, goalNode.coordinate.z - neighbor.coordinate.z); - open.add(neighbor); - } - }}} - } - return true; - } - - private int manhatten(int x, int y, int z) {return Math.abs(x)+ Math.abs(y)+ Math.abs(z);} - private float distSq(float x, float y, float z) { - return MathHelper.sqrt_float(x * x + y * y + z * z); - } - - @RequiredArgsConstructor - @Data - public static final class Node { - @Data - @RequiredArgsConstructor - public static final class Coordinate { - private final int x, y, z; - } - private final Coordinate coordinate; - - private float f = Float.MAX_VALUE, g = Float.MAX_VALUE; - private int lastVisited; - - @EqualsAndHashCode.Exclude - private Node parent; - - public static long makeHash(int x, int y, int z) - { - return y & 32767L | ((short)x & 32767L) << 16 | ((short)z & 32767L) << 32; - } - } -} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/pathfinding/AStarFineGrid.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/pathfinding/AStarFineGrid.java deleted file mode 100644 index 8cb49a10..00000000 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/pathfinding/AStarFineGrid.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod - * Copyright (C) 2021 cyoung06 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. - */ - -package kr.syeyoung.dungeonsguide.mod.dungeon.pathfinding; - -import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import net.minecraft.util.*; -import net.minecraft.world.World; - -import java.util.*; - -public class AStarFineGrid { - private final BlockPos min, max; - private final World world; - - int lastSx, lastSy, lastSz; - final int dx, dy, dz; - private DungeonRoom dungeonRoom; - - @Getter - private AxisAlignedBB destinationBB; - - public AStarFineGrid(DungeonRoom dungeonRoom, Vec3 destination) { - this.min = new BlockPos(dungeonRoom.getMinx(), 0, dungeonRoom.getMinz()); - this.max = new BlockPos(dungeonRoom.getMaxx(), 255, dungeonRoom.getMaxz()); - - this.world = dungeonRoom.getCachedWorld(); - this.dungeonRoom = dungeonRoom; - - this.dx = (int) (destination.xCoord * 2); - this.dy = (int) (destination.yCoord * 2); - this.dz = (int) (destination.zCoord * 2); - destinationBB = AxisAlignedBB.fromBounds(dx-2, dy-2, dz-2, dx+2, dy+2, dz+2); - } - - private Map<Node.Coordinate, Node> nodeMap = new HashMap<>(); - - private Node openNode(int x, int y, int z) - { - Node.Coordinate coordinate = new Node.Coordinate(x,y,z); - Node node = this.nodeMap.get(coordinate); - - if (node == null) - { - node = new Node(coordinate); - this.nodeMap.put(coordinate, node); - } - - return node; - } - - @Getter - private LinkedList<Vec3> route = new LinkedList<>(); - - @Getter - private PriorityQueue<Node> open = new PriorityQueue<>(Comparator.comparing((Node a) -> a == null ? Float.MAX_VALUE : a.f).thenComparing(a -> a == null ? Float.MAX_VALUE : a.coordinate.x).thenComparing(a -> a == null ? Float.MAX_VALUE : a.coordinate.y).thenComparing(a -> a == null ? Float.MAX_VALUE : a.coordinate.z)); - - private int pfindIdx = 0; - - public boolean pathfind(Vec3 from, long timeout) { - pfindIdx ++; - if (lastSx != (int)Math.round(from.xCoord * 2) || lastSy != (int)Math.round(from.yCoord*2) || lastSz != (int)Math.round(from.zCoord * 2)) - open.clear(); - - this.lastSx = (int) Math.round(from.xCoord * 2); - this.lastSy = (int) Math.round(from.yCoord * 2); - this.lastSz = (int) Math.round(from.zCoord * 2); - - Node startNode = openNode(dx, dy, dz); - Node goalNode = openNode(lastSx, lastSy, lastSz); - startNode.g = 0; - startNode.f = 0; - goalNode.g = Integer.MAX_VALUE; goalNode.f = Integer.MAX_VALUE; - if (goalNode.parent != null) { - LinkedList<Vec3> route = new LinkedList<>(); - Node curr =goalNode; - while(curr.parent != null) { - route.addLast(new Vec3(curr.coordinate.x / 2.0, curr.coordinate.y / 2.0 + 0.1, curr.coordinate.z/ 2.0)); - curr = curr.parent; - } - route.addLast(new Vec3(curr.coordinate.x / 2.0, curr.coordinate.y / 2.0 + 0.1, curr.coordinate.z/ 2.0)); - this.route = route; - return true; - } - open.add(startNode); - - long end = System.currentTimeMillis() + timeout; - - while (!open.isEmpty()) { - if (System.currentTimeMillis() > end) { - return false; - } - - Node n = open.poll(); - if (n.lastVisited == pfindIdx) continue; - n.lastVisited = pfindIdx; - - if (n == goalNode) { - // route = reconstructPath(startNode) - LinkedList<Vec3> route = new LinkedList<>(); - Node curr =goalNode; - while(curr.parent != null) { - route.addLast(new Vec3(curr.coordinate.x / 2.0, curr.coordinate.y / 2.0 + 0.1, curr.coordinate.z/ 2.0)); - curr = curr.parent; - } - route.addLast(new Vec3(curr.coordinate.x / 2.0, curr.coordinate.y / 2.0 + 0.1, curr.coordinate.z/ 2.0)); - this.route = route; - return true; - } - - for (EnumFacing value : EnumFacing.VALUES) { - Node neighbor = openNode(n.coordinate.x + value.getFrontOffsetX(), n.coordinate.y + value.getFrontOffsetY(), n.coordinate.z + value.getFrontOffsetZ()); - - // check blocked. - if (!((destinationBB.minX <= neighbor.coordinate.x && neighbor.coordinate.x <= destinationBB.maxX && - destinationBB.minY <= neighbor.coordinate.y && neighbor.coordinate.y <= destinationBB.maxY && - destinationBB.minZ <= neighbor.coordinate.z && neighbor.coordinate.z <= destinationBB.maxZ) // near destination - || !dungeonRoom.isBlocked(neighbor.coordinate.x, neighbor.coordinate.y, neighbor.coordinate.z))) { // not blocked - continue; - } - - float gScore = n.g + 1; // altho it's sq, it should be fine - if (gScore < neighbor.g) { - neighbor.parent = n; - neighbor.g = gScore; - neighbor.f = gScore + distSq(goalNode.coordinate.x - neighbor.coordinate.x, goalNode.coordinate.y - neighbor.coordinate.y, goalNode.coordinate.z - neighbor.coordinate.z); - open.add(neighbor); - } else if (neighbor.lastVisited != pfindIdx) { - neighbor.f = gScore + distSq(goalNode.coordinate.x - neighbor.coordinate.x, goalNode.coordinate.y - neighbor.coordinate.y, goalNode.coordinate.z - neighbor.coordinate.z); - open.add(neighbor); - } - } - } - return true; - } - - private int manhatten(int x, int y, int z) {return Math.abs(x)+ Math.abs(y)+ Math.abs(z);} - private float distSq(float x, float y, float z) { - return MathHelper.sqrt_float(x * x + y * y + z * z); - } - - @RequiredArgsConstructor - @Data - public static final class Node { - @Data - @RequiredArgsConstructor - public static final class Coordinate { - private final int x, y, z; - } - private final Coordinate coordinate; - - private float f = Float.MAX_VALUE, g = Float.MAX_VALUE; - private int lastVisited; - - @EqualsAndHashCode.Exclude - private Node parent; - - public static long makeHash(int x, int y, int z) - { - return y & 32767L | ((short)x & 32767L) << 16 | ((short)z & 32767L) << 32; - } - } -} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/pathfinding/JPSPathfinder.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/pathfinding/JPSPathfinder.java deleted file mode 100644 index 0a4e1b7d..00000000 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/pathfinding/JPSPathfinder.java +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod - * Copyright (C) 2021 cyoung06 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. - */ - -package kr.syeyoung.dungeonsguide.mod.dungeon.pathfinding; - -import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import net.minecraft.util.*; -import net.minecraft.world.World; - -import java.util.*; - -public class JPSPathfinder { - private final BlockPos min, max; - private final World world; - - private Vec3 start; - private Vec3 destination; - private DungeonRoom dungeonRoom; - - @Getter - private AxisAlignedBB destinationBB; - - public JPSPathfinder(DungeonRoom dungeonRoom){ - this.min = new BlockPos(dungeonRoom.getMinx(), 0, dungeonRoom.getMinz()); - this.max = new BlockPos(dungeonRoom.getMaxx(), 255, dungeonRoom.getMaxz()); - - this.world = dungeonRoom.getCachedWorld(); - this.dungeonRoom = dungeonRoom; - } - - private IntHashMap<Node> nodeMap = new IntHashMap(); - - private Node openNode(int x, int y, int z) - { - int i = Node.makeHash(x, y, z); - Node node = this.nodeMap.lookup(i); - - if (node == null) - { - node = new Node(x, y, z); - this.nodeMap.addKey(i, node); - } - - return node; - } - - @Getter - private LinkedList<Vec3> route = new LinkedList<>(); - - @Getter - private PriorityQueue<Node> open = new PriorityQueue<>(Comparator.comparing((Node a) -> a == null ? Float.MAX_VALUE : a.f).thenComparing(a -> a == null ? Float.MAX_VALUE : a.x).thenComparing(a -> a == null ? Float.MAX_VALUE : a.y).thenComparing(a -> a == null ? Float.MAX_VALUE : a.z)); - - private int tx, ty, tz; - - private Node addNode(Node parent, Node jumpPt, boolean addToOpen) { - float ng = parent.g + distSq(jumpPt.x - parent.x, jumpPt.y - parent.y, jumpPt.z - parent.z); - - if (ng < jumpPt.g) { - if (addToOpen) - open.remove(jumpPt); - jumpPt.g = ng; - jumpPt.h = jumpPt.h == -1 ? distSq(tx - jumpPt.x, ty - jumpPt.y, tz - jumpPt.z) : jumpPt.h; - jumpPt.f = jumpPt.h + jumpPt.g; - jumpPt.parent = parent; - if (addToOpen) - open.add(jumpPt); - } - return jumpPt; - } - - - long arr[]; - - public boolean pathfind(Vec3 from, Vec3 to, float within, long timeout) { - route.clear(); nodeMap.clearMap(); - - { - from = new Vec3(((int)(from.xCoord * 2)) / 2.0, ((int)(from.yCoord * 2) |
