Skip to content

Commit 77f858c

Browse files
committed
Kinda working pathing
1 parent 9602e3f commit 77f858c

File tree

9 files changed

+132
-37
lines changed

9 files changed

+132
-37
lines changed

common/src/main/kotlin/com/lambda/module/modules/movement/Pathfinder.kt

Lines changed: 78 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,36 +17,107 @@
1717

1818
package com.lambda.module.modules.movement
1919

20+
import com.lambda.context.SafeContext
2021
import com.lambda.event.events.RenderEvent
22+
import com.lambda.event.events.RotationEvent
2123
import com.lambda.event.listener.SafeListener.Companion.listen
2224
import com.lambda.graphics.renderer.esp.builders.buildLine
25+
import com.lambda.interaction.request.rotation.Rotation.Companion.rotationTo
2326
import com.lambda.module.Module
24-
import com.lambda.module.modules.client.TaskFlowModule.drawables
2527
import com.lambda.module.tag.ModuleTag
26-
import com.lambda.pathing.AStar
27-
import com.lambda.pathing.AStar.findPathAStar
28+
import com.lambda.pathing.Path
29+
import com.lambda.pathing.Pathing.findPathAStar
2830
import com.lambda.pathing.goal.SimpleGoal
2931
import com.lambda.util.math.setAlpha
32+
import com.lambda.util.player.MovementUtils.buildMovementInput
33+
import com.lambda.util.player.MovementUtils.mergeFrom
3034
import com.lambda.util.world.fastVectorOf
3135
import com.lambda.util.world.toBlockPos
3236
import com.lambda.util.world.toFastVec
33-
import com.lambda.util.world.toVec3d
37+
import net.minecraft.util.math.Vec3d
3438
import java.awt.Color
39+
import kotlin.math.cos
40+
import kotlin.math.sin
3541

3642
object Pathfinder : Module(
3743
name = "Pathfinder",
3844
description = "Get from A to B",
3945
defaultTags = setOf(ModuleTag.MOVEMENT)
4046
) {
47+
// PID Settings
48+
private val kP by setting("P Gain", 0.5, 0.0..2.0, 0.01)
49+
private val kI by setting("I Gain", 0.0, 0.0..1.0, 0.01)
50+
private val kD by setting("D Gain", 0.2, 0.0..1.0, 0.01)
51+
private val tolerance by setting("Node Tolerance", 0.1, 0.01..1.0, 0.01)
52+
53+
var path = Path()
54+
private var currentTarget: Vec3d? = null
55+
private var integralError = Vec3d.ZERO
56+
private var lastError = Vec3d.ZERO
57+
4158
init {
42-
listen<RenderEvent.StaticESP> {
43-
val path = findPathAStar(player.blockPos.toFastVec(), SimpleGoal(fastVectorOf(0, 120, 0)))
59+
onEnable {
60+
path = findPathAStar(
61+
player.blockPos.toFastVec(),
62+
SimpleGoal(fastVectorOf(0, 120, 0))
63+
)
64+
// currentTarget = Vec3d(0.5, 120.0, 0.5)
65+
integralError = Vec3d.ZERO
66+
lastError = Vec3d.ZERO
67+
}
68+
69+
listen<RotationEvent.StrafeInput> { event ->
70+
if (path.nodes.isEmpty()) return@listen
71+
72+
updateTargetNode()
73+
currentTarget?.let { target ->
74+
event.strafeYaw = player.eyePos.rotationTo(target).yaw
75+
val adjustment = calculatePID(target)
76+
val yawRad = Math.toRadians(event.strafeYaw)
77+
val forward = -sin(yawRad)
78+
val strafe = cos(yawRad)
79+
80+
val forwardComponent = adjustment.x * forward + adjustment.z * strafe
81+
val strafeComponent = adjustment.x * strafe - adjustment.z * forward
82+
83+
val moveInput = buildMovementInput(
84+
forward = forwardComponent,
85+
strafe = strafeComponent,
86+
jump = player.isOnGround && adjustment.y > 0.5
87+
)
88+
event.input.mergeFrom(moveInput)
89+
}
90+
}
4491

92+
listen<RenderEvent.StaticESP> { event ->
4593
path.nodes.zipWithNext { current, next ->
4694
val currentPos = current.pos.toBlockPos().toCenterPos()
4795
val nextPos = next.pos.toBlockPos().toCenterPos()
48-
it.renderer.buildLine(currentPos, nextPos, Color.BLUE.setAlpha(0.25))
96+
event.renderer.buildLine(currentPos, nextPos, Color.BLUE.setAlpha(0.25))
97+
}
98+
}
99+
}
100+
101+
private fun SafeContext.updateTargetNode() {
102+
path.nodes.firstOrNull()?.let { firstNode ->
103+
val nodeVec = Vec3d.ofBottomCenter(firstNode.pos.toBlockPos())
104+
if (player.pos.distanceTo(nodeVec) < tolerance) {
105+
path.nodes.removeFirst()
106+
integralError = Vec3d.ZERO
49107
}
108+
val next = path.nodes.firstOrNull()?.pos?.toBlockPos() ?: return
109+
currentTarget = Vec3d.ofBottomCenter(next)
50110
}
51111
}
112+
113+
private fun SafeContext.calculatePID(target: Vec3d): Vec3d {
114+
val error = target.subtract(player.pos)
115+
integralError = integralError.add(error)
116+
val derivativeError = error.subtract(lastError)
117+
lastError = error
118+
119+
return error.multiply(kP)
120+
.add(integralError.multiply(kI))
121+
.add(derivativeError.multiply(kD))
122+
}
52123
}

common/src/main/kotlin/com/lambda/module/modules/player/Freecam.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,5 +143,9 @@ object Freecam : Module(
143143
listen<ConnectionEvent.Disconnect> {
144144
disable()
145145
}
146+
147+
listen<ClientEvent.Shutdown> {
148+
disable()
149+
}
146150
}
147151
}

common/src/main/kotlin/com/lambda/pathing/Node.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ data class Node(
4343
return path
4444
}
4545

46-
override fun toString() = "Node(pos=${pos.toBlockPos().toShortString()}, gCost=$gCost, hCost=$hCost)"
46+
override fun toString() = "Node(pos=(${pos.toBlockPos().toShortString()}), gCost=$gCost, hCost=$hCost)"
4747

4848
companion object {
4949
fun FastVector.toNode(goal: Goal) =

common/src/main/kotlin/com/lambda/pathing/AStar.kt renamed to common/src/main/kotlin/com/lambda/pathing/Pathing.kt

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,11 @@ package com.lambda.pathing
2020
import com.lambda.context.SafeContext
2121
import com.lambda.pathing.Node.Companion.toNode
2222
import com.lambda.pathing.goal.Goal
23-
import com.lambda.pathing.move.Move
23+
import com.lambda.pathing.move.MoveFinder.moveOptions
2424
import com.lambda.util.world.FastVector
25-
import com.lambda.util.world.WorldUtils.traversable
26-
import com.lambda.util.world.toBlockPos
2725
import java.util.PriorityQueue
2826

29-
object AStar {
27+
object Pathing {
3028
fun SafeContext.findPathAStar(start: FastVector, goal: Goal): Path {
3129
val openSet = PriorityQueue<Node>()
3230
val closedSet = mutableSetOf<Node>()
@@ -58,21 +56,4 @@ object AStar {
5856
println("No path found")
5957
return Path()
6058
}
61-
62-
private fun SafeContext.moveOptions(origin: FastVector): List<Move> {
63-
val originPos = origin.toBlockPos()
64-
return Move.entries.filter { move ->
65-
traversable(originPos.add(move.x, move.y, move.z))
66-
}
67-
}
68-
69-
// class Move(
70-
// private val origin: FastVector,
71-
// val offset: FastVector,
72-
// ) {
73-
// val cost: Double = origin.distManhattan(offset).toDouble()
74-
//
75-
// fun nextNode(goal: Goal) =
76-
// origin.plus(offset).toNode(goal)
77-
// }
7859
}

common/src/main/kotlin/com/lambda/pathing/goal/SimpleGoal.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,13 @@
1818
package com.lambda.pathing.goal
1919

2020
import com.lambda.util.world.FastVector
21+
import com.lambda.util.world.distManhattan
2122
import com.lambda.util.world.distSq
2223

2324
class SimpleGoal(
2425
val pos: FastVector,
2526
) : Goal {
2627
override fun inGoal(pos: FastVector) = pos == this.pos
2728

28-
override fun heuristic(pos: FastVector) = pos distSq this.pos
29+
override fun heuristic(pos: FastVector) = pos distManhattan this.pos
2930
}

common/src/main/kotlin/com/lambda/pathing/move/Move.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,13 @@ import kotlin.math.abs
2626

2727
enum class Move(val x: Int, val y: Int, val z: Int) {
2828
TRAVERSE_NORTH(0, 0, -1),
29-
TRAVERSE_NORTH_EAST(1, 0, -1),
29+
// TRAVERSE_NORTH_EAST(1, 0, -1),
3030
TRAVERSE_EAST(1, 0, 0),
31-
TRAVERSE_SOUTH_EAST(1, 0, 1),
31+
// TRAVERSE_SOUTH_EAST(1, 0, 1),
3232
TRAVERSE_SOUTH(0, 0, 1),
33-
TRAVERSE_SOUTH_WEST(-1, 0, 1),
33+
// TRAVERSE_SOUTH_WEST(-1, 0, 1),
3434
TRAVERSE_WEST(-1, 0, 0),
35-
TRAVERSE_NORTH_WEST(-1, 0, -1),
35+
// TRAVERSE_NORTH_WEST(-1, 0, -1),
3636
PILLAR(0, 1, 0),
3737
ASCEND_NORTH(0, 1, -1),
3838
ASCEND_EAST(1, 1, 0),
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright 2025 Lambda
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
package com.lambda.pathing.move
19+
20+
import com.lambda.context.SafeContext
21+
import com.lambda.util.world.FastVector
22+
import com.lambda.util.world.WorldUtils.traversable
23+
import com.lambda.util.world.toBlockPos
24+
25+
object MoveFinder {
26+
fun SafeContext.moveOptions(origin: FastVector): List<Move> {
27+
val originPos = origin.toBlockPos()
28+
return Move.entries.filter { move ->
29+
traversable(originPos.add(move.x, move.y, move.z))
30+
}
31+
}
32+
}

common/src/main/kotlin/com/lambda/util/world/Position.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import net.minecraft.util.math.Direction
2222
import net.minecraft.util.math.Vec3d
2323
import net.minecraft.util.math.Vec3i
2424
import kotlin.math.abs
25+
import kotlin.math.sqrt
2526

2627
/**
2728
* Represents a position in the world encoded as a long.
@@ -193,6 +194,8 @@ infix fun FastVector.mod(scalar: Int): FastVector = fastVectorOf(x % scalar, y %
193194
infix fun FastVector.mod(scalar: Double): FastVector =
194195
fastVectorOf((x % scalar).toLong(), (y % scalar).toLong(), (z % scalar).toLong())
195196

197+
infix fun FastVector.dist(other: FastVector): Double = sqrt(distSq(other))
198+
196199
/**
197200
* Returns the squared distance between this position and the other.
198201
*/
@@ -206,11 +209,11 @@ infix fun FastVector.distSq(other: FastVector): Double {
206209
/**
207210
* Returns the Manhattan distance between this position and the other.
208211
*/
209-
infix fun FastVector.distManhattan(other: FastVector): Int {
212+
infix fun FastVector.distManhattan(other: FastVector): Double {
210213
val dx = x - other.x
211214
val dy = y - other.y
212215
val dz = z - other.z
213-
return abs(dx) + abs(dy) + abs(dz)
216+
return (abs(dx) + abs(dy) + abs(dz)).toDouble()
214217
}
215218

216219
/**

common/src/main/kotlin/com/lambda/util/world/WorldUtils.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,11 @@ import net.minecraft.util.math.Direction
2525
import net.minecraft.util.math.Vec3d
2626

2727
object WorldUtils {
28+
fun SafeContext.traversable(from: BlockPos, to: BlockPos) =
29+
BlockPos.stream(from, to).allMatch { traversable(it) }
30+
2831
fun SafeContext.traversable(pos: BlockPos) =
29-
blockState(pos.down()).isSideSolidFullSquare(world, pos, Direction.UP) && playerFitsIn(pos)
32+
blockState(pos.down()).isSideSolidFullSquare(world, pos.down(), Direction.UP) && playerFitsIn(pos)
3033

3134
fun SafeContext.playerFitsIn(pos: BlockPos) =
3235
world.isSpaceEmpty(Vec3d.ofBottomCenter(pos).playerBox())

0 commit comments

Comments
 (0)