Skip to main content

Overview

The RotationManager handles all rotation-related functionality, including smooth rotation interpolation, server-side rotation synchronization, and movement correction.

Key Concepts

Current vs Server Rotation

  • Current Rotation: The rotation the client is aiming at (may not be sent to server yet)
  • Server Rotation: The rotation the server has received and acknowledged
  • Actual Server Rotation: The rotation that was actually sent to the server
  • Theoretical Server Rotation: What the rotation would be if not lagging/blinking

Properties

currentRotation

The rotation the client wants to aim at.
val currentRotation: Rotation?
Example:
if (RotationManager.currentRotation != null) {
    val yaw = RotationManager.currentRotation!!.yaw
    val pitch = RotationManager.currentRotation!!.pitch
}

serverRotation

The rotation currently active on the server.
val serverRotation: Rotation
Accounts for blink and freeze states automatically.

activeRotationTarget

The current active rotation target being aimed at.
val activeRotationTarget: RotationTarget?

Methods

setRotationTarget (with Rotation)

Sets a target rotation to aim at.
fun setRotationTarget(
    rotation: Rotation,
    considerInventory: Boolean = true,
    valueGroup: RotationsValueGroup,
    priority: Priority,
    provider: ClientModule,
    whenReached: RestrictedSingleUseAction? = null
)
Parameters:
  • rotation - The target rotation (yaw, pitch)
  • considerInventory - Don’t rotate if inventory is open
  • valueGroup - Rotation settings (speed, smoothing, etc.)
  • priority - Priority level for this rotation request
  • provider - The module requesting the rotation
  • whenReached - Callback when rotation target is reached
Example:
val targetRotation = Rotation(
    yaw = calculateYaw(target),
    pitch = calculatePitch(target)
)

RotationManager.setRotationTarget(
    rotation = targetRotation,
    valueGroup = rotationsConfigurable,
    priority = Priority.IMPORTANT_FOR_USAGE,
    provider = this
)

setRotationTarget (with RotationTarget)

Sets a rotation target with advanced options.
fun setRotationTarget(
    plan: RotationTarget,
    priority: Priority,
    provider: ClientModule
)

isRotatingAllowed

Checks if rotation is currently allowed.
fun isRotatingAllowed(rotationTarget: RotationTarget): Boolean
Returns: true if rotation can be updated, false if blocked (e.g., inventory open)

update

Updates the current rotation to the next step. Called automatically every tick.
fun update()

rotationMatchesPreviousRotation

Checks if the rotation hasn’t changed since last update.
fun rotationMatchesPreviousRotation(): Boolean

Rotation Target Configuration

Movement Correction

Controls how player movement is adjusted during rotation:
  • OFF - No movement correction
  • SILENT - Correct movement without changing look direction
  • CHANGE_LOOK - Change player’s actual look direction
val target = rotationsConfigurable.toRotationTarget(
    rotation = targetRotation,
    considerInventory = true
)

Usage Examples

Basic Rotation to Entity

val rotationHandler = handler<GameTickEvent> {
    val target = world.entities.firstOrNull { it.shouldBeAttacked() }
    
    if (target != null) {
        val rotation = aimAt(target.eyePosition)
        
        RotationManager.setRotationTarget(
            rotation = rotation,
            valueGroup = rotationsConfigurable,
            priority = Priority.IMPORTANT_FOR_USAGE,
            provider = this
        )
    }
}

Rotation with Callback

RotationManager.setRotationTarget(
    rotation = targetRotation,
    valueGroup = rotationsConfigurable,
    priority = Priority.IMPORTANT_FOR_USAGE,
    provider = this,
    whenReached = {
        // Rotation has reached target
        performAction()
    }
)

Checking Server Rotation

val handler = handler<AttackEntityEvent> { event ->
    // Only attack if we're actually facing the target on the server
    val serverYaw = RotationManager.serverRotation.yaw
    val targetYaw = calculateYaw(event.entity)
    
    if (abs(serverYaw - targetYaw) > 10f) {
        event.cancelEvent()
    }
}

Using Movement Correction

// With silent movement correction (strafe while looking different direction)
val target = rotationsConfigurable.toRotationTarget(
    rotation = targetRotation,
    considerInventory = true
)
target.movementCorrection = MovementCorrection.SILENT

RotationManager.setRotationTarget(
    plan = target,
    priority = Priority.IMPORTANT_FOR_USAGE,
    provider = this
)

Aiming Utilities

Common rotation calculation utilities:

aimAt

// Aim at a specific position
val rotation = aimAt(targetPos)

facingAngle

// Calculate angle difference
val angle = facingAngle(targetRotation)

Priority System

Rotation requests use a priority system. Higher priority requests override lower ones:
  • Priority.NOT_IMPORTANT - Low priority
  • Priority.NORMAL - Standard priority
  • Priority.IMPORTANT_FOR_PLAYER - Player input priority
  • Priority.IMPORTANT_FOR_USAGE - Important for module functionality
// High priority rotation (e.g., in KillAura)
RotationManager.setRotationTarget(
    rotation = targetRotation,
    priority = Priority.IMPORTANT_FOR_USAGE,
    valueGroup = rotationsConfigurable,
    provider = this
)

Best Practices

Always check if a rotation is allowed before setting it to avoid conflicts with inventory operations.
Don’t set rotations every tick unless necessary. Use the whenReached callback for one-time actions.
The RotationManager automatically handles rotation interpolation and smoothing based on the configured values.

See Also

Build docs developers (and LLMs) love