Skip to content

Commit e5d627e

Browse files
committed
Rotation rework: Smooth lock, fixed duplicate look grim flag, refactor
1 parent 496b22e commit e5d627e

File tree

11 files changed

+175
-183
lines changed

11 files changed

+175
-183
lines changed

common/src/main/kotlin/com/lambda/event/events/RotationEvent.kt

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,39 +6,44 @@ import com.lambda.event.callback.ICancellable
66
import com.lambda.interaction.InteractionConfig
77
import com.lambda.interaction.RotationManager
88
import com.lambda.interaction.rotation.IRotationConfig
9-
import com.lambda.interaction.rotation.RotationRequest
9+
import com.lambda.interaction.rotation.RotationContext
1010
import com.lambda.interaction.visibilty.VisibilityChecker.findRotation
1111
import com.lambda.threading.runSafe
1212
import com.lambda.util.world.raycast.RayCastUtils.blockResult
1313
import com.lambda.util.world.raycast.RayCastUtils.entityResult
1414
import net.minecraft.entity.LivingEntity
1515
import net.minecraft.util.math.BlockPos
1616
import net.minecraft.util.math.Direction
17-
import java.util.*
1817

1918
abstract class RotationEvent : Event {
19+
/**
20+
* This event allows listeners to register a rotation request to be executed that tick.
21+
*
22+
* CAUTION: The listener with the lowest priority will win as it is the last to override the context.
23+
*
24+
* @property context The rotation context that listeners can set. Only one rotation can "win" each tick.
25+
*/
2026
class Pre : RotationEvent(), ICancellable by Cancellable() {
2127
// Only one rotation can "win" each tick
22-
val requests = TreeSet<RotationRequest>(Comparator.reverseOrder())
28+
var context: RotationContext? = null
2329

2430
init {
2531
// Always check if baritone wants to rotate as well
2632
RotationManager.BaritoneProcessor.baritoneContext?.let { context ->
27-
requests.add(RotationRequest(context.config, context.rotation, -1))
33+
this.context = RotationContext(context.rotation, context.config)
2834
}
2935
}
3036

3137
fun lookAtEntity(
3238
rotationConfig: IRotationConfig,
3339
interactionConfig: InteractionConfig,
34-
entity: LivingEntity,
35-
priority: Int = 0,
40+
entity: LivingEntity
3641
) {
3742
runSafe {
38-
findRotation(rotationConfig, interactionConfig, listOf(entity.boundingBox), priority) {
43+
findRotation(rotationConfig, interactionConfig, listOf(entity.boundingBox)) {
3944
entityResult?.entity == entity
40-
}?.let {
41-
requests.add(it)
45+
}?.let { rotationContext ->
46+
context = rotationContext
4247
}
4348
}
4449
}
@@ -47,21 +52,20 @@ abstract class RotationEvent : Event {
4752
rotationConfig: IRotationConfig,
4853
interactionConfig: InteractionConfig,
4954
blockPos: BlockPos,
50-
sides: Set<Direction> = emptySet(),
51-
priority: Int = 0,
55+
sides: Set<Direction> = emptySet()
5256
) {
5357
runSafe {
5458
val state = world.getBlockState(blockPos)
5559
val voxelShape = state.getOutlineShape(world, blockPos)
5660
val boundingBoxes = voxelShape.boundingBoxes.map { it.offset(blockPos) }
57-
findRotation(rotationConfig, interactionConfig, boundingBoxes, priority, sides) {
61+
findRotation(rotationConfig, interactionConfig, boundingBoxes, sides) {
5862
blockResult?.blockPos == blockPos && (blockResult?.side in sides || sides.isEmpty())
59-
}?.let {
60-
requests.add(it)
63+
}?.let { rotationContext ->
64+
context = rotationContext
6165
}
6266
}
6367
}
6468
}
6569

66-
class Post(val request: RotationRequest) : RotationEvent()
70+
class Post(val context: RotationContext) : RotationEvent()
6771
}

common/src/main/kotlin/com/lambda/interaction/PlayerPacketManager.kt

Lines changed: 18 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,17 @@ import com.lambda.core.Loadable
44
import com.lambda.context.SafeContext
55
import com.lambda.event.EventFlow.post
66
import com.lambda.event.EventFlow.postChecked
7-
import com.lambda.event.events.PacketEvent
87
import com.lambda.event.events.PlayerPacketEvent
9-
import com.lambda.event.listener.SafeListener.Companion.listener
108
import com.lambda.threading.runSafe
11-
import com.lambda.util.Communication.warn
129
import com.lambda.util.collections.LimitedOrderedSet
13-
import com.lambda.util.math.VecUtils.dist
14-
import com.lambda.util.math.VecUtils.distSq
10+
import com.lambda.util.math.VecUtils.approximate
1511
import com.lambda.util.player.MovementUtils.motionX
1612
import com.lambda.util.player.MovementUtils.motionZ
1713
import com.lambda.util.primitives.extension.component1
1814
import com.lambda.util.primitives.extension.component2
1915
import com.lambda.util.primitives.extension.component3
20-
import com.lambda.util.text.Color
21-
import com.lambda.util.text.buildText
22-
import com.lambda.util.text.color
23-
import com.lambda.util.text.literal
2416
import net.minecraft.network.packet.c2s.play.ClientCommandC2SPacket
2517
import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket.*
26-
import net.minecraft.network.packet.s2c.play.PlayerPositionLookS2CPacket
27-
import net.minecraft.util.math.MathHelper.square
28-
import net.minecraft.util.math.Vec3d
2918

3019
object PlayerPacketManager : Loadable {
3120
val configurations = LimitedOrderedSet<PlayerPacketEvent.Pre>(100)
@@ -55,45 +44,47 @@ object PlayerPacketManager : Loadable {
5544

5645
if (mc.cameraEntity != player) return
5746

58-
RotationManager.currentRotation = new.rotation
47+
val rotation = new.rotation
48+
val position = new.position
49+
RotationManager.currentRotation = rotation
50+
val (yaw, pitch) = rotation.float
51+
val onGround = new.onGround
5952

6053
if (player.hasVehicle()) {
6154
connection.sendPacket(
6255
Full(
6356
player.motionX,
6457
-999.0,
6558
player.motionZ,
66-
new.rotation.yaw.toFloat(),
67-
new.rotation.pitch.toFloat(),
68-
new.onGround
59+
yaw,
60+
pitch,
61+
onGround
6962
)
7063
)
7164
return
7265
}
7366

74-
val updatePosition = (new.position.subtract(previous.position) distSq Vec3d.ZERO) > square(2.0E-4) || ++sendTicks >= 20
75-
val updateRotation = new.rotation != previous.rotation
67+
val updatePosition = position.approximate(previous.position, 2.0E-4) || ++sendTicks >= 20
68+
// has to be different in float precision
69+
val updateRotation = !rotation.equalFloat(previous.rotation)
7670

77-
val (x, y, z) = new.position
78-
79-
val (yawD, pitchD) = new.rotation
80-
val (yaw, pitch) = yawD.toFloat() to pitchD.toFloat()
71+
val (x, y, z) = position
8172

8273
val packet = when {
8374
updatePosition && updateRotation -> {
84-
Full(x, y, z, yaw, pitch, new.onGround)
75+
Full(x, y, z, yaw, pitch, onGround)
8576
}
8677

8778
updatePosition -> {
88-
PositionAndOnGround(x, y, z, new.onGround)
79+
PositionAndOnGround(x, y, z, onGround)
8980
}
9081

9182
updateRotation -> {
92-
LookAndOnGround(yaw, pitch, new.onGround)
83+
LookAndOnGround(yaw, pitch, onGround)
9384
}
9485

95-
previous.onGround != new.onGround -> {
96-
OnGroundOnly(new.onGround)
86+
previous.onGround != onGround -> {
87+
OnGroundOnly(onGround)
9788
}
9889

9990
else -> null

common/src/main/kotlin/com/lambda/interaction/RotationManager.kt

Lines changed: 42 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,18 @@ import com.lambda.event.listener.UnsafeListener.Companion.unsafeListener
1010
import com.lambda.interaction.rotation.Rotation
1111
import com.lambda.interaction.rotation.Rotation.Companion.angleDifference
1212
import com.lambda.interaction.rotation.Rotation.Companion.fixSensitivity
13-
import com.lambda.interaction.rotation.Rotation.Companion.interpolate
13+
import com.lambda.interaction.rotation.Rotation.Companion.slerp
14+
import com.lambda.interaction.rotation.Rotation.Companion.lerp
1415
import com.lambda.interaction.rotation.RotationContext
1516
import com.lambda.interaction.rotation.RotationMode
16-
import com.lambda.interaction.rotation.RotationRequest
1717
import com.lambda.module.modules.client.Baritone
1818
import com.lambda.threading.runOnGameThread
1919
import com.lambda.threading.runSafe
2020
import com.lambda.util.math.MathUtils.lerp
2121
import com.lambda.util.math.MathUtils.toRadian
2222
import com.lambda.util.math.Vec2d
2323
import com.lambda.util.primitives.extension.partialTicks
24+
import com.lambda.util.primitives.extension.rotation
2425
import net.minecraft.client.input.KeyboardInput
2526
import net.minecraft.enchantment.EnchantmentHelper
2627
import net.minecraft.network.packet.s2c.play.PlayerPositionLookS2CPacket
@@ -30,9 +31,9 @@ import kotlin.math.sign
3031

3132
object RotationManager : Loadable {
3233
var currentRotation = Rotation.ZERO
33-
private var prevRotation = Rotation.ZERO
34+
var prevRotation = Rotation.ZERO
3435

35-
var currentRequest: RotationRequest? = null
36+
var currentContext: RotationContext? = null
3637

3738
private var keepTicks = 0
3839
private var pauseTicks = 0
@@ -41,9 +42,8 @@ object RotationManager : Loadable {
4142
fun update() =
4243
runSafe {
4344
RotationEvent.Pre().post {
44-
rotate()?.let {
45-
RotationEvent.Post(it).post()
46-
}
45+
rotate(context)
46+
currentContext?.let { RotationEvent.Post(it).post() }
4747
}
4848
}
4949

@@ -58,108 +58,97 @@ object RotationManager : Loadable {
5858
}
5959

6060
listener<RenderEvent.UpdateTarget> {
61-
if (currentRequest == null) return@listener
62-
if (currentRequest?.config?.rotationMode != RotationMode.LOCK) return@listener
63-
val interpolation = prevRotation.interpolate(currentRotation, mc.tickDelta.toDouble())
61+
val context = currentContext ?: return@listener
62+
if (context.config.rotationMode != RotationMode.LOCK) return@listener
63+
val interpolation = prevRotation.lerp(currentRotation, mc.tickDelta.toDouble())
6464

65-
// val rot = interpolation.fixSensitivity(prevRotation)
66-
67-
player.yaw = interpolation.yaw.toFloat()
68-
player.pitch = interpolation.pitch.toFloat()
65+
player.yaw = interpolation.yawF
66+
player.pitch = interpolation.pitchF
6967
}
7068

7169
unsafeListener<ConnectionEvent.Disconnect> {
7270
reset(Rotation.ZERO)
7371
}
7472
}
7573

76-
private fun RotationEvent.Pre.rotate() = runSafe {
74+
private fun rotate(newContext: RotationContext?) = runSafe {
7775
prevRotation = currentRotation
7876

7977
(keepTicks--).coerceAtLeast(0)
8078
(pauseTicks--).coerceAtLeast(0)
8179

82-
val resetTicks = currentRequest?.config?.resetTicks ?: 0
83-
if (keepTicks + resetTicks < 0 || pauseTicks >= 0) {
84-
currentRequest = null
80+
currentContext?.let { current ->
81+
if (keepTicks + current.config.resetTicks < 0 || pauseTicks >= 0) {
82+
currentContext = null
83+
}
8584
}
8685

87-
var chosenRequest: RotationRequest? = null
88-
89-
requests.firstOrNull()?.let { request ->
90-
chosenRequest = request
91-
currentRequest = request
86+
newContext?.let { request ->
87+
currentContext = request
9288
keepTicks = request.config.keepTicks
9389
}
9490

95-
currentRotation = Rotation(player.yaw, player.pitch)
96-
97-
val context = currentRequest ?: return@runSafe chosenRequest
98-
val rotationTo = if (keepTicks >= 0) context.rotation else currentRotation
91+
currentContext?.let { current ->
92+
val rotationTo = if (keepTicks >= 0) current.rotation else currentRotation
9993

100-
var speedMultiplier = (context.config as? RotationSettings)?.speedMultiplier ?: 1.0
101-
if (keepTicks < 0) speedMultiplier = 1.0
94+
var speedMultiplier = (current.config as? RotationSettings)?.speedMultiplier ?: 1.0
95+
if (keepTicks < 0) speedMultiplier = 1.0
10296

103-
val turnSpeed = context.config.turnSpeed * speedMultiplier
97+
val turnSpeed = current.config.turnSpeed * speedMultiplier
10498

105-
val interpolation = prevRotation.interpolate(rotationTo, turnSpeed)
99+
val interpolation = prevRotation.slerp(rotationTo, turnSpeed)
106100

107-
currentRotation = interpolation.fixSensitivity(prevRotation)
101+
currentRotation = interpolation.fixSensitivity(prevRotation)
108102

109-
if (context.config.rotationMode == RotationMode.LOCK) {
110-
player.yaw = currentRotation.yaw.toFloat()
111-
player.pitch = currentRotation.pitch.toFloat()
112-
}
113-
114-
chosenRequest?.let { request ->
115-
if (request.rotation.fixSensitivity(prevRotation) == currentRotation) {
116-
request.isPending = false
103+
if (current.config.rotationMode == RotationMode.LOCK) {
104+
player.yaw = currentRotation.yaw.toFloat()
105+
player.pitch = currentRotation.pitch.toFloat()
117106
}
107+
} ?: run {
108+
currentRotation = player.rotation
118109
}
119-
120-
return@runSafe chosenRequest
121110
}
122111

123112
private fun reset(rotation: Rotation) {
124113
prevRotation = rotation
125114
currentRotation = rotation
126115

127-
currentRequest = null
116+
currentContext = null
128117
pauseTicks = 3
129118
}
130119

131120
private val smoothRotation get() =
132121
lerp(prevRotation, currentRotation, mc.partialTicks)
133122

134123
@JvmStatic val lockRotation get() =
135-
if (currentRequest?.config?.rotationMode == RotationMode.LOCK) smoothRotation else null
124+
if (currentContext?.config?.rotationMode == RotationMode.LOCK) smoothRotation else null
136125

137126
@JvmStatic val renderYaw get() =
138-
if (currentRequest?.config == null) null else smoothRotation.yaw.toFloat()
127+
if (currentContext?.config == null) null else smoothRotation.yaw.toFloat()
139128

140129
@JvmStatic val renderPitch get() =
141-
if (currentRequest?.config == null) null else smoothRotation.pitch.toFloat()
130+
if (currentContext?.config == null) null else smoothRotation.pitch.toFloat()
142131

143132
@JvmStatic val handYaw get() =
144-
if (currentRequest?.config?.rotationMode == RotationMode.LOCK) currentRotation.yaw.toFloat() else null
133+
if (currentContext?.config?.rotationMode == RotationMode.LOCK) currentRotation.yaw.toFloat() else null
145134

146135
@JvmStatic val handPitch get() =
147-
if (currentRequest?.config?.rotationMode == RotationMode.LOCK) currentRotation.pitch.toFloat() else null
136+
if (currentContext?.config?.rotationMode == RotationMode.LOCK) currentRotation.pitch.toFloat() else null
148137

149138
@JvmStatic val movementYaw: Float? get() {
150-
val config = currentRequest?.config ?: return null
139+
val config = currentContext?.config ?: return null
151140
if (config.rotationMode == RotationMode.SILENT) return null
152141
return currentRotation.yaw.toFloat()
153142
}
154143

155144
@JvmStatic val movementPitch: Float? get() {
156-
val config = currentRequest?.config ?: return null
145+
val config = currentContext?.config ?: return null
157146
if (config.rotationMode == RotationMode.SILENT) return null
158147
return currentRotation.pitch.toFloat()
159148
}
160149

161150
@JvmStatic fun getRotationForVector(deltaTime: Double): Vec2d? {
162-
val config = currentRequest?.config ?: return null
151+
val config = currentContext?.config ?: return null
163152
if (config.rotationMode == RotationMode.SILENT) return null
164153

165154
val rot = lerp(prevRotation, currentRotation, deltaTime)
@@ -188,12 +177,12 @@ object RotationManager : Loadable {
188177

189178
@JvmStatic
190179
fun handleBaritoneRotation(yaw: Float, pitch: Float) = runSafe {
191-
baritoneContext = RotationContext(Baritone.rotation, Rotation(yaw, pitch))
180+
baritoneContext = RotationContext(Rotation(yaw, pitch), Baritone.rotation)
192181
}
193182

194183
@JvmStatic
195184
fun processPlayerMovement() = runSafe {
196-
val config = currentRequest?.config ?: return@runSafe
185+
val config = currentContext?.config ?: return@runSafe
197186

198187
val input = player.input
199188
val handledByBaritone = input !is KeyboardInput

0 commit comments

Comments
 (0)