diff --git a/src/main/java/com/lambda/mixin/MinecraftClientMixin.java b/src/main/java/com/lambda/mixin/MinecraftClientMixin.java index 745502ba5..7631d8bf2 100644 --- a/src/main/java/com/lambda/mixin/MinecraftClientMixin.java +++ b/src/main/java/com/lambda/mixin/MinecraftClientMixin.java @@ -17,13 +17,13 @@ package com.lambda.mixin; -import com.lambda.Lambda; import com.lambda.event.EventFlow; import com.lambda.event.events.ClientEvent; import com.lambda.event.events.InventoryEvent; import com.lambda.event.events.TickEvent; import com.lambda.gui.DearImGui; import com.lambda.module.modules.player.Interact; +import com.lambda.module.modules.player.InventoryMove; import com.lambda.module.modules.player.PacketMine; import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; @@ -33,6 +33,7 @@ import net.minecraft.client.gui.screen.ingame.ScreenHandlerProvider; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.network.ClientPlayerInteractionManager; +import net.minecraft.client.option.KeyBinding; import net.minecraft.client.render.WorldRenderer; import net.minecraft.client.sound.SoundManager; import net.minecraft.util.Hand; @@ -51,10 +52,14 @@ public class MinecraftClientMixin { @Shadow @Nullable public Screen currentScreen; + @Shadow @Nullable public HitResult crosshairTarget; + @Shadow + public int itemUseCooldown; + @Inject(method = "close", at = @At("HEAD")) void closeImGui(CallbackInfo ci) { DearImGui.INSTANCE.destroy(); @@ -131,6 +136,19 @@ private void onScreenRemove(@Nullable Screen screen, CallbackInfo ci) { } } + @Redirect(method = "setScreen", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/option/KeyBinding;unpressAll()V")) + private void redirectUnPressAll() { + if (!InventoryMove.getShouldMove()) { + KeyBinding.unpressAll(); + return; + } + KeyBinding.KEYS_BY_ID.values().forEach(bind -> { + if (!InventoryMove.isKeyMovementRelated(bind.boundKey.getCode())) { + bind.reset(); + } + }); + } + @Redirect(method = "doAttack()Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;swingHand(Lnet/minecraft/util/Hand;)V")) private void redirectHandSwing(ClientPlayerEntity instance, Hand hand) { if (this.crosshairTarget == null) return; @@ -151,6 +169,6 @@ boolean redirectMultiActon(ClientPlayerInteractionManager instance) { void injectFastPlace(CallbackInfo ci) { if (!Interact.INSTANCE.isEnabled()) return; - Lambda.getMc().itemUseCooldown = Interact.getPlaceDelay(); + itemUseCooldown = Interact.getPlaceDelay(); } } diff --git a/src/main/java/com/lambda/mixin/input/KeyboardMixin.java b/src/main/java/com/lambda/mixin/input/KeyboardMixin.java index 928bc5667..ffa136983 100644 --- a/src/main/java/com/lambda/mixin/input/KeyboardMixin.java +++ b/src/main/java/com/lambda/mixin/input/KeyboardMixin.java @@ -19,7 +19,10 @@ import com.lambda.event.EventFlow; import com.lambda.event.events.KeyboardEvent; +import com.lambda.module.modules.player.InventoryMove; import net.minecraft.client.Keyboard; +import net.minecraft.client.option.KeyBinding; +import net.minecraft.client.util.InputUtil; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -32,6 +35,13 @@ private void onKey(long window, int key, int scancode, int action, int modifiers EventFlow.post(new KeyboardEvent.Press(key, scancode, action, modifiers)); } + @Inject(method = "onKey", at = @At("RETURN")) + private void onKeyTail(long window, int key, int scancode, int action, int modifiers, CallbackInfo ci) { + if (!InventoryMove.getShouldMove() || !InventoryMove.isKeyMovementRelated(key)) return; + InputUtil.Key fromCode = InputUtil.fromKeyCode(key, scancode); + KeyBinding.setKeyPressed(fromCode, action != 0); + } + @Inject(method = "onChar", at = @At("HEAD")) private void onChar(long window, int codePoint, int modifiers, CallbackInfo ci) { char[] chars = Character.toChars(codePoint); diff --git a/src/main/kotlin/com/lambda/config/AbstractSetting.kt b/src/main/kotlin/com/lambda/config/AbstractSetting.kt index 1bc909d40..c7c8fb577 100644 --- a/src/main/kotlin/com/lambda/config/AbstractSetting.kt +++ b/src/main/kotlin/com/lambda/config/AbstractSetting.kt @@ -158,6 +158,10 @@ abstract class AbstractSetting( groups.add(path.toList()) } + fun group(path: NamedEnum?) = apply { + path?.let { groups.add(listOf(it)) } + } + fun reset(silent: Boolean = false) { if (!silent && value == defaultValue) { ConfigCommand.info(notChangedMessage()) diff --git a/src/main/kotlin/com/lambda/config/groups/RotationSettings.kt b/src/main/kotlin/com/lambda/config/groups/RotationSettings.kt index 1b8be36fb..505d9cfdb 100644 --- a/src/main/kotlin/com/lambda/config/groups/RotationSettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/RotationSettings.kt @@ -30,7 +30,7 @@ import kotlin.random.Random class RotationSettings( c: Configurable, - baseGroup: NamedEnum, + baseGroup: NamedEnum? = null, vis: () -> Boolean = { true } ) : RotationConfig { override var rotationMode by c.setting("Mode", RotationMode.Sync, "How the player is being rotated on interaction", vis).group(baseGroup) diff --git a/src/main/kotlin/com/lambda/interaction/request/rotating/RotationManager.kt b/src/main/kotlin/com/lambda/interaction/request/rotating/RotationManager.kt index dbc0d474c..dec63a198 100644 --- a/src/main/kotlin/com/lambda/interaction/request/rotating/RotationManager.kt +++ b/src/main/kotlin/com/lambda/interaction/request/rotating/RotationManager.kt @@ -61,6 +61,14 @@ object RotationManager : RequestHandler( var activeRequest: RotationRequest? = null private var changedThisTick = false + fun Any.onRotate( + alwaysListen: Boolean = false, + priority: Int = 0, + block: SafeContext.() -> Unit + ) = this.listen(priority, alwaysListen) { + block() + } + override fun load(): String { super.load() diff --git a/src/main/kotlin/com/lambda/module/modules/player/InventoryMove.kt b/src/main/kotlin/com/lambda/module/modules/player/InventoryMove.kt index 84c9e9111..9efdd934d 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/InventoryMove.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/InventoryMove.kt @@ -17,79 +17,58 @@ package com.lambda.module.modules.player -import com.lambda.event.events.MovementEvent -import com.lambda.event.events.UpdateManagerEvent -import com.lambda.event.listener.SafeListener.Companion.listen +import com.lambda.Lambda.mc import com.lambda.gui.LambdaScreen import com.lambda.interaction.request.rotating.Rotation import com.lambda.interaction.request.rotating.RotationConfig +import com.lambda.interaction.request.rotating.RotationManager.onRotate import com.lambda.interaction.request.rotating.RotationMode import com.lambda.interaction.request.rotating.visibilty.lookAt import com.lambda.module.Module import com.lambda.module.tag.ModuleTag import com.lambda.util.KeyboardUtils.isKeyPressed -import com.lambda.util.math.MathUtils.toDouble import com.lambda.util.math.MathUtils.toFloatSign -import com.lambda.util.player.MovementUtils.update import net.minecraft.client.gui.screen.ChatScreen import net.minecraft.client.gui.screen.Screen +import net.minecraft.client.gui.screen.ingame.AbstractCommandBlockScreen +import net.minecraft.client.gui.screen.ingame.AbstractSignEditScreen import net.minecraft.client.gui.screen.ingame.AnvilScreen -import net.minecraft.client.gui.screen.ingame.CommandBlockScreen -import net.minecraft.client.gui.screen.ingame.SignEditScreen -import org.lwjgl.glfw.GLFW.GLFW_KEY_A -import org.lwjgl.glfw.GLFW.GLFW_KEY_D import org.lwjgl.glfw.GLFW.GLFW_KEY_DOWN import org.lwjgl.glfw.GLFW.GLFW_KEY_KP_2 import org.lwjgl.glfw.GLFW.GLFW_KEY_KP_4 import org.lwjgl.glfw.GLFW.GLFW_KEY_KP_6 import org.lwjgl.glfw.GLFW.GLFW_KEY_KP_8 import org.lwjgl.glfw.GLFW.GLFW_KEY_LEFT -import org.lwjgl.glfw.GLFW.GLFW_KEY_LEFT_CONTROL -import org.lwjgl.glfw.GLFW.GLFW_KEY_LEFT_SHIFT import org.lwjgl.glfw.GLFW.GLFW_KEY_RIGHT -import org.lwjgl.glfw.GLFW.GLFW_KEY_S -import org.lwjgl.glfw.GLFW.GLFW_KEY_SPACE import org.lwjgl.glfw.GLFW.GLFW_KEY_UP -import org.lwjgl.glfw.GLFW.GLFW_KEY_W object InventoryMove : Module( name = "InventoryMove", description = "Allows you to move with GUIs opened", tag = ModuleTag.PLAYER, ) { - private val speed by setting("Rotation Speed", 5, 1..20, 1, unit = "°/tick") + private val arrowKeys by setting("Arrow Keys", false, "Allows rotating the players camera using the arrow keys") + private val speed by setting("Rotation Speed", 5, 1..20, 1, unit = "°/tick") { arrowKeys } private val rotationConfig = RotationConfig.Instant(RotationMode.Lock) + @JvmStatic + val shouldMove get() = isEnabled && !mc.currentScreen.hasInputOrNull + /** * Whether the current screen has text inputs or is null */ + @JvmStatic val Screen?.hasInputOrNull: Boolean get() = this is ChatScreen || - this is SignEditScreen || + this is AbstractSignEditScreen || this is AnvilScreen || - this is CommandBlockScreen || + this is AbstractCommandBlockScreen || this is LambdaScreen || this == null init { - listen(20250415) { event -> - if (mc.currentScreen.hasInputOrNull) return@listen - - val forward = isKeyPressed(GLFW_KEY_W).toDouble() - - isKeyPressed(GLFW_KEY_S).toDouble() - - val strafe = isKeyPressed(GLFW_KEY_A).toDouble() - - isKeyPressed(GLFW_KEY_D).toDouble() - - val jump = isKeyPressed(GLFW_KEY_SPACE) - val sneak = isKeyPressed(GLFW_KEY_LEFT_SHIFT) - val sprint = isKeyPressed(GLFW_KEY_LEFT_CONTROL) - - event.input.update(forward, strafe, jump, sneak, sprint) - } - - listen { - if (mc.currentScreen.hasInputOrNull) return@listen + onRotate { + if (!arrowKeys || mc.currentScreen.hasInputOrNull) return@onRotate val pitch = (isKeyPressed(GLFW_KEY_DOWN, GLFW_KEY_KP_2).toFloatSign() - isKeyPressed(GLFW_KEY_UP, GLFW_KEY_KP_8).toFloatSign()) * speed @@ -101,4 +80,19 @@ object InventoryMove : Module( ).requestBy(rotationConfig) } } + + @JvmStatic + fun isKeyMovementRelated(key: Int): Boolean { + val options = mc.options + return when (key) { + options.forwardKey.boundKey.code, + options.backKey.boundKey.code, + options.leftKey.boundKey.code, + options.rightKey.boundKey.code, + options.jumpKey.boundKey.code, + options.sprintKey.boundKey.code, + options.sneakKey.boundKey.code -> true + else -> false + } + } } diff --git a/src/main/resources/lambda.accesswidener b/src/main/resources/lambda.accesswidener index 225617e30..46df51c1f 100644 --- a/src/main/resources/lambda.accesswidener +++ b/src/main/resources/lambda.accesswidener @@ -9,6 +9,8 @@ transitive-accessible field net/minecraft/client/input/Input movementVector Lnet transitive-accessible field net/minecraft/client/MinecraftClient renderTaskQueue Ljava/util/Queue; transitive-accessible field net/minecraft/client/option/KeyBinding boundKey Lnet/minecraft/client/util/InputUtil$Key; transitive-accessible method net/minecraft/client/MinecraftClient getWindowTitle ()Ljava/lang/String; +accessible field net/minecraft/client/option/KeyBinding KEYS_BY_ID Ljava/util/Map; +accessible method net/minecraft/client/option/KeyBinding reset ()V # World transitive-accessible field net/minecraft/client/world/ClientWorld entityManager Lnet/minecraft/world/entity/ClientEntityManager;