Skip to content

Commit 6472662

Browse files
authored
Merge pull request #47 from awrped/master
cleanup pf code
2 parents 388a491 + 4f7facf commit 6472662

30 files changed

Lines changed: 274 additions & 727 deletions

src/main/kotlin/org/cobalt/api/pathfinder/Node.kt

Lines changed: 11 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,29 @@
11
package org.cobalt.api.pathfinder
22

3-
43
import org.cobalt.api.pathfinder.pathing.heuristic.HeuristicContext
54
import org.cobalt.api.pathfinder.pathing.heuristic.HeuristicWeights
65
import org.cobalt.api.pathfinder.pathing.heuristic.IHeuristicStrategy
76
import org.cobalt.api.pathfinder.wrapper.PathPosition
87

98
class Node(
10-
private val position: PathPosition,
9+
val position: PathPosition,
1110
start: PathPosition,
1211
target: PathPosition,
1312
heuristicWeights: HeuristicWeights,
1413
heuristicStrategy: IHeuristicStrategy,
15-
private val depth: Int,
14+
val depth: Int,
1615
) : Comparable<Node> {
1716

18-
private val hCost: Double = heuristicStrategy.calculate(
19-
HeuristicContext(position, start, target, heuristicWeights)
20-
)
21-
22-
private var gCost: Double = 0.0
23-
private var parent: Node? = null
24-
25-
fun getPosition(): PathPosition = position
17+
val heuristic: Double =
18+
heuristicStrategy.calculate(HeuristicContext(position, start, target, heuristicWeights))
2619

27-
fun getHeuristic(): Double = hCost
20+
var gCost: Double = 0.0
21+
var parent: Node? = null
2822

29-
fun getParent(): Node? = parent
30-
31-
fun getDepth(): Int = depth
32-
33-
fun setGCost(gCost: Double) {
34-
this.gCost = gCost
35-
}
23+
val fCost: Double
24+
get() = gCost + heuristic
3625

37-
fun setParent(parent: Node?) {
38-
this.parent = parent
39-
}
40-
41-
fun isTarget(target: PathPosition): Boolean = this.position == target
42-
43-
fun getFCost(): Double = getGCost() + getHeuristic()
44-
45-
fun getGCost(): Double {
46-
return if (this.parent == null) 0.0 else this.gCost
47-
}
26+
fun isTarget(target: PathPosition): Boolean = position == target
4827

4928
override fun equals(other: Any?): Boolean {
5029
if (other == null || this::class != other::class) return false
@@ -55,12 +34,12 @@ class Node(
5534
override fun hashCode(): Int = position.hashCode()
5635

5736
override fun compareTo(other: Node): Int {
58-
val fCostComparison = this.getFCost().compareTo(other.getFCost())
37+
val fCostComparison = fCost.compareTo(other.fCost)
5938
if (fCostComparison != 0) {
6039
return fCostComparison
6140
}
6241

63-
val heuristicComparison = this.getHeuristic().compareTo(other.getHeuristic())
42+
val heuristicComparison = heuristic.compareTo(other.heuristic)
6443
if (heuristicComparison != 0) {
6544
return heuristicComparison
6645
}

src/main/kotlin/org/cobalt/api/pathfinder/PathExecutor.kt

Lines changed: 53 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@ import org.cobalt.api.event.EventBus
88
import org.cobalt.api.event.annotation.SubscribeEvent
99
import org.cobalt.api.event.impl.client.TickEvent
1010
import org.cobalt.api.event.impl.render.WorldRenderEvent
11-
import org.cobalt.api.pathfinder.factory.impl.AStarPathfinderFactory
11+
import org.cobalt.api.pathfinder.pathfinder.AStarPathfinder
1212
import org.cobalt.api.pathfinder.pathing.NeighborStrategies
1313
import org.cobalt.api.pathfinder.pathing.configuration.PathfinderConfiguration
1414
import org.cobalt.api.pathfinder.pathing.processing.impl.MinecraftPathProcessor
1515
import org.cobalt.api.pathfinder.pathing.result.Path
1616
import org.cobalt.api.pathfinder.pathing.result.PathState
1717
import org.cobalt.api.pathfinder.provider.impl.MinecraftNavigationProvider
18+
import org.cobalt.api.pathfinder.result.PathImpl
1819
import org.cobalt.api.pathfinder.wrapper.PathPosition
1920
import org.cobalt.api.util.ChatUtils
2021
import org.cobalt.api.util.render.Render3D
@@ -38,53 +39,66 @@ object PathExecutor {
3839
val start = PathPosition(player.x, player.y, player.z)
3940
val target = PathPosition(x, y, z)
4041

41-
val factory = AStarPathfinderFactory()
42-
4342
val processor = MinecraftPathProcessor()
4443
val config =
45-
PathfinderConfiguration.builder()
46-
.provider(MinecraftNavigationProvider())
47-
.maxIterations(20000)
48-
.async(true)
49-
.neighborStrategy(NeighborStrategies.HORIZONTAL_DIAGONAL_AND_VERTICAL)
50-
.nodeValidationProcessors(listOf(processor))
51-
.nodeCostProcessors(listOf(processor))
52-
.build()
44+
PathfinderConfiguration(
45+
provider = MinecraftNavigationProvider(),
46+
// as of now max iterations is 20,000 but maybe wanna higher
47+
maxIterations = 20000,
48+
async = true,
49+
neighborStrategy = NeighborStrategies.HORIZONTAL_DIAGONAL_AND_VERTICAL,
50+
processors = listOf(processor)
51+
)
5352

54-
val pathfinder = factory.createPathfinder(config)
53+
val pathfinder = AStarPathfinder(config)
5554

5655
ChatUtils.sendDebug("Calculating path to $x, $y, $z...")
5756
val startTime = System.currentTimeMillis()
5857
pathfinder.findPath(start, target).thenAccept { result ->
59-
val duration = System.currentTimeMillis() - startTime
60-
if (result.successful()) {
61-
currentPath = result.getPath()
62-
currentWaypointIndex = 0
63-
58+
mc.execute {
59+
val duration = System.currentTimeMillis() - startTime
6460
val state = result.getPathState()
65-
val path = result.getPath()
66-
67-
if (state == PathState.FOUND) {
68-
ChatUtils.sendMessage(
69-
"§aPath found! §7Calculated in §f${duration}ms §8(${path.length()} nodes)"
70-
)
71-
} else {
72-
/*
73-
* partial paths can happen, i would recommend improving this functionality
74-
* to whoever maintainer wants to maintain my horrible shitcode of a pathfinder.
75-
* i think partial paths should be refactored, i will write all the cases now
76-
* iteration limit -> self explanatory xd (or if u cant use ur brain
77-
* then its just if the algorithm takes too many iterations to find a goal.
78-
* this is set literaaally like 20 lines above you...)
79-
* fallback -> pf searches everywhere and couldnt find a possible way to get there.
80-
* this can happen in the case of unloaded chunks, or an obstruction
81-
*/
82-
ChatUtils.sendMessage(
83-
"§ePartial path found! §7Calculated in §f${duration}ms §8(${path.length()} nodes)"
84-
)
61+
if (state != PathState.FOUND) {
62+
ChatUtils.sendMessage("§cFailed to find path: $state")
63+
return@execute
8564
}
86-
} else {
87-
ChatUtils.sendMessage("§cFailed to find path: ${result.getPathState()}")
65+
66+
val rawPath = result.getPath()
67+
val positions = rawPath.collect().toList()
68+
val path =
69+
if (positions.size <= 2) {
70+
rawPath
71+
} else {
72+
val simplified = ArrayList<PathPosition>(positions.size)
73+
simplified.add(positions.first())
74+
75+
for (i in 1 until positions.size - 1) {
76+
val prev = simplified.last()
77+
val curr = positions[i]
78+
val next = positions[i + 1]
79+
80+
val prevDx = (curr.flooredX - prev.flooredX).coerceIn(-1, 1)
81+
val prevDy = (curr.flooredY - prev.flooredY).coerceIn(-1, 1)
82+
val prevDz = (curr.flooredZ - prev.flooredZ).coerceIn(-1, 1)
83+
val nextDx = (next.flooredX - curr.flooredX).coerceIn(-1, 1)
84+
val nextDy = (next.flooredY - curr.flooredY).coerceIn(-1, 1)
85+
val nextDz = (next.flooredZ - curr.flooredZ).coerceIn(-1, 1)
86+
87+
if (prevDx == nextDx && prevDy == nextDy && prevDz == nextDz) {
88+
continue
89+
}
90+
simplified.add(curr)
91+
}
92+
93+
simplified.add(positions.last())
94+
PathImpl(rawPath.getStart(), rawPath.getEnd(), simplified)
95+
}
96+
currentPath = path
97+
currentWaypointIndex = 0
98+
99+
ChatUtils.sendMessage(
100+
"§aPath found! §7Calculated in §f${duration}ms §8(${path.length()} nodes)"
101+
)
88102
}
89103
}
90104
}

src/main/kotlin/org/cobalt/api/pathfinder/factory/PathfinderFactory.kt

Lines changed: 0 additions & 22 deletions
This file was deleted.

src/main/kotlin/org/cobalt/api/pathfinder/factory/PathfinderInitializer.kt

Lines changed: 0 additions & 8 deletions
This file was deleted.

src/main/kotlin/org/cobalt/api/pathfinder/factory/impl/AStarPathfinderFactory.kt

Lines changed: 0 additions & 13 deletions
This file was deleted.

0 commit comments

Comments
 (0)