diff --git a/src/main/kotlin/org/cobalt/command/impl/MainCommand.kt b/src/main/kotlin/org/cobalt/command/impl/MainCommand.kt index 6d55979..a869f03 100644 --- a/src/main/kotlin/org/cobalt/command/impl/MainCommand.kt +++ b/src/main/kotlin/org/cobalt/command/impl/MainCommand.kt @@ -3,9 +3,12 @@ package org.cobalt.command.impl import net.minecraft.client.Minecraft import org.cobalt.command.Command import org.cobalt.command.annotation.DefaultHandler +import org.cobalt.command.annotation.SubCommand import org.cobalt.ui.screen.ConfigScreen import org.cobalt.util.ChatUtils import org.cobalt.util.helper.TickScheduler +import org.cobalt.util.rotation.DefaultRotations +import org.cobalt.util.rotation.RotationManager internal object MainCommand : Command( name = "cobalt", @@ -22,4 +25,12 @@ internal object MainCommand : Command( } } + @SubCommand + fun rotate(yaw: Double, pitch: Double) { + RotationManager.setActiveRotation( + DefaultRotations, + yaw = yaw, + pitch = pitch + ) + } } diff --git a/src/main/kotlin/org/cobalt/util/rotation/DefaultRotations.kt b/src/main/kotlin/org/cobalt/util/rotation/DefaultRotations.kt new file mode 100644 index 0000000..bc3ff4e --- /dev/null +++ b/src/main/kotlin/org/cobalt/util/rotation/DefaultRotations.kt @@ -0,0 +1,96 @@ +package org.cobalt.util.rotation + +import org.cobalt.util.ChatUtils +import org.cobalt.util.MessageType +import kotlin.math.abs +import org.cobalt.Cobalt.mc + +object DefaultRotations : IRotation { + + private var rotating = false + private var targetYaw = 0.0 + private var targetPitch = 0.0 + private var currentYaw = 0.0 + private var currentPitch = 0.0 + + override fun onRotationStart(yaw: Double, pitch: Double) { + rotating = true + targetYaw = yaw + targetPitch = pitch + currentYaw = getPlayerYaw() + currentPitch = getPlayerPitch() + + ChatUtils.message("Rotation started to $yaw, $pitch", MessageType.DEBUG) + } + + override fun onRotationEnd() { + rotating = false + ChatUtils.message("Ended rotation.", MessageType.DEBUG) + } + + override fun onRotationWorldRender() { + if (!rotating) return + + val player = getPlayer() ?: return + + val currentYaw = player.yRot.toDouble() + val currentPitch = player.xRot.toDouble() + + val speed = 0.15 // TODO: add this as param in function + + val newYaw = lerpAngle(currentYaw, targetYaw, speed) + val newPitch = lerp(currentPitch, targetPitch, speed) + + applyRotation(newYaw, newPitch) + + if ( + distance(newYaw, targetYaw) < 0.05 && + abs(newPitch - targetPitch) < 0.05 + ) { + stopRotation() + } + } + + private fun lerpAngle(current: Double, target: Double, alpha: Double): Double { + val delta = ((target - current + 540) % 360) - 180 + return current + delta * alpha + } + + // YES its lerp, do I care? no! ill change in my next commit. + private fun lerp(a: Double, b: Double, t: Double): Double { + return a + (b - a) * t + } + + private fun distance(a: Double, b: Double): Double { + return abs(a - b) + } + + override fun isRotating(): Boolean = rotating + + private fun applyRotation(yaw: Double, pitch: Double) { + val player = getPlayer() ?: return + + val y = yaw.toFloat() + val p = pitch.toFloat() + + player.yRot = y + player.xRot = p + + player.yRotO = y + player.xRotO = p + + player.yHeadRot = y + player.yBodyRot = y + } + + private fun getPlayerYaw(): Double { + return getPlayer()?.yRot?.toDouble() ?: 0.0 + } + + private fun getPlayerPitch(): Double { + return getPlayer()?.xRot?.toDouble() ?: 0.0 + } + + private fun getPlayer() = mc.player + +} diff --git a/src/main/kotlin/org/cobalt/util/rotation/IRotation.kt b/src/main/kotlin/org/cobalt/util/rotation/IRotation.kt new file mode 100644 index 0000000..5863340 --- /dev/null +++ b/src/main/kotlin/org/cobalt/util/rotation/IRotation.kt @@ -0,0 +1,14 @@ +package org.cobalt.util.rotation + +interface IRotation { + + fun onRotationWorldRender() + fun onRotationEnd() + fun onRotationStart(yaw: Double, pitch: Double) + fun isRotating(): Boolean + + fun stopRotation() { + onRotationEnd() + } + +} diff --git a/src/main/kotlin/org/cobalt/util/rotation/RotationManager.kt b/src/main/kotlin/org/cobalt/util/rotation/RotationManager.kt new file mode 100644 index 0000000..7f60576 --- /dev/null +++ b/src/main/kotlin/org/cobalt/util/rotation/RotationManager.kt @@ -0,0 +1,40 @@ +package org.cobalt.util.rotation + +import org.cobalt.event.EventBus +import org.cobalt.event.annotation.SubscribeEvent +import org.cobalt.event.impl.WorldRenderEvent + +object RotationManager { + + private var rotation: IRotation = DefaultRotations + + init { + EventBus.register(this) + } + + fun setActiveRotation(newRotation: IRotation, yaw: Double, pitch: Double) { + if (rotation.isRotating()) { + rotation.stopRotation() + } + + rotation = newRotation + rotation.onRotationStart(yaw, pitch) + } + + fun getActiveRotation(): IRotation = rotation + + fun resetRotation() { + if (rotation.isRotating()) { + rotation.stopRotation() + } + + rotation = DefaultRotations + } + + @SubscribeEvent + fun onWorldRender(event: WorldRenderEvent) { + if (!rotation.isRotating()) return + rotation.onRotationWorldRender() + } + +}