Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions common/src/main/java/com/lambda/mixin/MinecraftClientMixin.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@
import com.lambda.event.events.InventoryEvent;
import com.lambda.event.events.TickEvent;
import com.lambda.module.modules.player.Interact;
import com.lambda.module.modules.player.InventoryMove;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.ingame.ScreenHandlerProvider;
import net.minecraft.client.network.ClientPlayerInteractionManager;
import net.minecraft.client.option.KeyBinding;
import net.minecraft.util.thread.ThreadExecutor;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
Expand Down Expand Up @@ -91,6 +93,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.INSTANCE.isDisabled() || InventoryMove.hasInputOrNull(currentScreen)) {
Copy link

Copilot AI Aug 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The condition InventoryMove.INSTANCE.isDisabled() || InventoryMove.hasInputOrNull(currentScreen) is duplicated in KeyboardMixin. Consider extracting this logic into a utility method to reduce code duplication.

Suggested change
if (InventoryMove.INSTANCE.isDisabled() || InventoryMove.hasInputOrNull(currentScreen)) {
if (shouldUnpressAll(currentScreen)) {

Copilot uses AI. Check for mistakes.
KeyBinding.unpressAll();
return;
}
KeyBinding.KEYS_BY_ID.values().forEach(bind -> {
if (!InventoryMove.isKeyMovementRelated(bind.boundKey.getCode())) {
bind.reset();
}
});
Comment on lines +102 to +106
Copy link

Copilot AI Aug 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using forEach with a lambda on every screen transition could be inefficient. Consider using a traditional for-each loop or caching the filtered keybindings for better performance.

Suggested change
KeyBinding.KEYS_BY_ID.values().forEach(bind -> {
if (!InventoryMove.isKeyMovementRelated(bind.boundKey.getCode())) {
bind.reset();
}
});
for (KeyBinding bind : KeyBinding.KEYS_BY_ID.values()) {
if (!InventoryMove.isKeyMovementRelated(bind.boundKey.getCode())) {
bind.reset();
}
}

Copilot uses AI. Check for mistakes.
}

@Redirect(method = "doItemUse", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerInteractionManager;isBreakingBlock()Z"))
boolean injectMultiActon(ClientPlayerInteractionManager instance) {
if (instance == null) return true;
Expand Down
14 changes: 14 additions & 0 deletions common/src/main/java/com/lambda/mixin/input/KeyboardMixin.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,17 @@

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;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

import static com.lambda.Lambda.getMc;

@Mixin(Keyboard.class)
public class KeyboardMixin {
@Inject(method = "onKey", at = @At("HEAD"))
Expand All @@ -33,6 +38,15 @@ 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.INSTANCE.isDisabled() || InventoryMove.hasInputOrNull(getMc().currentScreen)) return;
if (InventoryMove.isKeyMovementRelated(key)) {
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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@

package com.lambda.module.modules.player

import com.lambda.event.events.MovementEvent
import com.lambda.event.listener.SafeListener.Companion.listen
import com.lambda.Lambda.mc
import com.lambda.gui.LambdaScreen
import com.lambda.interaction.request.rotation.Rotation
import com.lambda.interaction.request.rotation.RotationConfig
Expand All @@ -28,57 +27,33 @@ import com.lambda.interaction.request.rotation.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.buildMovementInput
import com.lambda.util.player.MovementUtils.mergeFrom
import net.minecraft.client.gui.screen.ChatScreen
import net.minecraft.client.gui.screen.Screen
import net.minecraft.client.gui.screen.ingame.AnvilScreen
import net.minecraft.client.gui.screen.ingame.CommandBlockScreen
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen
import net.minecraft.client.gui.screen.ingame.SignEditScreen
import net.minecraft.client.network.ClientPlayerEntity
import org.lwjgl.glfw.GLFW.*
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_RIGHT
import org.lwjgl.glfw.GLFW.GLFW_KEY_UP

object InventoryMove : Module(
name = "InventoryMove",
description = "Allows you to move with GUIs opened",
defaultTags = setOf(ModuleTag.PLAYER, ModuleTag.MOVEMENT)
) {
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)

/**
* Whether the current screen has text inputs or is null
*/
val Screen?.hasInputOrNull: Boolean
get() = this is ChatScreen ||
this is SignEditScreen ||
this is AnvilScreen ||
this is CommandBlockScreen ||
this is LambdaScreen ||
this == null

init {
listen<MovementEvent.InputUpdate>(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)

player.isSprinting = isKeyPressed(GLFW_KEY_LEFT_CONTROL)
event.input.mergeFrom(buildMovementInput(forward, strafe, jump, sneak))
}

onRotate {
if (mc.currentScreen.hasInputOrNull) return@onRotate
if (!arrowKeys || hasInputOrNull(mc.currentScreen)) return@onRotate

val pitch = (isKeyPressed(GLFW_KEY_DOWN, GLFW_KEY_KP_2).toFloatSign() -
isKeyPressed(GLFW_KEY_UP, GLFW_KEY_KP_8).toFloatSign()) * speed
Expand All @@ -90,4 +65,31 @@ object InventoryMove : Module(
).requestBy(rotationConfig)
}
}

/**
* Whether the current screen has text inputs or is null
*/
@JvmStatic
fun hasInputOrNull(screen: Screen?) =
screen is ChatScreen ||
screen is SignEditScreen ||
screen is AnvilScreen ||
screen is CommandBlockScreen ||
screen is LambdaScreen ||
screen == null

@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
}
}
}
2 changes: 2 additions & 0 deletions common/src/main/resources/lambda.accesswidener
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ accessible field net/minecraft/client/MinecraftClient pausedTickDelta F
accessible field net/minecraft/client/MinecraftClient thread Ljava/lang/Thread;
accessible field net/minecraft/client/MinecraftClient uptimeInTicks J
accessible field net/minecraft/client/option/KeyBinding boundKey Lnet/minecraft/client/util/InputUtil$Key;
accessible field net/minecraft/client/option/KeyBinding KEYS_BY_ID Ljava/util/Map;
accessible method net/minecraft/client/option/KeyBinding reset ()V

# World
accessible field net/minecraft/client/world/ClientWorld entityManager Lnet/minecraft/client/world/ClientEntityManager;
Expand Down