Skip to content

Commit 71bbfec

Browse files
committed
NodeTypes and different moves
1 parent 77f858c commit 71bbfec

File tree

17 files changed

+521
-159
lines changed

17 files changed

+521
-159
lines changed

common/src/main/kotlin/com/lambda/interaction/construction/simulation/Simulation.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import com.lambda.module.modules.client.TaskFlowModule
3030
import com.lambda.threading.runSafe
3131
import com.lambda.util.BlockUtils.blockState
3232
import com.lambda.util.world.FastVector
33+
import com.lambda.util.world.WorldUtils.playerBox
3334
import com.lambda.util.world.WorldUtils.playerFitsIn
3435
import com.lambda.util.world.WorldUtils.traversable
3536
import com.lambda.util.world.toBlockPos
@@ -73,8 +74,6 @@ data class Simulation(
7374
}
7475

7576
companion object {
76-
fun Vec3d.playerBox(): Box = Box(x - 0.3, y, z - 0.3, x + 0.3, y + 1.8, z + 0.3).contract(1.0E-6)
77-
7877
fun Blueprint.simulation(
7978
interact: InteractionConfig = TaskFlowModule.interact,
8079
rotation: RotationConfig = TaskFlowModule.rotation,

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

Lines changed: 68 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,25 @@
1717

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

20+
import com.lambda.config.groups.RotationSettings
2021
import com.lambda.context.SafeContext
2122
import com.lambda.event.events.RenderEvent
2223
import com.lambda.event.events.RotationEvent
24+
import com.lambda.event.events.TickEvent
2325
import com.lambda.event.listener.SafeListener.Companion.listen
2426
import com.lambda.graphics.renderer.esp.builders.buildLine
27+
import com.lambda.interaction.request.rotation.Rotation
2528
import com.lambda.interaction.request.rotation.Rotation.Companion.rotationTo
29+
import com.lambda.interaction.request.rotation.RotationManager.onRotate
30+
import com.lambda.interaction.request.rotation.visibilty.lookAt
2631
import com.lambda.module.Module
2732
import com.lambda.module.tag.ModuleTag
2833
import com.lambda.pathing.Path
2934
import com.lambda.pathing.Pathing.findPathAStar
35+
import com.lambda.pathing.PathingSettings
3036
import com.lambda.pathing.goal.SimpleGoal
37+
import com.lambda.threading.runConcurrent
38+
import com.lambda.util.Communication.info
3139
import com.lambda.util.math.setAlpha
3240
import com.lambda.util.player.MovementUtils.buildMovementInput
3341
import com.lambda.util.player.MovementUtils.mergeFrom
@@ -38,75 +46,96 @@ import net.minecraft.util.math.Vec3d
3846
import java.awt.Color
3947
import kotlin.math.cos
4048
import kotlin.math.sin
49+
import kotlin.system.measureTimeMillis
4150

4251
object Pathfinder : Module(
4352
name = "Pathfinder",
4453
description = "Get from A to B",
4554
defaultTags = setOf(ModuleTag.MOVEMENT)
4655
) {
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)
56+
private val pathing = PathingSettings(this)
57+
private val rotation = RotationSettings(this)
5258

53-
var path = Path()
59+
var path: Path? = null
5460
private var currentTarget: Vec3d? = null
5561
private var integralError = Vec3d.ZERO
5662
private var lastError = Vec3d.ZERO
63+
private var calculating = false
5764

5865
init {
5966
onEnable {
60-
path = findPathAStar(
61-
player.blockPos.toFastVec(),
62-
SimpleGoal(fastVectorOf(0, 120, 0))
63-
)
64-
// currentTarget = Vec3d(0.5, 120.0, 0.5)
6567
integralError = Vec3d.ZERO
6668
lastError = Vec3d.ZERO
6769
}
6870

69-
listen<RotationEvent.StrafeInput> { event ->
70-
if (path.nodes.isEmpty()) return@listen
71+
listen<TickEvent.Pre> {
72+
if (calculating) return@listen
73+
calculating = true
7174

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)
75+
runConcurrent {
76+
val took = measureTimeMillis {
77+
path = findPathAStar(
78+
player.blockPos.toFastVec(),
79+
// SimpleGoal(fastVectorOf(0, 78, 0)),
80+
SimpleGoal(fastVectorOf(0, 120, 0)),
81+
pathing.cutoffTimeout
82+
)
83+
}
84+
info("Found path of length ${path?.moves?.size} in $took ms")
85+
println("Path: ${path?.toString()}")
86+
calculating = false
8987
}
9088
}
9189

90+
// listen<RotationEvent.StrafeInput> { event ->
91+
// updateTargetNode()
92+
// currentTarget?.let { target ->
93+
// event.strafeYaw = player.eyePos.rotationTo(target).yaw
94+
// val adjustment = calculatePID(target)
95+
// val yawRad = Math.toRadians(event.strafeYaw)
96+
// val forward = -sin(yawRad)
97+
// val strafe = cos(yawRad)
98+
//
99+
// val forwardComponent = adjustment.x * forward + adjustment.z * strafe
100+
// val strafeComponent = adjustment.x * strafe - adjustment.z * forward
101+
//
102+
// val moveInput = buildMovementInput(
103+
// forward = forwardComponent,
104+
// strafe = strafeComponent,
105+
// jump = player.isOnGround && adjustment.y > 0.5
106+
// )
107+
// event.input.mergeFrom(moveInput)
108+
// }
109+
// }
110+
//
111+
// onRotate {
112+
// val nextTarget = path?.moves?.getOrNull(2)?.pos?.toBlockPos() ?: return@onRotate
113+
// val part = player.eyePos.rotationTo(Vec3d.ofBottomCenter(nextTarget))
114+
// val targetRotation = Rotation(part.yaw, player.pitch.toDouble())
115+
//
116+
// lookAt(targetRotation).requestBy(rotation)
117+
// }
118+
92119
listen<RenderEvent.StaticESP> { event ->
93-
path.nodes.zipWithNext { current, next ->
120+
path?.moves?.zipWithNext { current, next ->
94121
val currentPos = current.pos.toBlockPos().toCenterPos()
95122
val nextPos = next.pos.toBlockPos().toCenterPos()
96-
event.renderer.buildLine(currentPos, nextPos, Color.BLUE.setAlpha(0.25))
123+
event.renderer.buildLine(currentPos, nextPos, Color.GREEN)
97124
}
98125
}
99126
}
100127

101128
private fun SafeContext.updateTargetNode() {
102-
path.nodes.firstOrNull()?.let { firstNode ->
129+
path?.moves?.firstOrNull()?.let { firstNode ->
103130
val nodeVec = Vec3d.ofBottomCenter(firstNode.pos.toBlockPos())
104-
if (player.pos.distanceTo(nodeVec) < tolerance) {
105-
path.nodes.removeFirst()
131+
if (player.pos.distanceTo(nodeVec) < pathing.tolerance) {
132+
path?.moves?.removeFirst()
106133
integralError = Vec3d.ZERO
107134
}
108-
val next = path.nodes.firstOrNull()?.pos?.toBlockPos() ?: return
135+
val next = path?.moves?.firstOrNull()?.pos?.toBlockPos() ?: return
109136
currentTarget = Vec3d.ofBottomCenter(next)
137+
} ?: run {
138+
currentTarget = null
110139
}
111140
}
112141

@@ -116,8 +145,8 @@ object Pathfinder : Module(
116145
val derivativeError = error.subtract(lastError)
117146
lastError = error
118147

119-
return error.multiply(kP)
120-
.add(integralError.multiply(kI))
121-
.add(derivativeError.multiply(kD))
148+
return error.multiply(pathing.kP)
149+
.add(integralError.multiply(pathing.kI))
150+
.add(derivativeError.multiply(pathing.kD))
122151
}
123152
}

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

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

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,16 @@
1717

1818
package com.lambda.pathing
1919

20+
import com.lambda.pathing.move.Move
2021
import com.lambda.util.world.toBlockPos
2122

2223
data class Path(
23-
val nodes: ArrayDeque<Node> = ArrayDeque(),
24+
val moves: ArrayDeque<Move> = ArrayDeque(),
2425
) {
25-
fun prepend(node: Node) {
26-
nodes.addFirst(node)
26+
fun prepend(move: Move) {
27+
moves.addFirst(move)
2728
}
2829

2930
override fun toString() =
30-
nodes.joinToString(" -> ") { "(${it.pos.toBlockPos().toShortString()})" }
31+
moves.joinToString(" -> ") { "(${it.pos.toBlockPos().toShortString()})" }
3132
}

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

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,42 +18,55 @@
1818
package com.lambda.pathing
1919

2020
import com.lambda.context.SafeContext
21-
import com.lambda.pathing.Node.Companion.toNode
2221
import com.lambda.pathing.goal.Goal
22+
import com.lambda.pathing.move.Move
23+
import com.lambda.pathing.move.MoveFinder
24+
import com.lambda.pathing.move.MoveFinder.findPathType
25+
import com.lambda.pathing.move.MoveFinder.getFeetY
2326
import com.lambda.pathing.move.MoveFinder.moveOptions
27+
import com.lambda.pathing.move.TraverseMove
28+
import com.lambda.util.Communication.warn
2429
import com.lambda.util.world.FastVector
30+
import com.lambda.util.world.toBlockPos
2531
import java.util.PriorityQueue
2632

2733
object Pathing {
28-
fun SafeContext.findPathAStar(start: FastVector, goal: Goal): Path {
29-
val openSet = PriorityQueue<Node>()
30-
val closedSet = mutableSetOf<Node>()
31-
val startNode = start.toNode(goal)
34+
fun SafeContext.findPathAStar(start: FastVector, goal: Goal, timeout: Long = 50L): Path {
35+
MoveFinder.clean()
36+
val startedAt = System.currentTimeMillis()
37+
val openSet = PriorityQueue<Move>()
38+
val closedSet = mutableSetOf<FastVector>()
39+
val startFeetY = getFeetY(start.toBlockPos())
40+
val startNode = TraverseMove(start, goal.heuristic(start), findPathType(start), startFeetY, 0.0)
3241
startNode.gCost = 0.0
3342
openSet.add(startNode)
3443

35-
while (openSet.isNotEmpty()) {
44+
println("Starting pathfinding at ${start.toBlockPos().toShortString()} to $goal")
45+
46+
while (openSet.isNotEmpty() && startedAt + timeout > System.currentTimeMillis()) {
3647
val current = openSet.remove()
48+
println("Considering node: ${current.pos.toBlockPos()}")
3749
if (goal.inGoal(current.pos)) {
38-
// println("Not yet considered nodes: ${openSet.size}")
39-
// println("Closed nodes: ${closedSet.size}")
50+
println("Not yet considered nodes: ${openSet.size}")
51+
println("Closed nodes: ${closedSet.size}")
4052
return current.createPathToSource()
4153
}
4254

43-
closedSet.add(current)
55+
closedSet.add(current.pos)
4456

45-
moveOptions(current.pos).forEach { move ->
46-
val successor = move.node(current.pos, goal)
47-
if (closedSet.contains(successor)) return@forEach
48-
val tentativeGCost = current.gCost + move.cost()
49-
if (tentativeGCost >= successor.gCost) return@forEach
50-
successor.predecessor = current
51-
successor.gCost = tentativeGCost
52-
openSet.add(successor)
57+
moveOptions(current, goal).forEach { move ->
58+
println("Considering move: $move")
59+
if (closedSet.contains(move.pos)) return@forEach
60+
val tentativeGCost = current.gCost + move.cost
61+
if (tentativeGCost >= move.gCost) return@forEach
62+
move.predecessor = current
63+
move.gCost = tentativeGCost
64+
openSet.add(move)
65+
println("Using move: $move")
5366
}
5467
}
5568

56-
println("No path found")
57-
return Path()
69+
warn("Only partial path found!")
70+
return if (openSet.isNotEmpty()) openSet.remove().createPathToSource() else Path()
5871
}
5972
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright 2024 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
19+
20+
interface PathingConfig {
21+
val kP: Double
22+
val kI: Double
23+
val kD: Double
24+
val tolerance: Double
25+
val cutoffTimeout: Long
26+
27+
val assumeJesus: Boolean
28+
}

0 commit comments

Comments
 (0)