diff --git a/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/gui/MixinHandledScreen.java b/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/gui/MixinHandledScreen.java new file mode 100644 index 00000000000..29f91aad3b4 --- /dev/null +++ b/src/main/java/net/ccbluex/liquidbounce/injection/mixins/minecraft/gui/MixinHandledScreen.java @@ -0,0 +1,23 @@ +package net.ccbluex.liquidbounce.injection.mixins.minecraft.gui; + +import net.ccbluex.liquidbounce.features.module.modules.movement.ModuleInventoryMove; +import net.minecraft.client.gui.screen.ingame.HandledScreen; +import net.minecraft.client.gui.screen.ingame.InventoryScreen; +import net.minecraft.screen.slot.Slot; +import net.minecraft.screen.slot.SlotActionType; +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; + +@Mixin(HandledScreen.class) +public abstract class MixinHandledScreen extends MixinScreen { + + @Inject(method = "onMouseClick(Lnet/minecraft/screen/slot/Slot;IILnet/minecraft/screen/slot/SlotActionType;)V", at = @At("HEAD"), cancellable = true) + private void cancelMouseClick(Slot slot, int slotId, int button, SlotActionType actionType, CallbackInfo ci) { + var inventoryMove = ModuleInventoryMove.INSTANCE; + if ((Object) this instanceof InventoryScreen && inventoryMove.getRunning() && inventoryMove.getCancelClicks()) { + ci.cancel(); + } + } +} diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/combat/ModuleAutoShoot.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/combat/ModuleAutoShoot.kt index 2e4f7a8f44d..aff0d2e64c6 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/combat/ModuleAutoShoot.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/combat/ModuleAutoShoot.kt @@ -208,7 +208,7 @@ object ModuleAutoShoot : ClientModule("AutoShoot", Category.COMBAT) { // Check if we are still aiming at the target clickScheduler.clicks { - if (player.isUsingItem || (considerInventory && InventoryManager.isInventoryOpenServerSide)) { + if (player.isUsingItem || (considerInventory && InventoryManager.isInventoryOpen)) { return@clicks false } diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/combat/autoarmor/ModuleAutoArmor.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/combat/autoarmor/ModuleAutoArmor.kt index ed858d3a018..4157c20c06c 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/combat/autoarmor/ModuleAutoArmor.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/combat/autoarmor/ModuleAutoArmor.kt @@ -101,7 +101,7 @@ object ModuleAutoArmor : ClientModule("AutoArmor", Category.COMBAT) { slot: ItemSlot, isInArmorSlot: Boolean ): InventoryAction { - val canTryHotbarMove = !isInArmorSlot && useHotbar && !InventoryManager.isInventoryOpenServerSide + val canTryHotbarMove = !isInArmorSlot && useHotbar && !InventoryManager.isInventoryOpen if (slot is HotbarItemSlot && canTryHotbarMove) { return UseInventoryAction(slot) } diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/combat/killaura/ModuleKillAura.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/combat/killaura/ModuleKillAura.kt index a96da506a27..d4712b78642 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/combat/killaura/ModuleKillAura.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/combat/killaura/ModuleKillAura.kt @@ -159,7 +159,7 @@ object ModuleKillAura : ClientModule("KillAura", Category.COMBAT) { val rotationUpdateHandler = handler { // Make sure killaura-logic is not running while inventory is open val isInInventoryScreen = - InventoryManager.isInventoryOpenServerSide || mc.currentScreen is GenericContainerScreen + InventoryManager.isInventoryOpen || mc.currentScreen is GenericContainerScreen val shouldCleanUpTracker = player.isSpectator || player.isDead || !canTargetEnemies @@ -470,7 +470,7 @@ object ModuleKillAura : ClientModule("KillAura", Category.COMBAT) { val shielding = attackShielding || choosenEntity !is PlayerEntity || player.mainHandStack.item is AxeItem || !choosenEntity.wouldBlockHit(player) val isInInventoryScreen = - InventoryManager.isInventoryOpenServerSide || mc.currentScreen is GenericContainerScreen + InventoryManager.isInventoryOpen || mc.currentScreen is GenericContainerScreen val missCooldown = considerMissCooldown && mc.attackCooldown > 0 return critical && shielding && @@ -485,7 +485,7 @@ object ModuleKillAura : ClientModule("KillAura", Category.COMBAT) { */ internal suspend fun Sequence<*>.prepareAttackEnvironment(rotation: Rotation? = null, attack: () -> Unit) { val isInInventoryScreen = - InventoryManager.isInventoryOpenServerSide || mc.currentScreen is GenericContainerScreen + InventoryManager.isInventoryOpen || mc.currentScreen is GenericContainerScreen if (simulateInventoryClosing && isInInventoryScreen) { network.sendPacket(CloseHandledScreenC2SPacket(0)) diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/combat/killaura/features/KillAuraFailSwing.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/combat/killaura/features/KillAuraFailSwing.kt index e7bbc6d8b1c..c2471f894b6 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/combat/killaura/features/KillAuraFailSwing.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/combat/killaura/features/KillAuraFailSwing.kt @@ -60,7 +60,7 @@ internal object KillAuraFailSwing : ToggleableConfigurable(ModuleKillAura, "Fail } val isInInventoryScreen = - InventoryManager.isInventoryOpenServerSide || mc.currentScreen is GenericContainerScreen + InventoryManager.isInventoryOpen || mc.currentScreen is GenericContainerScreen if (isInInventoryScreen && !ModuleKillAura.ignoreOpenInventory && !ModuleKillAura.simulateInventoryClosing) { return diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/ModuleInventoryMove.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/ModuleInventoryMove.kt index 7692a575263..26b7e4cd295 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/ModuleInventoryMove.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/ModuleInventoryMove.kt @@ -18,25 +18,30 @@ */ package net.ccbluex.liquidbounce.features.module.modules.movement +import net.ccbluex.liquidbounce.config.types.NamedChoice import net.ccbluex.liquidbounce.config.types.ToggleableConfigurable -import net.ccbluex.liquidbounce.event.events.NotificationEvent -import net.ccbluex.liquidbounce.event.events.QueuePacketEvent -import net.ccbluex.liquidbounce.event.events.ScreenEvent -import net.ccbluex.liquidbounce.event.events.TransferOrigin +import net.ccbluex.liquidbounce.event.events.* import net.ccbluex.liquidbounce.event.handler import net.ccbluex.liquidbounce.event.tickHandler import net.ccbluex.liquidbounce.features.module.Category import net.ccbluex.liquidbounce.features.module.ClientModule +import net.ccbluex.liquidbounce.features.module.modules.movement.ModuleInventoryMove.Behaviour.NORMAL +import net.ccbluex.liquidbounce.features.module.modules.movement.ModuleInventoryMove.Behaviour.SAFE import net.ccbluex.liquidbounce.utils.client.Chronometer import net.ccbluex.liquidbounce.utils.client.PacketQueueManager import net.ccbluex.liquidbounce.utils.client.formatAsTime import net.ccbluex.liquidbounce.utils.client.notification +import net.ccbluex.liquidbounce.utils.inventory.InventoryManager.isInventoryOpenServerSide +import net.ccbluex.liquidbounce.utils.inventory.closeInventorySilently +import net.ccbluex.liquidbounce.utils.inventory.isInInventoryScreen import net.minecraft.client.gui.screen.ChatScreen import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen import net.minecraft.client.gui.screen.ingame.HandledScreen +import net.minecraft.client.gui.screen.ingame.InventoryScreen import net.minecraft.client.option.KeyBinding import net.minecraft.item.ItemGroups import net.minecraft.network.packet.c2s.play.* +import org.lwjgl.glfw.GLFW.GLFW_RELEASE /** * InventoryMove module @@ -46,9 +51,24 @@ import net.minecraft.network.packet.c2s.play.* object ModuleInventoryMove : ClientModule("InventoryMove", Category.MOVEMENT) { - private val undetectable by boolean("Undetectable", false) + private val behavior by enumChoice("Behavior", NORMAL) + + enum class Behaviour(override val choiceName: String) : NamedChoice { + NORMAL("Normal"), + SAFE("Safe"), // disable clicks while moving + UNDETECTABLE("Undetectable"), // stop in inventory + } + private val passthroughSneak by boolean("PassthroughSneak", false) + // states of movement keys, using mc.options..isPressed doesn't work for some reason + private val movementKeys = mc.options.run { + arrayOf(forwardKey, leftKey, backKey, rightKey, jumpKey, sneakKey).associateWith { false }.toMutableMap() + } + + val cancelClicks + get() = behavior == SAFE && movementKeys.any { (key, pressed) -> pressed && shouldHandleInputs(key) } + object Blink : ToggleableConfigurable(this,"Blink", false) { /** @@ -99,7 +119,9 @@ object ModuleInventoryMove : ClientModule("InventoryMove", Category.MOVEMENT) { } fun shouldHandleInputs(keyBinding: KeyBinding): Boolean { - if (!running || mc.currentScreen is ChatScreen || isInCreativeSearchField()) { + val screen = mc.currentScreen ?: return true + + if (!running || screen is ChatScreen || isInCreativeSearchField()) { return false } @@ -108,7 +130,19 @@ object ModuleInventoryMove : ClientModule("InventoryMove", Category.MOVEMENT) { } // If we are in a handled screen, we should handle the inputs only if the undetectable option is not enabled - return !undetectable || mc.currentScreen !is HandledScreen<*> + return behavior == NORMAL || screen !is HandledScreen<*> + || behavior == SAFE && screen is InventoryScreen + } + + @Suppress("unused") + val keyHandler = handler { event -> + val key = movementKeys.keys.find { it.matchesKey(event.keyCode, event.scanCode) } ?: return@handler + val pressed = shouldHandleInputs(key) && event.action != GLFW_RELEASE + movementKeys[key] = pressed + + if (behavior == SAFE && isInInventoryScreen && isInventoryOpenServerSide && pressed) { + closeInventorySilently() + } } /** diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/player/ModuleFastExp.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/player/ModuleFastExp.kt index 0e9e4d829c1..b37bc275db6 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/player/ModuleFastExp.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/player/ModuleFastExp.kt @@ -67,7 +67,7 @@ object ModuleFastExp : ClientModule( @Suppress("unused") private val repeatable = tickHandler { val slot = getSlot() - if (slot == null || player.isDead || InventoryManager.isInventoryOpenServerSide || isRepaired(slot)) { + if (slot == null || player.isDead || InventoryManager.isInventoryOpen || isRepaired(slot)) { return@tickHandler } diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/player/autobuff/Buff.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/player/autobuff/Buff.kt index 6ba5150c7e5..b85dcb5e44a 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/player/autobuff/Buff.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/player/autobuff/Buff.kt @@ -37,7 +37,7 @@ abstract class Buff( ) : ToggleableConfigurable(ModuleAutoBuff, name, true) { internal open val passesRequirements: Boolean - get() = enabled && !InventoryManager.isInventoryOpenServerSide + get() = enabled && !InventoryManager.isInventoryOpen /** * Try to run feature if possible, otherwise return false diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/utils/aiming/RotationsUtil.kt b/src/main/kotlin/net/ccbluex/liquidbounce/utils/aiming/RotationsUtil.kt index 39ff3461f5e..9a5547590ba 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/utils/aiming/RotationsUtil.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/utils/aiming/RotationsUtil.kt @@ -266,7 +266,7 @@ object RotationManager : EventListener { } // Prevents any rotation changes when inventory is opened - val allowedRotation = ((!InventoryManager.isInventoryOpenServerSide && + val allowedRotation = ((!InventoryManager.isInventoryOpen && mc.currentScreen !is GenericContainerScreen) || !workingAimPlan.considerInventory) && allowedToUpdate() if (allowedRotation) { diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/utils/inventory/InventoryExtensions.kt b/src/main/kotlin/net/ccbluex/liquidbounce/utils/inventory/InventoryExtensions.kt index ff68c1f9de6..7c74e6896b9 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/utils/inventory/InventoryExtensions.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/utils/inventory/InventoryExtensions.kt @@ -36,7 +36,7 @@ val isInContainerScreen val canCloseMainInventory get() = !isInInventoryScreen && mc.player?.currentScreenHandler?.isPlayerInventory == true - && InventoryManager.isInventoryOpenServerSide + && InventoryManager.isInventoryOpen val GenericContainerScreen?.syncId get() = this?.screenHandler?.syncId ?: 0 diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/utils/inventory/InventoryManager.kt b/src/main/kotlin/net/ccbluex/liquidbounce/utils/inventory/InventoryManager.kt index 261217fc891..737b3c63caa 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/utils/inventory/InventoryManager.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/utils/inventory/InventoryManager.kt @@ -55,8 +55,16 @@ import kotlin.random.Random */ object InventoryManager : EventListener { + val isInventoryOpen + get() = isInInventoryScreen || isInventoryOpenServerSide + var isInventoryOpenServerSide = false - internal set + internal set(value) { + if (!field && value) { + inventoryOpened() + } + field = value + } var lastClickedSlot: Int = 0 private set @@ -137,13 +145,13 @@ object InventoryManager : EventListener { // Handle player inventory open requirements val requiresPlayerInventory = action.requiresPlayerInventoryOpen() if (requiresPlayerInventory) { - if (!isInventoryOpenServerSide) { + if (!isInventoryOpen) { openInventorySilently() waitTicks(constraints.startDelay.random()) } } else if (canCloseMainInventory) { // When all scheduled actions are done, we can close the inventory - if (isInventoryOpenServerSide) { + if (isInventoryOpen) { waitTicks(constraints.closeDelay.random()) closeInventorySilently() } @@ -181,7 +189,7 @@ object InventoryManager : EventListener { } while (schedule.isNotEmpty()) // When all scheduled actions are done, we can close the inventory - if (isInventoryOpenServerSide && canCloseMainInventory) { + if (isInventoryOpen && canCloseMainInventory) { waitTicks(maximumCloseDelay) closeInventorySilently() } @@ -233,7 +241,10 @@ object InventoryManager : EventListener { } } - val screenHandler = handler(priority = EventPriorityConvention.READ_FINAL_STATE) { event -> + @Suppress("unused") + private val screenHandler = handler( + priority = EventPriorityConvention.READ_FINAL_STATE + ) { event -> val screen = event.screen if (event.isCancelled) { @@ -242,14 +253,11 @@ object InventoryManager : EventListener { if (screen is InventoryScreen || screen is GenericContainerScreen) { inventoryOpened() - - if (screen is InventoryScreen) { - isInventoryOpenServerSide = true - } } } - val handleWorldChange = handler { + @Suppress("unused") + private val handleWorldChange = handler { isInventoryOpenServerSide = false } @@ -382,7 +390,7 @@ data class UseInventoryAction( ) : InventoryAction { override fun canPerformAction(inventoryConstraints: InventoryConstraints) = - !InventoryManager.isInventoryOpenServerSide && !isInContainerScreen && !isInInventoryScreen + !InventoryManager.isInventoryOpen && !isInContainerScreen && !isInInventoryScreen override fun performAction(): Boolean { useHotbarSlotOrOffhand(hotbarItemSlot) diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/utils/inventory/InventoryUtils.kt b/src/main/kotlin/net/ccbluex/liquidbounce/utils/inventory/InventoryUtils.kt index 299e3060f06..7865a210d8b 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/utils/inventory/InventoryUtils.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/utils/inventory/InventoryUtils.kt @@ -90,7 +90,7 @@ class PlayerInventoryConstraints : InventoryConstraints() { override fun passesRequirements(action: InventoryAction) = super.passesRequirements(action) && (!action.requiresPlayerInventoryOpen() || !requiresOpenInvenotory || - InventoryManager.isInventoryOpenServerSide) + InventoryManager.isInventoryOpen) } diff --git a/src/main/resources/liquidbounce.mixins.json b/src/main/resources/liquidbounce.mixins.json index cc94b011e8e..586b4410fa9 100644 --- a/src/main/resources/liquidbounce.mixins.json +++ b/src/main/resources/liquidbounce.mixins.json @@ -43,6 +43,7 @@ "minecraft.gui.MixinChatHud", "minecraft.gui.MixinChatInputSuggestor", "minecraft.gui.MixinChatScreen", + "minecraft.gui.MixinHandledScreen", "minecraft.gui.MixinInGameHud", "minecraft.gui.MixinPlayerListHud", "minecraft.gui.MixinScoreboard",