diff --git a/build.gradle b/build.gradle index abf2f2403e7..a25feb42670 100644 --- a/build.gradle +++ b/build.gradle @@ -66,6 +66,10 @@ dependencies { include 'org.apache.httpcomponents:httpmime:4.3.3' + // https://mvnrepository.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core + include 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4' + + include fileTree(include: ["*.jar"], dir: "libs") } diff --git a/src/main/java/net/ccbluex/liquidbounce/LiquidBounce.kt b/src/main/java/net/ccbluex/liquidbounce/LiquidBounce.kt index cfebd5e73c9..54b7b0856d4 100644 --- a/src/main/java/net/ccbluex/liquidbounce/LiquidBounce.kt +++ b/src/main/java/net/ccbluex/liquidbounce/LiquidBounce.kt @@ -42,10 +42,11 @@ import net.ccbluex.liquidbounce.utils.Background import net.ccbluex.liquidbounce.utils.ClassUtils.hasForge import net.ccbluex.liquidbounce.utils.ClientUtils.LOGGER import net.ccbluex.liquidbounce.utils.ClientUtils.disableFastRender -import net.ccbluex.liquidbounce.utils.InventoryUtils +import net.ccbluex.liquidbounce.utils.MovementUtils import net.ccbluex.liquidbounce.utils.RotationUtils -import net.ccbluex.liquidbounce.utils.TickedActions +import net.ccbluex.liquidbounce.utils.inventory.InventoryUtils import net.ccbluex.liquidbounce.utils.render.MiniMapRegister +import net.ccbluex.liquidbounce.utils.timing.TickedActions import kotlin.concurrent.thread object LiquidBounce { @@ -102,13 +103,14 @@ object LiquidBounce { registerListener(InventoryUtils) registerListener(MiniMapRegister) registerListener(TickedActions) + registerListener(MovementUtils) // Load client fonts loadFonts() // Load settings loadSettings(false) { - LOGGER.info("Successfully loaded ${it.count()} settings.") + LOGGER.info("Successfully loaded ${it.size} settings.") } // Register commands @@ -174,7 +176,7 @@ object LiquidBounce { // Refresh cape service CapeService.refreshCapeCarriers { - LOGGER.info("Successfully loaded ${CapeService.capeCarriers.count()} cape carriers.") + LOGGER.info("Successfully loaded ${CapeService.capeCarriers.size} cape carriers.") } // Load background diff --git a/src/main/java/net/ccbluex/liquidbounce/cape/CapeService.kt b/src/main/java/net/ccbluex/liquidbounce/cape/CapeService.kt index a16bdbb31ce..d61d73c8760 100644 --- a/src/main/java/net/ccbluex/liquidbounce/cape/CapeService.kt +++ b/src/main/java/net/ccbluex/liquidbounce/cape/CapeService.kt @@ -6,7 +6,6 @@ package net.ccbluex.liquidbounce.cape import com.google.gson.JsonParser -import net.ccbluex.liquidbounce.api.ClientApi.API_ENDPOINT import net.ccbluex.liquidbounce.event.EventTarget import net.ccbluex.liquidbounce.event.Listenable import net.ccbluex.liquidbounce.event.SessionEvent @@ -14,7 +13,7 @@ import net.ccbluex.liquidbounce.utils.ClientUtils.LOGGER import net.ccbluex.liquidbounce.utils.MinecraftInstance import net.ccbluex.liquidbounce.utils.login.UserUtils import net.ccbluex.liquidbounce.utils.misc.HttpUtils.get -import net.ccbluex.liquidbounce.utils.timer.MSTimer +import net.ccbluex.liquidbounce.utils.timing.MSTimer import org.apache.http.HttpHeaders import org.apache.http.HttpStatus import org.apache.http.client.methods.HttpDelete diff --git a/src/main/java/net/ccbluex/liquidbounce/event/EventManager.kt b/src/main/java/net/ccbluex/liquidbounce/event/EventManager.kt index 927a9b6ebb5..4087b86f8dc 100644 --- a/src/main/java/net/ccbluex/liquidbounce/event/EventManager.kt +++ b/src/main/java/net/ccbluex/liquidbounce/event/EventManager.kt @@ -23,7 +23,7 @@ object EventManager { val invokableEventTargets = registry.getOrDefault(eventClass, ArrayList()) invokableEventTargets += EventHook(listener, method, eventTarget) - registry[eventClass] = invokableEventTargets + registry[eventClass] = invokableEventTargets.sortedByDescending { it.priority }.toMutableList() } } @@ -33,10 +33,8 @@ object EventManager { * @param listenable for unregister */ fun unregisterListener(listenable: Listenable) = - registry.forEach { (key, targets) -> + registry.forEach { (_, targets) -> targets.removeIf { it.eventClass == listenable } - - registry[key] = targets } /** @@ -47,7 +45,7 @@ object EventManager { fun callEvent(event: Event) { val targets = registry[event.javaClass] ?: return - for (invokableEventTarget in targets.sortedByDescending { it.priority }) { + for (invokableEventTarget in targets) { try { if (!invokableEventTarget.eventClass.handleEvents() && !invokableEventTarget.isIgnoreCondition) continue diff --git a/src/main/java/net/ccbluex/liquidbounce/features/command/commands/GiveCommand.kt b/src/main/java/net/ccbluex/liquidbounce/features/command/commands/GiveCommand.kt index 28bf04dfcb7..500adc62181 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/command/commands/GiveCommand.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/command/commands/GiveCommand.kt @@ -7,7 +7,7 @@ package net.ccbluex.liquidbounce.features.command.commands import net.ccbluex.liquidbounce.features.command.Command import net.ccbluex.liquidbounce.utils.PacketUtils.sendPacket -import net.ccbluex.liquidbounce.utils.item.ItemUtils +import net.ccbluex.liquidbounce.utils.inventory.ItemUtils import net.ccbluex.liquidbounce.utils.misc.StringUtils import net.minecraft.item.Item import net.minecraft.network.play.client.C10PacketCreativeInventoryAction @@ -32,23 +32,7 @@ class GiveCommand : Command("give", "item", "i", "get") { return } - var emptySlot = -1 - - for (i in 36..44) { - if (thePlayer.inventoryContainer.getSlot(i).stack == null) { - emptySlot = i - break - } - } - - if (emptySlot == -1) { - for (i in 9..44) { - if (thePlayer.inventoryContainer.getSlot(i).stack == null) { - emptySlot = i - break - } - } - } + val emptySlot = thePlayer.inventory.firstEmptyStack if (emptySlot != -1) { sendPacket(C10PacketCreativeInventoryAction(emptySlot, itemStack)) diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/Module.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/Module.kt index a21495569c5..f245bfd020d 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/Module.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/Module.kt @@ -13,11 +13,14 @@ import net.ccbluex.liquidbounce.lang.translation import net.ccbluex.liquidbounce.ui.client.hud.HUD.addNotification import net.ccbluex.liquidbounce.ui.client.hud.element.elements.Arraylist import net.ccbluex.liquidbounce.ui.client.hud.element.elements.Notification +import net.ccbluex.liquidbounce.utils.CoroutineUtils.waitUntil import net.ccbluex.liquidbounce.utils.MinecraftInstance import net.ccbluex.liquidbounce.utils.extensions.toLowerCamelCase import net.ccbluex.liquidbounce.utils.misc.RandomUtils.nextFloat +import net.ccbluex.liquidbounce.utils.timing.TickedActions import net.ccbluex.liquidbounce.value.Value import net.minecraft.client.audio.PositionedSoundRecord +import net.minecraft.item.ItemStack import net.minecraft.util.ResourceLocation import org.lwjgl.input.Keyboard @@ -68,6 +71,8 @@ open class Module @JvmOverloads constructor( // Call toggle onToggle(value) + TickScheduler.clear() + // Play sound and add notification if (!isStarting) { mc.soundHandler.playSound(PositionedSoundRecord.create(ResourceLocation("random.click"), 1F)) @@ -143,4 +148,51 @@ open class Module @JvmOverloads constructor( * Events should be handled when module is enabled */ override fun handleEvents() = state + + internal object TickScheduler { + lateinit var instance: Module + + internal fun schedule(id: Int, allowDuplicates: Boolean = false, action: () -> Unit) = + TickedActions.schedule(id, instance, allowDuplicates, action) + + internal fun scheduleClick(slot: Int, button: Int, mode: Int, allowDuplicates: Boolean = false, windowId: Int = mc.thePlayer.openContainer.windowId, action: ((ItemStack?) -> Unit)? = null) = + schedule(slot, allowDuplicates) { + val newStack = mc.playerController.windowClick(windowId, slot, button, mode, mc.thePlayer) + action?.invoke(newStack) + } + + operator fun plusAssign(action: () -> Unit) { + schedule(-1, true, action) + } + + // Schedule actions to be executed in following ticks, one each tick + // Thread is frozen until all actions were executed (suitable for coroutines) + internal fun scheduleAndSuspend(vararg actions: () -> Unit) = + actions.forEach { + this += it + waitUntil(::isEmpty) + } + + internal fun scheduleAndSuspend(id: Int = -1, allowDuplicates: Boolean = true, action: () -> Unit) { + schedule(id, allowDuplicates, action) + waitUntil(::isEmpty) + } + + internal fun isScheduled(id: Int) = TickedActions.isScheduled(id, instance) + + // Checks if id click is scheduled: if (id in TickScheduler) + operator fun contains(id: Int) = isScheduled(id) + + internal fun clear() = TickedActions.clear(instance) + + internal val size + get() = TickedActions.size(instance) + + internal fun isEmpty() = TickedActions.isEmpty(instance) + + } + + init { + TickScheduler.instance = this + } } \ No newline at end of file diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/ModuleCategory.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/ModuleCategory.kt index fda596d4d42..9b9afd56bbc 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/ModuleCategory.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/ModuleCategory.kt @@ -14,6 +14,7 @@ enum class ModuleCategory(val displayName: String) { WORLD("World"), MISC("Misc"), EXPLOIT("Exploit"), - FUN("Fun") + FUN("Fun"), + BETA("Beta") } \ No newline at end of file diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/ModuleManager.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/ModuleManager.kt index 01bba630982..6a692f837cb 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/ModuleManager.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/ModuleManager.kt @@ -11,6 +11,9 @@ import net.ccbluex.liquidbounce.event.EventTarget import net.ccbluex.liquidbounce.event.KeyEvent import net.ccbluex.liquidbounce.event.Listenable import net.ccbluex.liquidbounce.features.command.CommandManager.registerCommand +import net.ccbluex.liquidbounce.features.module.modules.beta.CoroutineArmorer +import net.ccbluex.liquidbounce.features.module.modules.beta.CoroutineCleaner +import net.ccbluex.liquidbounce.features.module.modules.beta.CoroutineStealer import net.ccbluex.liquidbounce.features.module.modules.combat.* import net.ccbluex.liquidbounce.features.module.modules.exploit.* import net.ccbluex.liquidbounce.features.module.modules.`fun`.Derp @@ -22,6 +25,7 @@ import net.ccbluex.liquidbounce.features.module.modules.render.* import net.ccbluex.liquidbounce.features.module.modules.world.* import net.ccbluex.liquidbounce.features.module.modules.world.Timer import net.ccbluex.liquidbounce.utils.ClientUtils.LOGGER +import net.ccbluex.liquidbounce.utils.inventory.InventoryManager import java.util.* @@ -99,6 +103,9 @@ object ModuleManager : Listenable { Clip, ComponentOnHover, ConsoleSpammer, + CoroutineArmorer, + CoroutineCleaner, + CoroutineStealer, Criticals, Damage, Derp, @@ -202,6 +209,8 @@ object ModuleManager : Listenable { Zoot ) + InventoryManager.startCoroutine() + LOGGER.info("[ModuleManager] Loaded ${modules.size} modules.") } diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/beta/CoroutineArmorer.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/beta/CoroutineArmorer.kt new file mode 100644 index 00000000000..ebc5f587ef0 --- /dev/null +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/beta/CoroutineArmorer.kt @@ -0,0 +1,246 @@ +@file:Suppress("ControlFlowWithEmptyBody") + +package net.ccbluex.liquidbounce.features.module.modules.beta + +import kotlinx.coroutines.delay +import net.ccbluex.liquidbounce.features.module.Module +import net.ccbluex.liquidbounce.features.module.ModuleCategory +import net.ccbluex.liquidbounce.utils.CoroutineUtils.waitUntil +import net.ccbluex.liquidbounce.utils.PacketUtils.sendPackets +import net.ccbluex.liquidbounce.utils.inventory.CoroutineArmorComparator.getBestArmorSet +import net.ccbluex.liquidbounce.utils.inventory.InventoryManager +import net.ccbluex.liquidbounce.utils.inventory.InventoryManager.canClickInventory +import net.ccbluex.liquidbounce.utils.inventory.InventoryManager.hasScheduled +import net.ccbluex.liquidbounce.utils.inventory.InventoryUtils.isFirstInventoryClick +import net.ccbluex.liquidbounce.utils.inventory.InventoryUtils.serverOpenInventory +import net.ccbluex.liquidbounce.utils.inventory.InventoryUtils.serverSlot +import net.ccbluex.liquidbounce.utils.inventory.hasItemAgePassed +import net.ccbluex.liquidbounce.utils.timing.TimeUtils.randomDelay +import net.ccbluex.liquidbounce.value.BoolValue +import net.ccbluex.liquidbounce.value.IntegerValue +import net.minecraft.client.gui.inventory.GuiInventory +import net.minecraft.entity.EntityLiving.getArmorPosition +import net.minecraft.item.ItemStack +import net.minecraft.network.play.client.C08PacketPlayerBlockPlacement +import net.minecraft.network.play.client.C09PacketHeldItemChange + +// TODO: What happens if you get an armor while spoofing selected slot while scaffolding? +// hotbar option should check whether serverSlot == currentItem or smth like that +object CoroutineArmorer: Module("CoroutineArmorer", ModuleCategory.BETA) { + private val maxDelay: Int by object : IntegerValue("MaxDelay", 50, 0..500) { + override fun onChange(oldValue: Int, newValue: Int) = newValue.coerceAtLeast(minDelay) + } + private val minDelay by object : IntegerValue("MinDelay", 50, 0..500) { + override fun onChange(oldValue: Int, newValue: Int) = newValue.coerceAtMost(maxDelay) + + override fun isSupported() = maxDelay > 0 + } + private val minItemAge by IntegerValue("MinItemAge", 0, 0..2000) + + private val invOpen by InventoryManager.invOpenValue + private val simulateInventory by InventoryManager.simulateInventoryValue + + private val autoClose by InventoryManager.autoCloseValue + private val startDelay by InventoryManager.startDelayValue + private val closeDelay by InventoryManager.closeDelayValue + + // When swapping armor pieces, it grabs the better one, drags and swaps it with equipped one and drops the equipped one (no time of having no armor piece equipped) + // Has to make more clicks, works slower + private val smartSwap by BoolValue("SmartSwap", true) + + private val noMove by InventoryManager.noMoveValue + private val noMoveAir by InventoryManager.noMoveAirValue + private val noMoveGround by InventoryManager.noMoveGroundValue + + val hotbar by BoolValue("Hotbar", true) + // Sacrifices 1 tick speed for complete undetectability, needed to bypass Vulcan + private val delayedSlotSwitch by BoolValue("DelayedSlotSwitch", true) { hotbar } + // Prevents AutoArmor from hotbar equipping while any screen is open + val onlyWhenNoScreen by BoolValue("OnlyWhenNoScreen", false) { hotbar } + + suspend fun equipFromHotbar() { + if (!shouldOperate(onlyHotbar = true)) + return + + val thePlayer = mc.thePlayer ?: return + + var hasClickedHotbar = false + + for (hotbarIndex in 0..8) { + if (!shouldOperate(onlyHotbar = true)) + return + + // Don't right-click to equip items while inventory is open when value onlyWhenNoScreen is enabled + if (onlyWhenNoScreen && serverOpenInventory) + break + + val stacks = thePlayer.openContainer.inventory + + val stack = stacks.getOrNull(hotbarIndex + 36) ?: continue + + val bestArmorSet = getBestArmorSet(stacks) ?: return + + if (stack !in bestArmorSet) + continue + + val armorPosition = getArmorPosition(stack) - 1 + + // If armor slot isn't occupied, right click to equip + if (thePlayer.getCurrentArmor(armorPosition) == null) { + hasClickedHotbar = true + + val equippingAction = { + // Switch selected hotbar slot, right click to equip + sendPackets( + C09PacketHeldItemChange(hotbarIndex), + C08PacketPlayerBlockPlacement(stack) + ) + + // Instantly update inventory on client-side to prevent repetitive clicking because of ping + thePlayer.inventory.armorInventory[armorPosition] = stack + thePlayer.inventory.mainInventory[hotbarIndex] = null + } + + if (delayedSlotSwitch) + // Schedule for the following tick and wait for them to be sent + TickScheduler.scheduleAndSuspend(equippingAction) + else + // Schedule all possible hotbar clicks for the following tick (doesn't suspend the loop) + TickScheduler += equippingAction + } + } + + // Not really needed to bypass + delay(randomDelay(minDelay, maxDelay).toLong()) + + waitUntil(TickScheduler::isEmpty) + + // Sync selected slot next tick + if (hasClickedHotbar) + TickScheduler += { serverSlot = thePlayer.inventory.currentItem } + } + + suspend fun equipFromInventory() { + if (!shouldOperate()) + return + + val thePlayer = mc.thePlayer ?: return + + for (armorType in 0..3) { + if (!shouldOperate()) + return + + val stacks = thePlayer.openContainer.inventory + + val armorSet = getBestArmorSet(stacks) ?: continue + + // Shouldn't iterate over armor set because after waiting for nomove and invopen it could be outdated + val (index, stack) = armorSet[armorType] ?: continue + + // Index is null when searching in chests for already equipped armor to prevent any accidental impossible interactions + index ?: continue + + // Check if best item is already scheduled to be equipped next tick + if (index in TickScheduler || (armorType + 5) in TickScheduler) + continue + + if (!stack.hasItemAgePassed(minItemAge)) + continue + + when (stacks[armorType + 5]) { + // Best armor is already equipped + stack -> continue + + // No item is equipped in armor slot + null -> + // Equip by shift-clicking + click(index, 0, 1) + + else -> { + if (smartSwap) { + // Player has worse armor equipped, drag the best armor, swap it with currently equipped armor and drop the bad armor + // This way there is no time of having no armor (but more clicks) + + // Grab better armor + click(index, 0, 0) + + // Swap it with currently equipped armor + click(armorType + 5, 0, 0) + + // Drop worse item by dragging and dropping it + click(-999, 0, 0) + } else { + // Normal version + + // Drop worse armor + click(armorType + 5, 0, 4) + + // Equip better armor + click(index, 0, 1) + } + } + } + } + + // Wait till all scheduled clicks were sent + waitUntil(TickScheduler::isEmpty) + } + + fun equipFromHotbarInChest(hotbarIndex: Int?, stack: ItemStack) { + // AutoArmor is disabled or prohibited from equipping while in containers + if (hotbarIndex == null || !state || onlyWhenNoScreen) + return + + sendPackets( + C09PacketHeldItemChange(hotbarIndex), + C08PacketPlayerBlockPlacement(stack) + ) + } + + private suspend fun shouldOperate(onlyHotbar: Boolean = false): Boolean { + while (true) { + if (!state) + return false + + if (mc.playerController?.currentGameType?.isSurvivalOrAdventure != true) + return false + + // It is impossible to equip armor when a container is open; only try to equip by right-clicking from hotbar (if onlyWhenNoScreen is disabled) + if (mc.thePlayer?.openContainer?.windowId != 0 && (!onlyHotbar || onlyWhenNoScreen)) + return false + + // Player doesn't need to have inventory open or not to move, when equipping from hotbar + if (onlyHotbar) + return hotbar + + if (invOpen && mc.currentScreen !is GuiInventory) + return false + + // Wait till NoMove check isn't violated + if (canClickInventory(closeWhenViolating = true)) + return true + + // If NoMove is violated, wait a tick and check again + // If there is no delay, very weird things happen: https://www.guilded.gg/CCBlueX/groups/1dgpg8Jz/channels/034be45e-1b72-4d5a-bee7-d6ba52ba1657/chat?messageId=94d314cd-6dc4-41c7-84a7-212c8ea1cc2a + delay(50) + } + } + + private suspend fun click(slot: Int, button: Int, mode: Int, allowDuplicates: Boolean = false) { + if (simulateInventory || invOpen) + serverOpenInventory = true + + if (isFirstInventoryClick) { + // Have to set this manually, because it would delay all clicks until a first scheduled click was sent + isFirstInventoryClick = false + + delay(startDelay.toLong()) + } + + TickScheduler.scheduleClick(slot, button, mode, allowDuplicates) + + hasScheduled = true + + delay(randomDelay(minDelay, maxDelay).toLong()) + } +} \ No newline at end of file diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/beta/CoroutineCleaner.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/beta/CoroutineCleaner.kt new file mode 100644 index 00000000000..85a7e3a577e --- /dev/null +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/beta/CoroutineCleaner.kt @@ -0,0 +1,578 @@ +@file:Suppress("ControlFlowWithEmptyBody") + +package net.ccbluex.liquidbounce.features.module.modules.beta + +import kotlinx.coroutines.delay +import net.ccbluex.liquidbounce.features.module.Module +import net.ccbluex.liquidbounce.features.module.ModuleCategory +import net.ccbluex.liquidbounce.utils.ClientUtils.displayChatMessage +import net.ccbluex.liquidbounce.utils.CoroutineUtils.waitUntil +import net.ccbluex.liquidbounce.utils.block.BlockUtils.isFullBlock +import net.ccbluex.liquidbounce.utils.extensions.shuffled +import net.ccbluex.liquidbounce.utils.inventory.* +import net.ccbluex.liquidbounce.utils.inventory.CoroutineArmorComparator.getBestArmorSet +import net.ccbluex.liquidbounce.utils.inventory.InventoryManager.canClickInventory +import net.ccbluex.liquidbounce.utils.inventory.InventoryManager.hasScheduled +import net.ccbluex.liquidbounce.utils.inventory.InventoryUtils.isFirstInventoryClick +import net.ccbluex.liquidbounce.utils.inventory.InventoryUtils.serverOpenInventory +import net.ccbluex.liquidbounce.utils.timing.TimeUtils.randomDelay +import net.ccbluex.liquidbounce.value.BoolValue +import net.ccbluex.liquidbounce.value.IntegerValue +import net.ccbluex.liquidbounce.value.ListValue +import net.minecraft.block.BlockContainer +import net.minecraft.block.BlockFalling +import net.minecraft.block.BlockWorkbench +import net.minecraft.client.gui.inventory.GuiInventory +import net.minecraft.enchantment.Enchantment +import net.minecraft.entity.item.EntityItem +import net.minecraft.init.Blocks +import net.minecraft.init.Items +import net.minecraft.item.* +import net.minecraft.potion.Potion + +object CoroutineCleaner: Module("CoroutineCleaner", ModuleCategory.BETA) { + private val drop by BoolValue("Drop", true) + val sort by BoolValue("Sort", true) + + private val maxDelay: Int by object : IntegerValue("MaxDelay", 50, 0..500) { + override fun onChange(oldValue: Int, newValue: Int) = newValue.coerceAtLeast(minDelay) + } + private val minDelay by object : IntegerValue("MinDelay", 50, 0..500) { + override fun isSupported() = maxDelay > 0 + + override fun onChange(oldValue: Int, newValue: Int) = newValue.coerceAtMost(maxDelay) + } + private val minItemAge by IntegerValue("MinItemAge", 0, 0..2000) + + private val limitStackCounts by BoolValue("LimitStackCounts", true) + private val maxBlockStacks by IntegerValue("MaxBlockStacks", 5, 0..36) { limitStackCounts } + private val maxFoodStacks by IntegerValue("MaxFoodStacks", 5, 0..36) { limitStackCounts } + // TODO: max potion, vehicle, throwable, bucket stacks, ..., or limit buckets by default + + private val mergeStacks by BoolValue("MergeStacks", true) + + private val invOpen by InventoryManager.invOpenValue + private val simulateInventory by InventoryManager.simulateInventoryValue + + private val autoClose by InventoryManager.autoCloseValue + private val startDelay by InventoryManager.startDelayValue + private val closeDelay by InventoryManager.closeDelayValue + + private val noMove by InventoryManager.noMoveValue + private val noMoveAir by InventoryManager.noMoveAirValue + private val noMoveGround by InventoryManager.noMoveGroundValue + + private val randomSlot by BoolValue("RandomSlot", false) + private val ignoreVehicles by BoolValue("IgnoreVehicles", false) + + private val onlyGoodPotions by BoolValue("OnlyGoodPotions", false) + + val highlightUseful by BoolValue("HighlightUseful", true) + + private val slot1Value = SortValue("Slot1", "Sword") + private val slot2Value = SortValue("Slot2", "Bow") + private val slot3Value = SortValue("Slot3", "Pickaxe") + private val slot4Value = SortValue("Slot4", "Axe") + private val slot5Value = SortValue("Slot5", "Shovel") + private val slot6Value = SortValue("Slot6", "Food") + private val slot7Value = SortValue("Slot7", "Throwable") + private val slot8Value = SortValue("Slot8", "Block") + private val slot9Value = SortValue("Slot9", "Block") + + // Compact multiple small stacks into one to free up inventory space + suspend fun compactStacks() { + if (!mergeStacks || !shouldOperate()) + return + + val thePlayer = mc.thePlayer ?: return + + // Loop multiple times until no clicks were scheduled + while (true) { + if (!shouldOperate()) return + + val stacks = thePlayer.openContainer.inventory + + // List of stack indices with different types to be compacted by double-clicking + val indicesToDoubleClick = stacks.withIndex() + .groupBy { it.value?.item } + .mapNotNull { (item, groupedStacks) -> + item ?: return@mapNotNull null + + val sortedStacks = groupedStacks + // Only try to merge non-full stacks, without limiting stack counts in isStackUseful + .filter { it.value.stackSize != it.value.maxStackSize && isStackUseful(it.value, stacks, ignoreLimits = true) } + // Prioritise stacks that are lower in inventory + .sortedByDescending { it.index } + // Prioritise stacks that are sorted + .sortedByDescending { canBeSortedTo(it.index, it.value?.item, stacks.size) } + + // Return first stack that can be merged with a different stack of the same type else null + sortedStacks.firstOrNull { (_, clickedStack) -> + sortedStacks.any { (_, mergedStack) -> + clickedStack != mergedStack + && clickedStack.stackSize + mergedStack.stackSize <= clickedStack.maxStackSize + } + }?.index + } + + var hasMerged = false + + for (index in indicesToDoubleClick) { + if (!shouldOperate()) return + + if (index in TickScheduler) continue + + hasMerged = true + + // TODO: Perhaps add a slider for merge delay? + + click(index, 0, 0, coerceTo = 100) + + click(index, 0, 6, allowDuplicates = true, coerceTo = 100) + + click(index, 0, 0, allowDuplicates = true, coerceTo = 100) + } + + // No stacks to be merged were found + if (!hasMerged) break + + // This part isn't fully instant because of the complex vanilla merging behaviour, stack size changes and so on + // Waits a tick to see how the stacks got merged + waitUntil(TickScheduler::isEmpty) + } + } + + // Sort hotbar (with useful items without even dropping bad items first) + suspend fun sortHotbar() { + if (!sort || !shouldOperate()) return + + val thePlayer = mc.thePlayer ?: return + + for ((hotbarIndex, value) in SORTING_VALUES.withIndex().shuffled(randomSlot)) { + // Check if slot has a valid sorting target + val isRightType = SORTING_TARGETS[value.get()] ?: continue + + // Stop if player violates invopen or nomove checks + if (!shouldOperate()) return + + val stacks = thePlayer.openContainer.inventory + + val index = hotbarIndex + 36 + + val stack = stacks.getOrNull(index) + val item = stack?.item + + // Slot is already sorted + if (isRightType(item) && isStackUseful(stack, stacks)) + continue + + // Search for best item to sort + for ((otherIndex, otherStack) in stacks.withIndex()) { + if (otherIndex in TickScheduler) + continue + + if (!otherStack.hasItemAgePassed(minItemAge)) + continue + + val otherItem = otherStack?.item + + // Check if an item is the correct type, isn't bad and isn't already sorted + if (isRightType(otherItem) && isStackUseful(otherStack, stacks) && !canBeSortedTo(otherIndex, otherItem, stacks.size)) { + click(otherIndex, hotbarIndex, 2) + break + } + } + } + + waitUntil(TickScheduler::isEmpty) + } + + // Drop bad items to free up inventory space + suspend fun dropGarbage() { + if (!drop || !shouldOperate()) return + + val thePlayer = mc.thePlayer ?: return + + for (index in thePlayer.openContainer.inventorySlots.indices.shuffled(randomSlot)) { + // Stop if player violates invopen or nomove checks + if (!shouldOperate()) return + + if (index in TickScheduler) + continue + + val stacks = thePlayer.openContainer.inventory + val stack = stacks.getOrNull(index) ?: continue + + if (!stack.hasItemAgePassed(minItemAge)) + continue + + // If stack isn't useful, drop it + if (!isStackUseful(stack, stacks)) + click(index, 1, 4) + } + + waitUntil(TickScheduler::isEmpty) + } + + private suspend fun shouldOperate(): Boolean { + while (true) { + if (!state) + return false + + if (mc.playerController?.currentGameType?.isSurvivalOrAdventure != true) + return false + + if (mc.thePlayer?.openContainer?.windowId != 0) + return false + + if (invOpen && mc.currentScreen !is GuiInventory) + return false + + // Wait till NoMove check isn't violated + if (canClickInventory(closeWhenViolating = true)) + return true + + // If NoMove is violated, wait a tick and check again + // If there is no delay, very weird things happen: https://www.guilded.gg/CCBlueX/groups/1dgpg8Jz/channels/034be45e-1b72-4d5a-bee7-d6ba52ba1657/chat?messageId=94d314cd-6dc4-41c7-84a7-212c8ea1cc2a + delay(50) + } + } + + suspend fun click(slot: Int, button: Int, mode: Int, allowDuplicates: Boolean = false, coerceTo: Int = Int.MAX_VALUE) { + if (simulateInventory || invOpen) + serverOpenInventory = true + + if (isFirstInventoryClick) { + // Have to set this manually, because it would delay all clicks until a first scheduled click was sent + isFirstInventoryClick = false + + delay(startDelay.toLong()) + } + + TickScheduler.scheduleClick(slot, button, mode, allowDuplicates) + + hasScheduled = true + + delay(randomDelay(minDelay, maxDelay).coerceAtMost(coerceTo).toLong()) + } + + private val SORTING_VALUES = arrayOf( + slot1Value, slot2Value, slot3Value, slot4Value, slot5Value, slot6Value, slot7Value, slot8Value, slot9Value + ) + + private class SortValue(name: String, value: String) : ListValue(name, SORTING_KEYS, value) { + override fun isSupported() = sort + override fun onChanged(oldValue: String, newValue: String) = + SORTING_VALUES.forEach { value -> + if (value != this && newValue == value.get() && SORTING_TARGETS.keys.indexOf(value.get()) < 5) { + value.set(oldValue) + value.openList = true + + displayChatMessage("§8[§9§lInventoryCleaner§8] §3Value §a${value.name}§3 was changed to §a$oldValue§3 to prevent conflicts.") + } + } + } + + fun canBeSortedTo(index: Int, item: Item?, stacksSize: Int? = null): Boolean { + if (!sort) return false + + // If stacksSize argument is passed, check if index is a hotbar slot + val index = + if (stacksSize != null) index.toHotbarIndex(stacksSize) ?: return false + else index + + return SORTING_TARGETS[SORTING_VALUES.getOrNull(index)?.get()]?.invoke(item) ?: false + } + + fun Int.toHotbarIndex(stacksSize: Int): Int? { + val parsed = this - stacksSize + 9 + + return if (parsed in 0..8) parsed else null + } + + fun isStackUseful(stack: ItemStack?, stacks: List, entityStacksMap: Map? = null, ignoreLimits: Boolean = false): Boolean { + val item = stack?.item ?: return false + + return when (item) { + in ITEMS_WHITELIST -> true + + // TODO: Limit max bucket count, vehicle count + is ItemEnderPearl, is ItemEnchantedBook, is ItemBucket, is ItemBed -> true + + // TODO: Simplify + is ItemFood -> isUsefulFood(stack, stacks, entityStacksMap, ignoreLimits) + is ItemBlock -> isUsefulBlock(stack, stacks, entityStacksMap, ignoreLimits) + + is ItemArmor, is ItemTool, is ItemSword, is ItemBow -> isUsefulEquipment(stack, stacks, entityStacksMap) + + is ItemBoat, is ItemMinecart -> !ignoreVehicles + + is ItemPotion -> isUsefulPotion(stack) + + + else -> false + } + } + + private fun isUsefulPotion(stack: ItemStack?): Boolean { + val item = stack?.item ?: return false + + if (item is ItemPotion) { + val isSplash = stack.isSplashPotion() + val isHarmful = item.getEffects(stack)?.any { it.potionID in NEGATIVE_EFFECT_IDS } ?: return false + + // Only keep helpful potions and, if 'onlyGoodPotions' is disabled, also splash harmful potions + return !isHarmful || (!onlyGoodPotions && isSplash) + } + + return false + } + + private fun isUsefulEquipment(stack: ItemStack?, stacks: List, entityStacksMap: Map? = null): Boolean { + val item = stack?.item ?: return false + + return when (item) { + is ItemArmor -> getBestArmorSet(stacks, entityStacksMap)?.contains(stack) ?: true + + is ItemTool -> { + val blockType = when (item) { + is ItemAxe -> Blocks.log + is ItemPickaxe -> Blocks.stone + else -> Blocks.dirt + } + + return hasBestParameters(stack, stacks, entityStacksMap) { + it.item.getStrVsBlock(it, blockType) * it.durability + } + } + + is ItemSword -> + hasBestParameters(stack, stacks, entityStacksMap) { + it.attackDamage.toFloat() + } + + is ItemBow -> + hasBestParameters(stack, stacks, entityStacksMap) { + it.getEnchantmentLevel(Enchantment.power).toFloat() + } + + else -> false + } + } + + private fun isUsefulFood(stack: ItemStack?, stacks: List, entityStacksMap: Map?, ignoreLimits: Boolean): Boolean { + val item = stack?.item ?: return false + + if (item !is ItemFood) return false + + if (ignoreLimits || !limitStackCounts) return true + + val stackSaturation = item.getSaturationModifier(stack) * stack.stackSize + + val index = stacks.indexOf(stack) + + val isSorted = canBeSortedTo(index, item, stacks.size) + + val stacksToIterate = stacks.toMutableList() + + var distanceSqToItem = .0 + + if (!entityStacksMap.isNullOrEmpty()) { + distanceSqToItem = mc.thePlayer.getDistanceSqToEntity(entityStacksMap[stack] ?: return false) + stacksToIterate += entityStacksMap.keys + } + + val betterCount = stacksToIterate.withIndex().count { (otherIndex, otherStack) -> + if (stack == otherStack) + return@count false + + val otherItem = otherStack?.item ?: return@count false + + if (otherItem !is ItemFood) + return@count false + + // Items dropped on ground should have index -1 + val otherIndex = if (otherIndex > stacks.lastIndex) -1 else otherIndex + + val otherStackSaturation = otherItem.getSaturationModifier(otherStack) * otherStack.stackSize + + when (otherStackSaturation.compareTo(stackSaturation)) { + // Other stack has bigger saturation sum + 1 -> true + // Both stacks are equally good + 0 -> { + // Only true when both items are dropped on ground + if (index == otherIndex) { + val otherEntityItem = entityStacksMap?.get(otherStack) ?: return@count false + + // If other item is closer, count it as better + distanceSqToItem > mc.thePlayer.getDistanceSqToEntity(otherEntityItem) + } else { + val isOtherSorted = canBeSortedTo(otherIndex, otherItem, stacks.size) + + // Count as better alternative only when compared stack isn't sorted and the other is sorted, or has higher index + !isSorted && (isOtherSorted || otherIndex > index) + } + } + else -> false + } + } + + return betterCount < maxFoodStacks + } + + private fun isUsefulBlock(stack: ItemStack?, stacks: List, entityStacksMap: Map?, ignoreLimits: Boolean): Boolean { + if (!isSuitableBlock(stack)) return false + + if (ignoreLimits || !limitStackCounts) return true + + val index = stacks.indexOf(stack) + + val isSorted = canBeSortedTo(index, stack!!.item, stacks.size) + + val iteratedStacks = stacks.toMutableList() + + var distanceSqToItem = .0 + + if (!entityStacksMap.isNullOrEmpty()) { + distanceSqToItem = mc.thePlayer.getDistanceSqToEntity(entityStacksMap[stack] ?: return false) + iteratedStacks += entityStacksMap.keys + } + + val betterCount = iteratedStacks.withIndex().count { (otherIndex, otherStack) -> + if (!isSuitableBlock(otherStack) || otherStack == stack) + return@count false + + // Items dropped on ground should have index -1 + val otherIndex = if (otherIndex > stacks.lastIndex) -1 else otherIndex + + when (otherStack!!.stackSize.compareTo(stack.stackSize)) { + // Found a stack that has higher size + 1 -> true + // Both stacks are equally good + 0 -> { + // Only true when both items are dropped on ground + if (index == otherIndex) { + val otherEntityItem = entityStacksMap?.get(otherStack) ?: return@count false + + // If other item is closer, count it as better + distanceSqToItem > mc.thePlayer.getDistanceSqToEntity(otherEntityItem) + } else { + val isOtherSorted = canBeSortedTo(otherIndex, otherStack.item, stacks.size) + + // Count as better alternative only when compared stack isn't sorted and the other is sorted, or has higher index + !isSorted && (isOtherSorted || otherIndex > index) + } + } + else -> false + } + } + + return betterCount < maxBlockStacks + } + + private fun hasBestParameters(stack: ItemStack?, stacks: List, entityStacksMap: Map? = null, parameters: (ItemStack) -> Float): Boolean { + val item = stack?.item ?: return false + + val index = stacks.indexOf(stack) + + val currentStats = parameters(stack) + + val isSorted = canBeSortedTo(index, item, stacks.size) + + val iteratedStacks = stacks.toMutableList() + + var distanceSqToItem = .0 + + if (!entityStacksMap.isNullOrEmpty()) { + distanceSqToItem = mc.thePlayer.getDistanceSqToEntity(entityStacksMap[stack] ?: return false) + iteratedStacks += entityStacksMap.keys + } + + iteratedStacks.forEachIndexed { otherIndex, otherStack -> + val otherItem = otherStack?.item ?: return@forEachIndexed + + // Check if items aren't the same instance but are the same type + if (stack == otherStack || item.javaClass != otherItem.javaClass) + return@forEachIndexed + + // Items dropped on ground should have index -1 + val otherIndex = if (otherIndex > stacks.lastIndex) -1 else otherIndex + + val otherStats = parameters(otherStack) + + val isOtherSorted = canBeSortedTo(otherIndex, otherItem, stacks.size) + + // Compare stats one by one + when (otherStats.compareTo(currentStats)) { + // Other item had better base stat, compared item isn't the best + 1 -> return false + // Both have the same base stat, compare sum of their enchantment levels + 0 -> when (otherStack.enchantmentSum.compareTo(stack.enchantmentSum)) { + 1 -> return false + // Same base stat, sum of enchantment levels, compare durability * unbreaking + 0 -> when (otherStack.totalDurability.compareTo(stack.totalDurability)) { + 1 -> return false + // Both items are pretty much equally good, sorted item wins over not sorted, otherwise the one with higher index + 0 -> { + // Only true when both items are dropped on ground, if other item is closer, compared one isn't the best + if (index == otherIndex) { + val otherEntityItem = entityStacksMap?.get(otherStack) ?: return@forEachIndexed + when (distanceSqToItem.compareTo(mc.thePlayer.getDistanceSqToEntity(otherEntityItem))) { + 1 -> return false + // Both items are exactly far, pretty much impossible + 0 -> return true + } + } else if (!isSorted && (isOtherSorted || otherIndex > index)) + return false + } + } + } + } + } + + return true + } + + @Suppress("DEPRECATION") + fun isSuitableBlock(stack: ItemStack?): Boolean { + val item = stack?.item ?: return false + + if (item is ItemBlock) { + val block = item.block + + return isFullBlock(block) && !block.hasTileEntity() + && block !is BlockWorkbench && block !is BlockContainer && block !is BlockFalling + } + + return false + } +} + +private val ITEMS_WHITELIST = arrayOf( + Items.arrow, Items.diamond, Items.iron_ingot, Items.gold_ingot, Items.stick, Items.egg, Items.snowball +) + +private val NEGATIVE_EFFECT_IDS = arrayOf( + Potion.moveSlowdown.id, Potion.digSlowdown.id, Potion.harm.id, Potion.confusion.id, Potion.blindness.id, + Potion.hunger.id, Potion.weakness.id, Potion.poison.id, Potion.wither.id, +) + +private val SORTING_TARGETS: Map Boolean)?> = mapOf( + "Sword" to { it is ItemSword }, + "Bow" to { it is ItemBow }, + "Pickaxe" to { it is ItemPickaxe }, + "Axe" to { it is ItemAxe }, + "Shovel" to { it is ItemSpade }, + "Food" to { it is ItemFood }, + "Block" to { it is ItemBlock }, + "Water" to { it == Items.water_bucket || it == Items.bucket }, + "Fire" to { it is ItemFlintAndSteel || it == Items.lava_bucket || it == Items.bucket }, + "Gapple" to { it is ItemAppleGold }, + "Pearl" to { it is ItemEnderPearl }, + "Potion" to { it is ItemPotion }, + "Throwable" to { it is ItemEgg || it is ItemSnowball }, + "Ignore" to null +) + +private val SORTING_KEYS = SORTING_TARGETS.keys.toTypedArray() \ No newline at end of file diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/beta/CoroutineStealer.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/beta/CoroutineStealer.kt new file mode 100644 index 00000000000..c9d797dff51 --- /dev/null +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/beta/CoroutineStealer.kt @@ -0,0 +1,311 @@ +/* + * LiquidBounce Hacked Client + * A free open source mixin-based injection hacked client for Minecraft using Minecraft Forge. + * https://github.com/CCBlueX/LiquidBounce/ + */ + +package net.ccbluex.liquidbounce.features.module.modules.beta + +import kotlinx.coroutines.delay +import net.ccbluex.liquidbounce.event.EventTarget +import net.ccbluex.liquidbounce.event.PacketEvent +import net.ccbluex.liquidbounce.event.Render2DEvent +import net.ccbluex.liquidbounce.features.module.Module +import net.ccbluex.liquidbounce.features.module.ModuleCategory +import net.ccbluex.liquidbounce.features.module.modules.beta.CoroutineCleaner.canBeSortedTo +import net.ccbluex.liquidbounce.features.module.modules.beta.CoroutineCleaner.isStackUseful +import net.ccbluex.liquidbounce.utils.CoroutineUtils.waitUntil +import net.ccbluex.liquidbounce.utils.extensions.component1 +import net.ccbluex.liquidbounce.utils.extensions.component2 +import net.ccbluex.liquidbounce.utils.extensions.shuffled +import net.ccbluex.liquidbounce.utils.inventory.InventoryManager +import net.ccbluex.liquidbounce.utils.inventory.InventoryManager.canClickInventory +import net.ccbluex.liquidbounce.utils.inventory.InventoryUtils.hasSpaceInInventory +import net.ccbluex.liquidbounce.utils.inventory.InventoryUtils.serverSlot +import net.ccbluex.liquidbounce.utils.render.RenderUtils.drawRect +import net.ccbluex.liquidbounce.utils.timing.TimeUtils.randomDelay +import net.ccbluex.liquidbounce.value.BoolValue +import net.ccbluex.liquidbounce.value.IntegerValue +import net.minecraft.client.gui.ScaledResolution +import net.minecraft.client.gui.inventory.GuiChest +import net.minecraft.entity.EntityLiving.getArmorPosition +import net.minecraft.init.Blocks +import net.minecraft.init.Items +import net.minecraft.item.ItemArmor +import net.minecraft.item.ItemStack +import net.minecraft.network.play.client.C0DPacketCloseWindow +import net.minecraft.network.play.server.S2DPacketOpenWindow +import net.minecraft.network.play.server.S2EPacketCloseWindow +import net.minecraft.network.play.server.S30PacketWindowItems +import java.awt.Color + +object CoroutineStealer : Module("CoroutineStealer", ModuleCategory.BETA) { + + private val maxDelay: Int by object : IntegerValue("MaxDelay", 50, 0..500) { + override fun onChange(oldValue: Int, newValue: Int) = newValue.coerceAtLeast(minDelay) + } + private val minDelay by object : IntegerValue("MinDelay", 50, 0..500) { + override fun isSupported() = maxDelay > 0 + + override fun onChange(oldValue: Int, newValue: Int) = newValue.coerceAtMost(maxDelay) + } + + private val startDelay by IntegerValue("StartDelay", 50, 0..500) + private val closeDelay by IntegerValue("CloseDelay", 50, 0..500) + + private val noMove by InventoryManager.noMoveValue + private val noMoveAir by InventoryManager.noMoveAirValue + private val noMoveGround by InventoryManager.noMoveGroundValue + + private val noCompass by BoolValue("NoCompass", true) + + private val chestTitle by BoolValue("ChestTitle", true) + + private val randomSlot by BoolValue("RandomSlot", true) + + private val progressBar by BoolValue("ProgressBar", true) + + private var progress: Float? = null + set(value) { + field = value?.coerceIn(0f, 1f) + + if (field == null) + easingProgress = 0f + } + + private var easingProgress = 0f + + private var receivedId: Int? = null + + private var stacks = emptyList() + + private suspend fun shouldOperate(): Boolean { + while (true) { + if (!state) + return false + + if (mc.playerController?.currentGameType?.isSurvivalOrAdventure != true) + return false + + if (mc.currentScreen !is GuiChest) + return false + + if (mc.thePlayer?.openContainer?.windowId != receivedId) + return false + + // Wait till NoMove check isn't violated + if (canClickInventory()) + return true + + // If NoMove is violated, wait a tick and check again + // If there is no delay, very weird things happen: https://www.guilded.gg/CCBlueX/groups/1dgpg8Jz/channels/034be45e-1b72-4d5a-bee7-d6ba52ba1657/chat?messageId=94d314cd-6dc4-41c7-84a7-212c8ea1cc2a + delay(50) + } + } + + suspend fun stealFromChest() { + if (!state) + return + + val thePlayer = mc.thePlayer ?: return + + val screen = mc.currentScreen ?: return + + if (screen !is GuiChest || !shouldOperate()) + return + + // Check if player isn't holding a compass and browsing navigation gui + if (noCompass && thePlayer.heldItem?.item == Items.compass) + return + + // Check if chest isn't a custom gui + if (chestTitle && Blocks.chest.localizedName !in (screen.lowerChestInventory ?: return).name) + return + + progress = 0f + + delay(startDelay.toLong()) + + // Go through the chest multiple times, till there are no useful items anymore + while (true) { + if (!shouldOperate()) + return + + val sortBlacklist = BooleanArray(9) + + val usefulItems = stacks.dropLast(36) + .mapIndexedNotNull { index, stack -> + stack ?: return@mapIndexedNotNull null + + if (index in TickScheduler || (CoroutineCleaner.state && !isStackUseful(stack, stacks))) + return@mapIndexedNotNull null + + var sortableTo: Int? = null + + if (CoroutineCleaner.state && CoroutineCleaner.sort) { + for (hotbarIndex in 0..8) { + if (sortBlacklist[hotbarIndex]) + continue + + if (!canBeSortedTo(hotbarIndex, stack.item)) + continue + + val hotbarStack = stacks.getOrNull(stacks.size - 9 + hotbarIndex) + + if (!isStackUseful(hotbarStack, stacks)) { + sortableTo = hotbarIndex + sortBlacklist[hotbarIndex] = true + break + } + } + } + + Triple(index, stack, sortableTo) + }.shuffled(randomSlot) + + // Prioritize items that can be sorted (so that as many items could be instantly sorted) + // Explanation: If a non-sortable item goes before the sortable, it gets shift-clicked to some hotbar slot, which is then occupied with useful item that shouldn't get swapped by sorting... + // (sortable items would have to be normally shift-clicked afterward) + .sortedByDescending { it.third != null } + .toMutableList() + + // TODO: Might block sortable items from getting instantly sorted, armor having lower priority might be better afterwards... + // TODO: Or it could wait for armor to get equipped... Or it could expect which slot the armor would go to... + // Also prioritize armor pieces so that they could be equipped while in chest, from hotbar. + if (CoroutineArmorer.state && CoroutineArmorer.hotbar && !CoroutineArmorer.onlyWhenNoScreen) + usefulItems.sortByDescending { it.second.item is ItemArmor } + + var hasTaken = false + + run scheduler@ { + usefulItems.forEachIndexed { index, (slot, stack, sortableTo) -> + if (!shouldOperate()) { + TickScheduler += { serverSlot = thePlayer.inventory.currentItem } + return + } + + if (!hasSpaceInInventory()) { + // Check if the chest has any empty slot + val hasChestEmptySlot = stacks.dropLast(36).any { it == null } + + // If the item is supposed to be sorted, put the stack that occupies its slot into chest, else find first garbage item + var garbageIndex = sortableTo?.plus(stacks.size - 9) + + if (garbageIndex == null) { + val garbageInventoryIndex = stacks.takeLast(36) + .indexOfLast { CoroutineCleaner.state && !isStackUseful(it, stacks) } + + if (garbageInventoryIndex != -1) + // Convert index in player's inventory to index of the whole open container + garbageIndex = stacks.size - 36 + garbageInventoryIndex + } + + garbageIndex ?: return@scheduler + + // Shift + left-click bad item from inventory into chest to free up space + if (hasChestEmptySlot) TickScheduler.scheduleClick(garbageIndex, 0, 1) + // Drop bad item from inventory when there is no space + else TickScheduler.scheduleClick(garbageIndex, 1, 4) + + delay(randomDelay(minDelay, maxDelay).toLong()) + } + + hasTaken = true + + // TODO: If armor can be equipped from hotbar, but all slots are occupied, sort it to slot with useless item or not sorted item and equip (if the item was useful or sorted, sort it back in the end) + // this is kinda finished ^ + + // TODO: might schedule clicks that exceed inventory space at low delays, it will notice that it doesn't have space in inventory next tick, when the scheduled click gets executed + // If target is sortable to a hotbar slot, steal and sort it at the same time, else shift + left-click + TickScheduler.scheduleClick(slot, sortableTo ?: 0, if (sortableTo != null) 2 else 1) { + progress = (index + 1) / usefulItems.size.toFloat() + + // Try to equip armor piece from hotbar 1 tick after stealing it + run equipArmor@ { + val item = stack.item + + if (item !is ItemArmor || thePlayer.inventory.armorInventory[getArmorPosition(stack) - 1] != null) + return@equipArmor + + TickScheduler += { + val hotbarStacks = thePlayer.inventory.mainInventory.take(9) + + // Can't get index of stack instance, because it is different even from the one returned from windowClick() + val newIndex = hotbarStacks.indexOfFirst { it?.getIsItemStackEqual(stack) ?: false } + + if (newIndex != -1) + CoroutineArmorer.equipFromHotbarInChest(newIndex, stack) + } + } + } + + delay(randomDelay(minDelay, maxDelay).toLong()) + } + } + + // If no clicks were sent in the last loop stop searching + if (!hasTaken) { + progress = 1f + delay(closeDelay.toLong()) + + TickScheduler += { serverSlot = thePlayer.inventory.currentItem } + break + } + + // Wait till all scheduled clicks were sent + waitUntil(TickScheduler::isEmpty) + + // Before closing the chest, check all items once more, whether server hadn't cancelled some of the actions. + stacks = thePlayer.openContainer.inventory + } + + // Wait before the chest gets closed (if it gets closed out of tick loop it could throw npe) + TickScheduler.scheduleAndSuspend { + thePlayer.closeScreen() + progress = null + } + } + + // Progress bar + @EventTarget + fun onRender2D(event: Render2DEvent) { + if (!progressBar || mc.currentScreen !is GuiChest) + return + + val progress = progress ?: return + + val (scaledWidth, scaledHeight) = ScaledResolution(mc) + + val minX = scaledWidth * 0.3f + val maxX = scaledWidth * 0.7f + val minY = scaledHeight * 0.75f + val maxY = minY + 10f + + easingProgress += (progress - easingProgress) / 6f * event.partialTicks + + drawRect(minX - 2, minY - 2, maxX + 2, maxY + 2, Color(200, 200, 200).rgb) + drawRect(minX, minY, maxX, maxY, Color(50, 50, 50).rgb) + drawRect(minX, minY, minX + (maxX - minX) * easingProgress, maxY, Color.HSBtoRGB(easingProgress / 5, 1f, 1f) or 0xFF0000) + } + + @EventTarget + fun onPacket(event: PacketEvent) { + val packet = event.packet + + when (packet) { + is C0DPacketCloseWindow, is S2DPacketOpenWindow, is S2EPacketCloseWindow -> { + receivedId = null + progress = null + } + is S30PacketWindowItems -> { + // Chests never have windowId 0 + if (packet.func_148911_c() == 0) + return + + receivedId = packet.func_148911_c() + + stacks = packet.itemStacks.toList() + } + } + } +} \ No newline at end of file diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/Aimbot.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/Aimbot.kt index 8b657c58021..02ff0c98147 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/Aimbot.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/Aimbot.kt @@ -18,7 +18,7 @@ import net.ccbluex.liquidbounce.utils.RotationUtils.limitAngleChange import net.ccbluex.liquidbounce.utils.RotationUtils.searchCenter import net.ccbluex.liquidbounce.utils.RotationUtils.toRotation import net.ccbluex.liquidbounce.utils.extensions.* -import net.ccbluex.liquidbounce.utils.timer.MSTimer +import net.ccbluex.liquidbounce.utils.timing.MSTimer import net.ccbluex.liquidbounce.value.BoolValue import net.ccbluex.liquidbounce.value.FloatValue import java.util.* diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/AutoArmor.java b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/AutoArmor.java index e1c8c871fff..81ecf800e45 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/AutoArmor.java +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/AutoArmor.java @@ -10,11 +10,11 @@ import net.ccbluex.liquidbounce.features.module.Module; import net.ccbluex.liquidbounce.features.module.ModuleCategory; import net.ccbluex.liquidbounce.injection.implementations.IMixinItemStack; -import net.ccbluex.liquidbounce.utils.InventoryUtils; import net.ccbluex.liquidbounce.utils.MovementUtils; -import net.ccbluex.liquidbounce.utils.item.ArmorComparator; -import net.ccbluex.liquidbounce.utils.item.ArmorPiece; -import net.ccbluex.liquidbounce.utils.timer.TimeUtils; +import net.ccbluex.liquidbounce.utils.inventory.ArmorComparator; +import net.ccbluex.liquidbounce.utils.inventory.ArmorPiece; +import net.ccbluex.liquidbounce.utils.inventory.InventoryUtils; +import net.ccbluex.liquidbounce.utils.timing.TimeUtils; import net.ccbluex.liquidbounce.value.BoolValue; import net.ccbluex.liquidbounce.value.IntegerValue; import net.minecraft.client.gui.inventory.GuiInventory; @@ -32,7 +32,7 @@ import java.util.stream.IntStream; import static net.ccbluex.liquidbounce.utils.PacketUtils.sendPacket; -import static net.ccbluex.liquidbounce.utils.item.ItemUtilsKt.isEmpty; +import static net.ccbluex.liquidbounce.utils.inventory.ItemUtilsKt.isEmpty; import static net.minecraft.network.play.client.C16PacketClientStatus.EnumState.OPEN_INVENTORY_ACHIEVEMENT; public class AutoArmor extends Module { diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/AutoClicker.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/AutoClicker.kt index d0b9b2ad99a..1df0a760858 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/AutoClicker.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/AutoClicker.kt @@ -13,7 +13,7 @@ import net.ccbluex.liquidbounce.features.module.ModuleCategory import net.ccbluex.liquidbounce.utils.extensions.fixedSensitivityPitch import net.ccbluex.liquidbounce.utils.extensions.fixedSensitivityYaw import net.ccbluex.liquidbounce.utils.misc.RandomUtils.nextFloat -import net.ccbluex.liquidbounce.utils.timer.TimeUtils.randomClickDelay +import net.ccbluex.liquidbounce.utils.timing.TimeUtils.randomClickDelay import net.ccbluex.liquidbounce.value.BoolValue import net.ccbluex.liquidbounce.value.IntegerValue import net.minecraft.client.settings.KeyBinding diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/AutoPot.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/AutoPot.kt index f0ba8b0ae93..2b0f6eea628 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/AutoPot.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/AutoPot.kt @@ -11,15 +11,17 @@ import net.ccbluex.liquidbounce.event.EventTarget import net.ccbluex.liquidbounce.event.MotionEvent import net.ccbluex.liquidbounce.features.module.Module import net.ccbluex.liquidbounce.features.module.ModuleCategory -import net.ccbluex.liquidbounce.utils.InventoryUtils import net.ccbluex.liquidbounce.utils.PacketUtils.sendPacket import net.ccbluex.liquidbounce.utils.PacketUtils.sendPackets import net.ccbluex.liquidbounce.utils.Rotation import net.ccbluex.liquidbounce.utils.RotationUtils.serverRotation import net.ccbluex.liquidbounce.utils.RotationUtils.setTargetRotation +import net.ccbluex.liquidbounce.utils.inventory.InventoryUtils +import net.ccbluex.liquidbounce.utils.inventory.InventoryUtils.serverOpenInventory +import net.ccbluex.liquidbounce.utils.inventory.isSplashPotion import net.ccbluex.liquidbounce.utils.misc.FallingPlayer import net.ccbluex.liquidbounce.utils.misc.RandomUtils.nextFloat -import net.ccbluex.liquidbounce.utils.timer.MSTimer +import net.ccbluex.liquidbounce.utils.timing.MSTimer import net.ccbluex.liquidbounce.value.BoolValue import net.ccbluex.liquidbounce.value.FloatValue import net.ccbluex.liquidbounce.value.IntegerValue @@ -28,9 +30,6 @@ import net.minecraft.client.gui.inventory.GuiInventory import net.minecraft.item.ItemPotion import net.minecraft.network.play.client.C08PacketPlayerBlockPlacement import net.minecraft.network.play.client.C09PacketHeldItemChange -import net.minecraft.network.play.client.C0DPacketCloseWindow -import net.minecraft.network.play.client.C16PacketClientStatus -import net.minecraft.network.play.client.C16PacketClientStatus.EnumState.OPEN_INVENTORY_ACHIEVEMENT import net.minecraft.potion.Potion object AutoPot : Module("AutoPot", ModuleCategory.COMBAT) { @@ -59,7 +58,7 @@ object AutoPot : Module("AutoPot", ModuleCategory.COMBAT) { // Hotbar Potion val potionInHotbar = findPotion(36, 45) - if (thePlayer.health <= health && potionInHotbar != -1) { + if (potionInHotbar != null && thePlayer.health <= health) { if (thePlayer.onGround) { when (mode.lowercase()) { "jump" -> thePlayer.jump() @@ -85,20 +84,18 @@ object AutoPot : Module("AutoPot", ModuleCategory.COMBAT) { } // Inventory Potion -> Hotbar Potion - val potionInInventory = findPotion(9, 36) - if (potionInInventory != -1 && InventoryUtils.hasSpaceHotbar()) { + val potionInInventory = findPotion(9, 36) ?: return + if (InventoryUtils.hasSpaceInHotbar()) { if (openInventory && mc.currentScreen !is GuiInventory) return - val openInventory = mc.currentScreen !is GuiInventory && simulateInventory - - if (openInventory) - sendPacket(C16PacketClientStatus(OPEN_INVENTORY_ACHIEVEMENT)) + if (simulateInventory) + serverOpenInventory = true mc.playerController.windowClick(0, potionInInventory, 0, 1, thePlayer) - if (openInventory) - sendPacket(C0DPacketCloseWindow()) + if (simulateInventory && mc.currentScreen !is GuiInventory) + serverOpenInventory = false msTimer.reset() } @@ -122,13 +119,13 @@ object AutoPot : Module("AutoPot", ModuleCategory.COMBAT) { } } - private fun findPotion(startSlot: Int, endSlot: Int): Int { + private fun findPotion(startSlot: Int, endSlot: Int): Int? { val thePlayer = mc.thePlayer for (i in startSlot until endSlot) { val stack = thePlayer.inventoryContainer.getSlot(i).stack - if (stack == null || stack.item !is ItemPotion || !ItemPotion.isSplash(stack.metadata)) + if (stack == null || stack.item !is ItemPotion || !stack.isSplashPotion()) continue val itemPotion = stack.item as ItemPotion @@ -143,7 +140,7 @@ object AutoPot : Module("AutoPot", ModuleCategory.COMBAT) { return i } - return -1 + return null } override val tag diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/AutoRod.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/AutoRod.kt index f5b61cd4a4d..6f3a8eb305f 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/AutoRod.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/AutoRod.kt @@ -6,7 +6,7 @@ import net.ccbluex.liquidbounce.features.module.Module import net.ccbluex.liquidbounce.features.module.ModuleCategory import net.ccbluex.liquidbounce.utils.EntityUtils.isSelected import net.ccbluex.liquidbounce.utils.RaycastUtils -import net.ccbluex.liquidbounce.utils.timer.MSTimer +import net.ccbluex.liquidbounce.utils.timing.MSTimer import net.ccbluex.liquidbounce.value.BoolValue import net.ccbluex.liquidbounce.value.IntegerValue import net.minecraft.init.Items diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/AutoSoup.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/AutoSoup.kt index f9357cb3961..30136376cf8 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/AutoSoup.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/AutoSoup.kt @@ -9,19 +9,22 @@ import net.ccbluex.liquidbounce.event.EventTarget import net.ccbluex.liquidbounce.event.UpdateEvent import net.ccbluex.liquidbounce.features.module.Module import net.ccbluex.liquidbounce.features.module.ModuleCategory -import net.ccbluex.liquidbounce.utils.InventoryUtils import net.ccbluex.liquidbounce.utils.PacketUtils.sendPacket import net.ccbluex.liquidbounce.utils.PacketUtils.sendPackets -import net.ccbluex.liquidbounce.utils.timer.MSTimer +import net.ccbluex.liquidbounce.utils.inventory.InventoryUtils +import net.ccbluex.liquidbounce.utils.inventory.InventoryUtils.serverOpenInventory +import net.ccbluex.liquidbounce.utils.inventory.InventoryUtils.serverSlot +import net.ccbluex.liquidbounce.utils.timing.MSTimer import net.ccbluex.liquidbounce.value.BoolValue import net.ccbluex.liquidbounce.value.FloatValue import net.ccbluex.liquidbounce.value.IntegerValue import net.ccbluex.liquidbounce.value.ListValue import net.minecraft.client.gui.inventory.GuiInventory import net.minecraft.init.Items -import net.minecraft.network.play.client.* +import net.minecraft.network.play.client.C07PacketPlayerDigging import net.minecraft.network.play.client.C07PacketPlayerDigging.Action.DROP_ITEM -import net.minecraft.network.play.client.C16PacketClientStatus.EnumState.OPEN_INVENTORY_ACHIEVEMENT +import net.minecraft.network.play.client.C08PacketPlayerBlockPlacement +import net.minecraft.network.play.client.C09PacketHeldItemChange import net.minecraft.util.BlockPos import net.minecraft.util.EnumFacing @@ -56,7 +59,7 @@ object AutoSoup : Module("AutoSoup", ModuleCategory.COMBAT) { if (bowl == "Drop") sendPacket(C07PacketPlayerDigging(DROP_ITEM, BlockPos.ORIGIN, EnumFacing.DOWN)) - sendPacket(C09PacketHeldItemChange(mc.thePlayer.inventory.currentItem)) + serverSlot = thePlayer.inventory.currentItem timer.reset() return } @@ -81,10 +84,8 @@ object AutoSoup : Module("AutoSoup", ModuleCategory.COMBAT) { } if (bowlMovable) { - val openInventory = mc.currentScreen !is GuiInventory && simulateInventory - - if (openInventory) - sendPacket(C16PacketClientStatus(OPEN_INVENTORY_ACHIEVEMENT)) + if (simulateInventory) + serverOpenInventory = true mc.playerController.windowClick(0, bowlInHotbar, 0, 1, thePlayer) } @@ -92,18 +93,17 @@ object AutoSoup : Module("AutoSoup", ModuleCategory.COMBAT) { val soupInInventory = InventoryUtils.findItem(9, 35, Items.mushroom_stew) - if (soupInInventory != null && InventoryUtils.hasSpaceHotbar()) { + if (soupInInventory != null && InventoryUtils.hasSpaceInHotbar()) { if (openInventory && mc.currentScreen !is GuiInventory) return - val openInventory = mc.currentScreen !is GuiInventory && simulateInventory - if (openInventory) - sendPacket(C16PacketClientStatus(OPEN_INVENTORY_ACHIEVEMENT)) + if (simulateInventory) + serverOpenInventory = true mc.playerController.windowClick(0, soupInInventory, 0, 1, thePlayer) - if (openInventory) - sendPacket(C0DPacketCloseWindow()) + if (simulateInventory && mc.currentScreen !is GuiInventory) + serverOpenInventory = false timer.reset() } diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/AutoWeapon.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/AutoWeapon.kt index 66a2053f57a..2e27f2c28cf 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/AutoWeapon.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/AutoWeapon.kt @@ -12,14 +12,14 @@ import net.ccbluex.liquidbounce.event.UpdateEvent import net.ccbluex.liquidbounce.features.module.Module import net.ccbluex.liquidbounce.features.module.ModuleCategory import net.ccbluex.liquidbounce.utils.PacketUtils.sendPacket -import net.ccbluex.liquidbounce.utils.item.attackDamage +import net.ccbluex.liquidbounce.utils.inventory.InventoryUtils.serverSlot +import net.ccbluex.liquidbounce.utils.inventory.attackDamage import net.ccbluex.liquidbounce.value.BoolValue import net.ccbluex.liquidbounce.value.IntegerValue import net.minecraft.item.ItemSword import net.minecraft.item.ItemTool import net.minecraft.network.play.client.C02PacketUseEntity import net.minecraft.network.play.client.C02PacketUseEntity.Action.ATTACK -import net.minecraft.network.play.client.C09PacketHeldItemChange object AutoWeapon : Module("AutoWeapon", ModuleCategory.COMBAT) { @@ -37,8 +37,7 @@ object AutoWeapon : Module("AutoWeapon", ModuleCategory.COMBAT) { @EventTarget fun onPacket(event: PacketEvent) { - if (event.packet is C02PacketUseEntity && event.packet.action == ATTACK - && attackEnemy) { + if (event.packet is C02PacketUseEntity && event.packet.action == ATTACK && attackEnemy) { attackEnemy = false // Find the best weapon in hotbar (#Kotlin Style) @@ -52,7 +51,7 @@ object AutoWeapon : Module("AutoWeapon", ModuleCategory.COMBAT) { // Switch to best weapon if (spoof) { - sendPacket(C09PacketHeldItemChange(slot)) + serverSlot = slot ticks = spoofTicks } else { mc.thePlayer.inventory.currentItem = slot @@ -70,7 +69,8 @@ object AutoWeapon : Module("AutoWeapon", ModuleCategory.COMBAT) { // Switch back to old item after some time if (ticks > 0) { if (ticks == 1) - sendPacket(C09PacketHeldItemChange(mc.thePlayer.inventory.currentItem)) + serverSlot = mc.thePlayer.inventory.currentItem + ticks-- } } diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/Criticals.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/Criticals.kt index 89135879915..266805bc0d0 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/Criticals.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/Criticals.kt @@ -15,7 +15,7 @@ import net.ccbluex.liquidbounce.utils.PacketUtils.sendPackets import net.ccbluex.liquidbounce.utils.extensions.component1 import net.ccbluex.liquidbounce.utils.extensions.component2 import net.ccbluex.liquidbounce.utils.extensions.component3 -import net.ccbluex.liquidbounce.utils.timer.MSTimer +import net.ccbluex.liquidbounce.utils.timing.MSTimer import net.ccbluex.liquidbounce.value.IntegerValue import net.ccbluex.liquidbounce.value.ListValue import net.minecraft.entity.EntityLivingBase diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/Ignite.java b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/Ignite.java index fd0490cd3f4..9623724c653 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/Ignite.java +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/Ignite.java @@ -10,10 +10,10 @@ import net.ccbluex.liquidbounce.features.module.Module; import net.ccbluex.liquidbounce.features.module.ModuleCategory; import net.ccbluex.liquidbounce.utils.EntityUtils; -import net.ccbluex.liquidbounce.utils.InventoryUtils; import net.ccbluex.liquidbounce.utils.RotationUtils; import net.ccbluex.liquidbounce.utils.extensions.MathExtensionsKt; -import net.ccbluex.liquidbounce.utils.timer.MSTimer; +import net.ccbluex.liquidbounce.utils.inventory.InventoryUtils; +import net.ccbluex.liquidbounce.utils.timing.MSTimer; import net.ccbluex.liquidbounce.value.BoolValue; import net.minecraft.block.BlockAir; import net.minecraft.client.entity.EntityPlayerSP; @@ -75,7 +75,7 @@ public void onUpdate(final UpdateEvent event) { RotationUtils.INSTANCE.setKeepCurrentRotation(true); - sendPacket(new C09PacketHeldItemChange(fireInHotbar - 36)); + InventoryUtils.INSTANCE.setServerSlot(fireInHotbar - 36); final ItemStack itemStack = mc.thePlayer.inventoryContainer.getSlot(fireInHotbar).getStack(); diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/KillAura.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/KillAura.kt index b14929f3c70..1026c278df6 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/KillAura.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/KillAura.kt @@ -35,18 +35,18 @@ import net.ccbluex.liquidbounce.utils.RotationUtils.setTargetRotation import net.ccbluex.liquidbounce.utils.RotationUtils.targetRotation import net.ccbluex.liquidbounce.utils.RotationUtils.toRotation import net.ccbluex.liquidbounce.utils.extensions.* -import net.ccbluex.liquidbounce.utils.item.ItemUtils.isConsumingItem +import net.ccbluex.liquidbounce.utils.inventory.InventoryUtils.serverOpenInventory +import net.ccbluex.liquidbounce.utils.inventory.ItemUtils.isConsumingItem import net.ccbluex.liquidbounce.utils.misc.RandomUtils.nextFloat import net.ccbluex.liquidbounce.utils.misc.RandomUtils.nextInt import net.ccbluex.liquidbounce.utils.render.RenderUtils.drawPlatform -import net.ccbluex.liquidbounce.utils.timer.MSTimer -import net.ccbluex.liquidbounce.utils.timer.TimeUtils.randomClickDelay +import net.ccbluex.liquidbounce.utils.timing.MSTimer +import net.ccbluex.liquidbounce.utils.timing.TimeUtils.randomClickDelay import net.ccbluex.liquidbounce.value.BoolValue import net.ccbluex.liquidbounce.value.FloatValue import net.ccbluex.liquidbounce.value.IntegerValue import net.ccbluex.liquidbounce.value.ListValue import net.minecraft.client.gui.inventory.GuiContainer -import net.minecraft.client.gui.inventory.GuiInventory import net.minecraft.enchantment.EnchantmentHelper import net.minecraft.entity.Entity import net.minecraft.entity.EntityLivingBase @@ -54,11 +54,12 @@ import net.minecraft.entity.item.EntityArmorStand import net.minecraft.entity.player.EntityPlayer import net.minecraft.item.ItemAxe import net.minecraft.item.ItemSword -import net.minecraft.network.play.client.* +import net.minecraft.network.play.client.C02PacketUseEntity import net.minecraft.network.play.client.C02PacketUseEntity.Action.ATTACK import net.minecraft.network.play.client.C02PacketUseEntity.Action.INTERACT +import net.minecraft.network.play.client.C07PacketPlayerDigging import net.minecraft.network.play.client.C07PacketPlayerDigging.Action.RELEASE_USE_ITEM -import net.minecraft.network.play.client.C16PacketClientStatus.EnumState.OPEN_INVENTORY_ACHIEVEMENT +import net.minecraft.network.play.client.C08PacketPlayerBlockPlacement import net.minecraft.potion.Potion import net.minecraft.util.BlockPos import net.minecraft.util.EnumFacing @@ -444,11 +445,11 @@ object KillAura : Module("KillAura", ModuleCategory.COMBAT, Keyboard.KEY_R) { // Settings val multi = targetMode == "Multi" - val openInventory = aac && mc.currentScreen is GuiInventory + val manipulateInventory = aac && serverOpenInventory val failHit = failRate > 0 && nextInt(endExclusive = 100) <= failRate // Close inventory when open - if (openInventory) sendPacket(C0DPacketCloseWindow()) + if (manipulateInventory) serverOpenInventory = false updateHitable() @@ -489,7 +490,7 @@ object KillAura : Module("KillAura", ModuleCategory.COMBAT, Keyboard.KEY_R) { } // Open inventory - if (openInventory) sendPacket(C16PacketClientStatus(OPEN_INVENTORY_ACHIEVEMENT)) + if (manipulateInventory) serverOpenInventory = true } /** diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/SuperKnockback.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/SuperKnockback.kt index 95c61b18dd4..5c09336988f 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/SuperKnockback.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/SuperKnockback.kt @@ -11,8 +11,8 @@ import net.ccbluex.liquidbounce.features.module.ModuleCategory import net.ccbluex.liquidbounce.utils.MovementUtils.isMoving import net.ccbluex.liquidbounce.utils.PacketUtils.sendPacket import net.ccbluex.liquidbounce.utils.PacketUtils.sendPackets -import net.ccbluex.liquidbounce.utils.timer.MSTimer -import net.ccbluex.liquidbounce.utils.timer.TimeUtils.randomDelay +import net.ccbluex.liquidbounce.utils.timing.MSTimer +import net.ccbluex.liquidbounce.utils.timing.TimeUtils.randomDelay import net.ccbluex.liquidbounce.value.BoolValue import net.ccbluex.liquidbounce.value.IntegerValue import net.ccbluex.liquidbounce.value.ListValue diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/Trigger.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/Trigger.kt index 0cf8bc53064..888ce1a16d6 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/Trigger.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/Trigger.kt @@ -10,7 +10,7 @@ import net.ccbluex.liquidbounce.event.Render3DEvent import net.ccbluex.liquidbounce.features.module.Module import net.ccbluex.liquidbounce.features.module.ModuleCategory import net.ccbluex.liquidbounce.utils.EntityUtils.isSelected -import net.ccbluex.liquidbounce.utils.timer.TimeUtils.randomClickDelay +import net.ccbluex.liquidbounce.utils.timing.TimeUtils.randomClickDelay import net.ccbluex.liquidbounce.value.IntegerValue import net.minecraft.client.settings.KeyBinding diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/Velocity.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/Velocity.kt index 60978c03130..d9a0d2fdf2a 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/Velocity.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/combat/Velocity.kt @@ -16,7 +16,7 @@ import net.ccbluex.liquidbounce.utils.MovementUtils.isOnGround import net.ccbluex.liquidbounce.utils.MovementUtils.speed import net.ccbluex.liquidbounce.utils.extensions.toRadians import net.ccbluex.liquidbounce.utils.misc.RandomUtils.nextInt -import net.ccbluex.liquidbounce.utils.timer.MSTimer +import net.ccbluex.liquidbounce.utils.timing.MSTimer import net.ccbluex.liquidbounce.value.BoolValue import net.ccbluex.liquidbounce.value.FloatValue import net.ccbluex.liquidbounce.value.IntegerValue diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/exploit/ConsoleSpammer.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/exploit/ConsoleSpammer.kt index 72d3bcc356f..6772a8ca56b 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/exploit/ConsoleSpammer.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/exploit/ConsoleSpammer.kt @@ -14,7 +14,7 @@ import net.ccbluex.liquidbounce.features.module.ModuleCategory import net.ccbluex.liquidbounce.utils.PacketUtils.sendPacket import net.ccbluex.liquidbounce.utils.PacketUtils.sendPackets import net.ccbluex.liquidbounce.utils.misc.RandomUtils.nextInt -import net.ccbluex.liquidbounce.utils.timer.MSTimer +import net.ccbluex.liquidbounce.utils.timing.MSTimer import net.ccbluex.liquidbounce.value.IntegerValue import net.ccbluex.liquidbounce.value.ListValue import net.minecraft.entity.player.EnumPlayerModelParts diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/exploit/Phase.java b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/exploit/Phase.java index a51d75b8f07..fbe235245fa 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/exploit/Phase.java +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/exploit/Phase.java @@ -10,7 +10,7 @@ import net.ccbluex.liquidbounce.features.module.ModuleCategory; import net.ccbluex.liquidbounce.utils.MovementUtils; import net.ccbluex.liquidbounce.utils.block.BlockUtils; -import net.ccbluex.liquidbounce.utils.timer.TickTimer; +import net.ccbluex.liquidbounce.utils.timing.TickTimer; import net.ccbluex.liquidbounce.value.ListValue; import net.minecraft.init.Blocks; import net.minecraft.network.Packet; diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/exploit/PingSpoof.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/exploit/PingSpoof.kt index e9df0fea4de..8077c3378e2 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/exploit/PingSpoof.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/exploit/PingSpoof.kt @@ -11,12 +11,12 @@ import net.ccbluex.liquidbounce.event.UpdateEvent import net.ccbluex.liquidbounce.features.module.Module import net.ccbluex.liquidbounce.features.module.ModuleCategory import net.ccbluex.liquidbounce.utils.PacketUtils.sendPacket -import net.ccbluex.liquidbounce.utils.timer.TimeUtils.randomDelay +import net.ccbluex.liquidbounce.utils.timing.TimeUtils.randomDelay import net.ccbluex.liquidbounce.value.IntegerValue import net.minecraft.network.Packet import net.minecraft.network.play.client.C00PacketKeepAlive -import net.minecraft.network.play.client.C16PacketClientStatus import net.minecraft.network.play.client.C0FPacketConfirmTransaction +import net.minecraft.network.play.client.C16PacketClientStatus object PingSpoof : Module("PingSpoof", ModuleCategory.EXPLOIT) { diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/exploit/Plugins.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/exploit/Plugins.kt index 41b9c098ed3..ec1ad04ad76 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/exploit/Plugins.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/exploit/Plugins.kt @@ -12,7 +12,7 @@ import net.ccbluex.liquidbounce.features.module.Module import net.ccbluex.liquidbounce.features.module.ModuleCategory import net.ccbluex.liquidbounce.utils.ClientUtils.displayChatMessage import net.ccbluex.liquidbounce.utils.PacketUtils.sendPacket -import net.ccbluex.liquidbounce.utils.timer.TickTimer +import net.ccbluex.liquidbounce.utils.timing.TickTimer import net.minecraft.network.play.client.C14PacketTabComplete import net.minecraft.network.play.server.S3APacketTabComplete diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/exploit/ServerCrasher.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/exploit/ServerCrasher.kt index 5f094e0e4db..951088adca3 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/exploit/ServerCrasher.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/exploit/ServerCrasher.kt @@ -15,7 +15,7 @@ import net.ccbluex.liquidbounce.utils.extensions.component2 import net.ccbluex.liquidbounce.utils.extensions.component3 import net.ccbluex.liquidbounce.utils.misc.RandomUtils.randomNumber import net.ccbluex.liquidbounce.utils.misc.RandomUtils.randomString -import net.ccbluex.liquidbounce.utils.timer.MSTimer +import net.ccbluex.liquidbounce.utils.timing.MSTimer import net.ccbluex.liquidbounce.value.ListValue import net.minecraft.init.Items import net.minecraft.item.ItemStack @@ -55,24 +55,26 @@ object ServerCrasher : Module("ServerCrasher", ModuleCategory.EXPLOIT) { when (mode.lowercase()) { "aacnew" -> { // Spam positions - for (index in 0..10000) { + repeat(10000) { sendPacket(C04PacketPlayerPosition( - thePlayer.posX + 9412 * index, - thePlayer.entityBoundingBox.minY + 9412 * index, - thePlayer.posZ + 9412 * index, + thePlayer.posX + 9412 * it, + thePlayer.entityBoundingBox.minY + 9412 * it, + thePlayer.posZ + 9412 * it, true )) } } "aacother" -> { // Spam positions - for (index in 0..10000) { - sendPacket(C04PacketPlayerPosition( - thePlayer.posX + 500000 * index, - thePlayer.entityBoundingBox.minY + 500000 * index, - thePlayer.posZ + 500000 * index, + repeat(10000) { + sendPacket( + C04PacketPlayerPosition( + thePlayer.posX + 500000 * it, + thePlayer.entityBoundingBox.minY + 500000 * it, + thePlayer.posZ + 500000 * it, true - )) + ) + ) } } "aacold" -> { diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/exploit/Teleport.java b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/exploit/Teleport.java index c834d9ad1bc..b39ebce8e25 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/exploit/Teleport.java +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/exploit/Teleport.java @@ -14,7 +14,7 @@ import net.ccbluex.liquidbounce.utils.PathUtils; import net.ccbluex.liquidbounce.utils.block.BlockUtils; import net.ccbluex.liquidbounce.utils.render.RenderUtils; -import net.ccbluex.liquidbounce.utils.timer.TickTimer; +import net.ccbluex.liquidbounce.utils.timing.TickTimer; import net.ccbluex.liquidbounce.value.BoolValue; import net.ccbluex.liquidbounce.value.ListValue; import net.minecraft.block.BlockAir; diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/fun/SkinDerp.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/fun/SkinDerp.kt index 12e956a31b3..0b3e70b5684 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/fun/SkinDerp.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/fun/SkinDerp.kt @@ -9,7 +9,7 @@ import net.ccbluex.liquidbounce.event.EventTarget import net.ccbluex.liquidbounce.event.UpdateEvent import net.ccbluex.liquidbounce.features.module.Module import net.ccbluex.liquidbounce.features.module.ModuleCategory -import net.ccbluex.liquidbounce.utils.timer.MSTimer +import net.ccbluex.liquidbounce.utils.timing.MSTimer import net.ccbluex.liquidbounce.value.BoolValue import net.ccbluex.liquidbounce.value.IntegerValue import net.minecraft.entity.player.EnumPlayerModelParts diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/misc/AtAllProvider.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/misc/AtAllProvider.kt index c4eaee55aac..2f2c703de5e 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/misc/AtAllProvider.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/misc/AtAllProvider.kt @@ -10,8 +10,8 @@ import net.ccbluex.liquidbounce.event.PacketEvent import net.ccbluex.liquidbounce.event.UpdateEvent import net.ccbluex.liquidbounce.features.module.Module import net.ccbluex.liquidbounce.features.module.ModuleCategory -import net.ccbluex.liquidbounce.utils.timer.MSTimer -import net.ccbluex.liquidbounce.utils.timer.TimeUtils.randomDelay +import net.ccbluex.liquidbounce.utils.timing.MSTimer +import net.ccbluex.liquidbounce.utils.timing.TimeUtils.randomDelay import net.ccbluex.liquidbounce.value.BoolValue import net.ccbluex.liquidbounce.value.IntegerValue import net.minecraft.network.play.client.C01PacketChatMessage diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/misc/LiquidChat.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/misc/LiquidChat.kt index 13dc1fe0067..785b77b4a50 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/misc/LiquidChat.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/misc/LiquidChat.kt @@ -15,7 +15,7 @@ import net.ccbluex.liquidbounce.features.module.ModuleCategory import net.ccbluex.liquidbounce.utils.ClientUtils.LOGGER import net.ccbluex.liquidbounce.utils.ClientUtils.displayChatMessage import net.ccbluex.liquidbounce.utils.login.UserUtils -import net.ccbluex.liquidbounce.utils.timer.MSTimer +import net.ccbluex.liquidbounce.utils.timing.MSTimer import net.ccbluex.liquidbounce.value.BoolValue import net.minecraft.event.ClickEvent import net.minecraft.util.ChatComponentText diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/misc/Spammer.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/misc/Spammer.kt index 8e80ef2d83f..f37c91ee94d 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/misc/Spammer.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/misc/Spammer.kt @@ -13,8 +13,8 @@ import net.ccbluex.liquidbounce.features.module.ModuleCategory import net.ccbluex.liquidbounce.utils.misc.RandomUtils.nextFloat import net.ccbluex.liquidbounce.utils.misc.RandomUtils.nextInt import net.ccbluex.liquidbounce.utils.misc.RandomUtils.randomString -import net.ccbluex.liquidbounce.utils.timer.MSTimer -import net.ccbluex.liquidbounce.utils.timer.TimeUtils.randomDelay +import net.ccbluex.liquidbounce.utils.timing.MSTimer +import net.ccbluex.liquidbounce.utils.timing.TimeUtils.randomDelay import net.ccbluex.liquidbounce.value.BoolValue import net.ccbluex.liquidbounce.value.IntegerValue import net.ccbluex.liquidbounce.value.TextValue diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/BufferSpeed.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/BufferSpeed.kt index 3ab1a175de5..04db4dcbfd4 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/BufferSpeed.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/BufferSpeed.kt @@ -199,7 +199,7 @@ object BufferSpeed : Module("BufferSpeed", ModuleCategory.MOVEMENT) { if (buffer && speed > 0.2) { speed /= 1.0199999809265137 - strafe(speed.toFloat()) + strafe() } } else { speed = 0.0 diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/Fly.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/Fly.kt index 9c8c378d136..a6d31800e55 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/Fly.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/Fly.kt @@ -26,7 +26,7 @@ import net.ccbluex.liquidbounce.utils.PacketUtils.sendPacket import net.ccbluex.liquidbounce.utils.extensions.stop import net.ccbluex.liquidbounce.utils.extensions.stopXZ import net.ccbluex.liquidbounce.utils.render.RenderUtils.drawPlatform -import net.ccbluex.liquidbounce.utils.timer.MSTimer +import net.ccbluex.liquidbounce.utils.timing.MSTimer import net.ccbluex.liquidbounce.value.BoolValue import net.ccbluex.liquidbounce.value.FloatValue import net.ccbluex.liquidbounce.value.IntegerValue diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/InventoryMove.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/InventoryMove.kt index 3e90ced2a4c..b3c90434986 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/InventoryMove.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/InventoryMove.kt @@ -10,21 +10,29 @@ import net.ccbluex.liquidbounce.event.EventTarget import net.ccbluex.liquidbounce.event.UpdateEvent import net.ccbluex.liquidbounce.features.module.Module import net.ccbluex.liquidbounce.features.module.ModuleCategory -import net.ccbluex.liquidbounce.utils.MovementUtils.isMoving +import net.ccbluex.liquidbounce.utils.inventory.InventoryManager +import net.ccbluex.liquidbounce.utils.inventory.InventoryManager.canClickInventory +import net.ccbluex.liquidbounce.utils.inventory.InventoryUtils.serverOpenInventory import net.ccbluex.liquidbounce.value.BoolValue import net.minecraft.client.gui.GuiChat import net.minecraft.client.gui.GuiIngameMenu -import net.minecraft.client.gui.inventory.GuiContainer +import net.minecraft.client.gui.inventory.GuiChest +import net.minecraft.client.gui.inventory.GuiInventory import net.minecraft.client.settings.GameSettings object InventoryMove : Module("InventoryMove", ModuleCategory.MOVEMENT) { - private val undetectable by BoolValue("Undetectable", false) + private val notInChests by BoolValue("NotInChests", false) val aacAdditionPro by BoolValue("AACAdditionPro", false) - private val noMoveClicks by BoolValue("NoMoveClicks", false) - private val noClicksAir by BoolValue("NoClicksInAir", false) { noMoveClicks } - private val noClicksGround by BoolValue("NoClicksOnGround", true) { noMoveClicks } + private val noMove by InventoryManager.noMoveValue + private val noMoveAir by InventoryManager.noMoveAirValue + private val noMoveGround by InventoryManager.noMoveGroundValue + + // If player violates nomove check and inventory is open, close inventory and reopen it when still + private val silentlyCloseAndReopen by BoolValue("SilentlyCloseAndReopen", false) { noMove && (noMoveAir || noMoveGround) } + // Reopen closed inventory just before a click (could flag for clicking too fast after opening inventory) + private val reopenOnClick by BoolValue("ReopenOnClick", false) { silentlyCloseAndReopen && noMove && (noMoveAir || noMoveGround) } private val affectedBindings = arrayOf( mc.gameSettings.keyBindForward, @@ -35,32 +43,36 @@ object InventoryMove : Module("InventoryMove", ModuleCategory.MOVEMENT) { mc.gameSettings.keyBindSprint ) - fun canClickInventory() = - !state || !isMoving || !noMoveClicks || (if (mc.thePlayer.onGround) !noClicksGround else !noClicksAir) - @EventTarget fun onUpdate(event: UpdateEvent) { - if (mc.currentScreen !is GuiChat && mc.currentScreen !is GuiIngameMenu && (!undetectable || mc.currentScreen !is GuiContainer)) { - for (affectedBinding in affectedBindings) { - val shouldExcept = Sprint.state && Sprint.mode == "Legit" - affectedBinding.pressed = if (affectedBinding == affectedBindings.last() && shouldExcept) true else GameSettings.isKeyDown(affectedBinding) - } + val screen = mc.currentScreen + + // Don't make player move when chat or ESC menu are open + if (screen is GuiChat || screen is GuiIngameMenu) + return + + if (notInChests && screen is GuiChest) + return + + if (silentlyCloseAndReopen && screen is GuiInventory) { + if (canClickInventory(closeWhenViolating = true) && !reopenOnClick) + serverOpenInventory = true } + + for (affectedBinding in affectedBindings) + affectedBinding.pressed = GameSettings.isKeyDown(affectedBinding) + || (affectedBinding == mc.gameSettings.keyBindSprint && Sprint.state && Sprint.mode == "Legit") } @EventTarget fun onClick(event: ClickWindowEvent) { - if (!canClickInventory()) - event.cancelEvent() + if (!canClickInventory()) event.cancelEvent() + else if (reopenOnClick) serverOpenInventory = true } override fun onDisable() { - val isIngame = mc.currentScreen != null - - for (affectedBinding in affectedBindings) { - if (!GameSettings.isKeyDown(affectedBinding) || isIngame) - affectedBinding.pressed = false - } + for (affectedBinding in affectedBindings) + affectedBinding.pressed = GameSettings.isKeyDown(affectedBinding) } override val tag diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/Sprint.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/Sprint.kt index 37486fd5ba1..850985f24a5 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/Sprint.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/Sprint.kt @@ -13,6 +13,7 @@ import net.ccbluex.liquidbounce.features.module.ModuleCategory import net.ccbluex.liquidbounce.utils.MovementUtils.isMoving import net.ccbluex.liquidbounce.utils.RotationUtils.targetRotation import net.ccbluex.liquidbounce.utils.extensions.toRadians +import net.ccbluex.liquidbounce.utils.inventory.InventoryUtils.serverOpenInventory import net.ccbluex.liquidbounce.value.BoolValue import net.ccbluex.liquidbounce.value.FloatValue import net.ccbluex.liquidbounce.value.ListValue @@ -42,6 +43,8 @@ object Sprint : Module("Sprint", ModuleCategory.MOVEMENT) { private val usingItem by BoolValue("UsingItem", false) { mode == "Vanilla" } + private val inventory by BoolValue("Inventory", false) { mode == "Vanilla" } + val food by BoolValue("Food", true) { mode == "Vanilla" } val checkServerSide by BoolValue("CheckServerSide", false) { mode == "Vanilla" } @@ -75,7 +78,13 @@ object Sprint : Module("Sprint", ModuleCategory.MOVEMENT) { ) < 0.8 if (mode == "Vanilla") { - if (!isMoving || mc.thePlayer.isSneaking || blindness && mc.thePlayer.isPotionActive(Potion.blindness) || usingItem && mc.thePlayer.isUsingItem || food && !(mc.thePlayer.foodStats.foodLevel > 6f || mc.thePlayer.capabilities.allowFlying) || (checkServerSide && (mc.thePlayer.onGround || !checkServerSideGround) && !allDirections && shouldStop)) { + if (!isMoving || mc.thePlayer.isSneaking + || (blindness && mc.thePlayer.isPotionActive(Potion.blindness)) + || (usingItem && mc.thePlayer.isUsingItem) + || (food && !(mc.thePlayer.foodStats.foodLevel > 6f || mc.thePlayer.capabilities.allowFlying)) + || (checkServerSide && (mc.thePlayer.onGround || !checkServerSideGround) && !allDirections && shouldStop) + || (inventory && serverOpenInventory) + ) { mc.thePlayer.isSprinting = false return } diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/Step.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/Step.kt index 975f77667a6..cbfdfed7d7c 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/Step.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/Step.kt @@ -14,7 +14,7 @@ import net.ccbluex.liquidbounce.utils.MovementUtils.direction import net.ccbluex.liquidbounce.utils.MovementUtils.isMoving import net.ccbluex.liquidbounce.utils.PacketUtils.sendPacket import net.ccbluex.liquidbounce.utils.PacketUtils.sendPackets -import net.ccbluex.liquidbounce.utils.timer.MSTimer +import net.ccbluex.liquidbounce.utils.timing.MSTimer import net.ccbluex.liquidbounce.value.FloatValue import net.ccbluex.liquidbounce.value.IntegerValue import net.ccbluex.liquidbounce.value.ListValue diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/flymodes/hypixel/BoostHypixel.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/flymodes/hypixel/BoostHypixel.kt index b85d1c77bc9..1c2edac137f 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/flymodes/hypixel/BoostHypixel.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/flymodes/hypixel/BoostHypixel.kt @@ -16,8 +16,7 @@ import net.ccbluex.liquidbounce.utils.PacketUtils.sendPackets import net.ccbluex.liquidbounce.utils.extensions.component1 import net.ccbluex.liquidbounce.utils.extensions.component2 import net.ccbluex.liquidbounce.utils.extensions.component3 -import net.ccbluex.liquidbounce.utils.timer.TickTimer -import net.minecraft.init.Blocks +import net.ccbluex.liquidbounce.utils.timing.TickTimer import net.minecraft.init.Blocks.air import net.minecraft.network.play.client.C03PacketPlayer import net.minecraft.network.play.client.C03PacketPlayer.C04PacketPlayerPosition diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/flymodes/hypixel/FreeHypixel.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/flymodes/hypixel/FreeHypixel.kt index 5a2533cd878..c217498abf0 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/flymodes/hypixel/FreeHypixel.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/flymodes/hypixel/FreeHypixel.kt @@ -9,7 +9,7 @@ import net.ccbluex.liquidbounce.event.MoveEvent import net.ccbluex.liquidbounce.features.module.modules.movement.Fly.startY import net.ccbluex.liquidbounce.features.module.modules.movement.flymodes.FlyMode import net.ccbluex.liquidbounce.utils.extensions.stop -import net.ccbluex.liquidbounce.utils.timer.TickTimer +import net.ccbluex.liquidbounce.utils.timing.TickTimer import java.math.BigDecimal import java.math.RoundingMode diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/flymodes/hypixel/Hypixel.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/flymodes/hypixel/Hypixel.kt index cc07db739c1..240d79736b1 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/flymodes/hypixel/Hypixel.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/flymodes/hypixel/Hypixel.kt @@ -13,9 +13,8 @@ import net.ccbluex.liquidbounce.features.module.modules.movement.Fly.hypixelBoos import net.ccbluex.liquidbounce.features.module.modules.movement.Fly.hypixelBoostDelay import net.ccbluex.liquidbounce.features.module.modules.movement.Fly.hypixelBoostTimer import net.ccbluex.liquidbounce.features.module.modules.movement.flymodes.FlyMode -import net.ccbluex.liquidbounce.utils.timer.MSTimer -import net.ccbluex.liquidbounce.utils.timer.TickTimer -import net.minecraft.init.Blocks +import net.ccbluex.liquidbounce.utils.timing.MSTimer +import net.ccbluex.liquidbounce.utils.timing.TickTimer import net.minecraft.init.Blocks.air import net.minecraft.network.play.client.C03PacketPlayer import net.minecraft.util.AxisAlignedBB diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/flymodes/other/CubeCraft.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/flymodes/other/CubeCraft.kt index 7c0e351811e..365d2de5f5b 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/flymodes/other/CubeCraft.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/flymodes/other/CubeCraft.kt @@ -8,7 +8,7 @@ package net.ccbluex.liquidbounce.features.module.modules.movement.flymodes.other import net.ccbluex.liquidbounce.event.MoveEvent import net.ccbluex.liquidbounce.features.module.modules.movement.flymodes.FlyMode import net.ccbluex.liquidbounce.utils.extensions.toRadiansD -import net.ccbluex.liquidbounce.utils.timer.TickTimer +import net.ccbluex.liquidbounce.utils.timing.TickTimer import kotlin.math.cos import kotlin.math.sin diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/flymodes/other/MineSecure.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/flymodes/other/MineSecure.kt index a5f004c9744..29330cf56b2 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/flymodes/other/MineSecure.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/flymodes/other/MineSecure.kt @@ -13,7 +13,7 @@ import net.ccbluex.liquidbounce.utils.extensions.component1 import net.ccbluex.liquidbounce.utils.extensions.component2 import net.ccbluex.liquidbounce.utils.extensions.component3 import net.ccbluex.liquidbounce.utils.extensions.toRadiansD -import net.ccbluex.liquidbounce.utils.timer.MSTimer +import net.ccbluex.liquidbounce.utils.timing.MSTimer import net.minecraft.network.play.client.C03PacketPlayer.C04PacketPlayerPosition import kotlin.math.cos import kotlin.math.sin diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/flymodes/other/Mineplex.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/flymodes/other/Mineplex.kt index 419863e6faf..e1944947ee6 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/flymodes/other/Mineplex.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/flymodes/other/Mineplex.kt @@ -15,8 +15,7 @@ import net.ccbluex.liquidbounce.features.module.modules.movement.flymodes.FlyMod import net.ccbluex.liquidbounce.utils.ClientUtils.displayChatMessage import net.ccbluex.liquidbounce.utils.MovementUtils.strafe import net.ccbluex.liquidbounce.utils.extensions.* -import net.ccbluex.liquidbounce.utils.timer.MSTimer -import net.minecraft.init.Blocks +import net.ccbluex.liquidbounce.utils.timing.MSTimer import net.minecraft.init.Blocks.air import net.minecraft.network.play.client.C03PacketPlayer import net.minecraft.util.AxisAlignedBB diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/flymodes/spartan/Spartan.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/flymodes/spartan/Spartan.kt index 0bc91a25d72..3d487876aaa 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/flymodes/spartan/Spartan.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/flymodes/spartan/Spartan.kt @@ -7,7 +7,7 @@ package net.ccbluex.liquidbounce.features.module.modules.movement.flymodes.spart import net.ccbluex.liquidbounce.features.module.modules.movement.flymodes.FlyMode import net.ccbluex.liquidbounce.utils.PacketUtils.sendPackets -import net.ccbluex.liquidbounce.utils.timer.TickTimer +import net.ccbluex.liquidbounce.utils.timing.TickTimer import net.minecraft.network.play.client.C03PacketPlayer.C04PacketPlayerPosition object Spartan : FlyMode("Spartan") { diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/speedmodes/ncp/Frame.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/speedmodes/ncp/Frame.kt index 57b217850a2..220bad4dbae 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/speedmodes/ncp/Frame.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/speedmodes/ncp/Frame.kt @@ -8,7 +8,7 @@ package net.ccbluex.liquidbounce.features.module.modules.movement.speedmodes.ncp import net.ccbluex.liquidbounce.features.module.modules.movement.speedmodes.SpeedMode import net.ccbluex.liquidbounce.utils.MovementUtils.isMoving import net.ccbluex.liquidbounce.utils.MovementUtils.strafe -import net.ccbluex.liquidbounce.utils.timer.TickTimer +import net.ccbluex.liquidbounce.utils.timing.TickTimer object Frame : SpeedMode("Frame") { private var motionTicks = 0 diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/speedmodes/other/MineplexGround.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/speedmodes/other/MineplexGround.kt index 7e2e6e2803d..fb2d0298da3 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/speedmodes/other/MineplexGround.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/speedmodes/other/MineplexGround.kt @@ -5,14 +5,13 @@ */ package net.ccbluex.liquidbounce.features.module.modules.movement.speedmodes.other -import net.ccbluex.liquidbounce.features.module.modules.movement.Speed +import net.ccbluex.liquidbounce.features.module.modules.movement.Speed.mineplexGroundSpeed import net.ccbluex.liquidbounce.features.module.modules.movement.speedmodes.SpeedMode import net.ccbluex.liquidbounce.utils.ClientUtils.displayChatMessage import net.ccbluex.liquidbounce.utils.MovementUtils.isMoving import net.ccbluex.liquidbounce.utils.MovementUtils.strafe -import net.ccbluex.liquidbounce.utils.PacketUtils.sendPacket import net.ccbluex.liquidbounce.utils.extensions.plus -import net.minecraft.network.play.client.C09PacketHeldItemChange +import net.ccbluex.liquidbounce.utils.inventory.InventoryUtils.serverSlot import net.minecraft.util.BlockPos import net.minecraft.util.EnumFacing import net.minecraft.util.Vec3 @@ -27,7 +26,8 @@ object MineplexGround : SpeedMode("MineplexGround") { for (i in 36..44) { val itemStack = mc.thePlayer.inventory.getStackInSlot(i) if (itemStack != null) continue - sendPacket(C09PacketHeldItemChange(i - 36)) + + serverSlot = i - 36 spoofSlot = true break } @@ -42,18 +42,21 @@ object MineplexGround : SpeedMode("MineplexGround") { displayChatMessage("§8[§c§lMineplex§aSpeed§8] §cYou need one empty slot.") return } + val blockPos = BlockPos(mc.thePlayer).down() val vec = Vec3(blockPos).addVector(0.4, 0.4, 0.4) + Vec3(EnumFacing.UP.directionVec) + mc.playerController.onPlayerRightClick(mc.thePlayer, mc.theWorld, null, blockPos, EnumFacing.UP, Vec3(vec.xCoord * 0.4f, vec.yCoord * 0.4f, vec.zCoord * 0.4f)) - val targetSpeed = Speed.mineplexGroundSpeed - if (targetSpeed > speed) speed += targetSpeed / 8 - if (speed >= targetSpeed) speed = targetSpeed + + speed = (speed + mineplexGroundSpeed / 8).coerceAtMost(mineplexGroundSpeed) + strafe(speed) - if (!spoofSlot) sendPacket(C09PacketHeldItemChange(mc.thePlayer.inventory.currentItem)) + + if (!spoofSlot) serverSlot = mc.thePlayer.inventory.currentItem } override fun onDisable() { speed = 0f - sendPacket(C09PacketHeldItemChange(mc.thePlayer.inventory.currentItem)) + serverSlot = mc.thePlayer.inventory.currentItem } } \ No newline at end of file diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/speedmodes/other/TeleportCubeCraft.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/speedmodes/other/TeleportCubeCraft.kt index 01ef6ecb32b..1aacecfdfe5 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/speedmodes/other/TeleportCubeCraft.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/speedmodes/other/TeleportCubeCraft.kt @@ -10,7 +10,7 @@ import net.ccbluex.liquidbounce.features.module.modules.movement.Speed import net.ccbluex.liquidbounce.features.module.modules.movement.speedmodes.SpeedMode import net.ccbluex.liquidbounce.utils.MovementUtils.direction import net.ccbluex.liquidbounce.utils.MovementUtils.isMoving -import net.ccbluex.liquidbounce.utils.timer.MSTimer +import net.ccbluex.liquidbounce.utils.timing.MSTimer import kotlin.math.cos import kotlin.math.sin diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/speedmodes/verus/VerusLowHop.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/speedmodes/verus/VerusLowHop.kt index fe16299bb0c..3ced88015ce 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/speedmodes/verus/VerusLowHop.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/movement/speedmodes/verus/VerusLowHop.kt @@ -27,7 +27,7 @@ object VerusLowHop : SpeedMode("VerusLowHop") { } airTicks++ - speed *= 0.98f; + speed *= 0.98f } strafe(speed, false) diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/AntiAFK.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/AntiAFK.kt index 80bec618988..850bb2d42a2 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/AntiAFK.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/AntiAFK.kt @@ -13,7 +13,7 @@ import net.ccbluex.liquidbounce.utils.extensions.fixedSensitivityPitch import net.ccbluex.liquidbounce.utils.extensions.fixedSensitivityYaw import net.ccbluex.liquidbounce.utils.misc.RandomUtils.nextFloat import net.ccbluex.liquidbounce.utils.misc.RandomUtils.nextInt -import net.ccbluex.liquidbounce.utils.timer.MSTimer +import net.ccbluex.liquidbounce.utils.timing.MSTimer import net.ccbluex.liquidbounce.value.BoolValue import net.ccbluex.liquidbounce.value.FloatValue import net.ccbluex.liquidbounce.value.IntegerValue diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/AntiFireball.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/AntiFireball.kt index 04d5ded26d4..5e1b9486dbc 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/AntiFireball.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/AntiFireball.kt @@ -19,6 +19,7 @@ import net.ccbluex.liquidbounce.utils.RotationUtils.targetRotation import net.ccbluex.liquidbounce.utils.RotationUtils.toRotation import net.ccbluex.liquidbounce.utils.extensions.* import net.ccbluex.liquidbounce.utils.misc.RandomUtils.nextFloat +import net.ccbluex.liquidbounce.utils.timing.MSTimer import net.ccbluex.liquidbounce.value.BoolValue import net.ccbluex.liquidbounce.value.FloatValue import net.ccbluex.liquidbounce.value.ListValue diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/AutoFish.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/AutoFish.kt index c30a7d6ee57..9955bf891d1 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/AutoFish.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/AutoFish.kt @@ -9,7 +9,7 @@ import net.ccbluex.liquidbounce.event.EventTarget import net.ccbluex.liquidbounce.event.UpdateEvent import net.ccbluex.liquidbounce.features.module.Module import net.ccbluex.liquidbounce.features.module.ModuleCategory -import net.ccbluex.liquidbounce.utils.timer.MSTimer +import net.ccbluex.liquidbounce.utils.timing.MSTimer import net.minecraft.item.ItemFishingRod object AutoFish : Module("AutoFish", ModuleCategory.PLAYER) { diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/Blink.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/Blink.kt index e5f43a229fb..73b2a6558bf 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/Blink.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/Blink.kt @@ -15,7 +15,7 @@ import net.ccbluex.liquidbounce.features.module.modules.render.Breadcrumbs import net.ccbluex.liquidbounce.utils.PacketUtils.sendPackets import net.ccbluex.liquidbounce.utils.render.ColorUtils.rainbow import net.ccbluex.liquidbounce.utils.render.RenderUtils.glColor -import net.ccbluex.liquidbounce.utils.timer.MSTimer +import net.ccbluex.liquidbounce.utils.timing.MSTimer import net.ccbluex.liquidbounce.value.BoolValue import net.ccbluex.liquidbounce.value.IntegerValue import net.minecraft.client.entity.EntityOtherPlayerMP diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/FastUse.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/FastUse.kt index 3a2e66196f0..dc599a944f4 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/FastUse.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/FastUse.kt @@ -10,9 +10,9 @@ import net.ccbluex.liquidbounce.event.MoveEvent import net.ccbluex.liquidbounce.event.UpdateEvent import net.ccbluex.liquidbounce.features.module.Module import net.ccbluex.liquidbounce.features.module.ModuleCategory -import net.ccbluex.liquidbounce.utils.item.ItemUtils.isConsumingItem import net.ccbluex.liquidbounce.utils.PacketUtils.sendPacket -import net.ccbluex.liquidbounce.utils.timer.MSTimer +import net.ccbluex.liquidbounce.utils.inventory.ItemUtils.isConsumingItem +import net.ccbluex.liquidbounce.utils.timing.MSTimer import net.ccbluex.liquidbounce.value.BoolValue import net.ccbluex.liquidbounce.value.FloatValue import net.ccbluex.liquidbounce.value.IntegerValue diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/InventoryCleaner.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/InventoryCleaner.kt index b3ccb5fe9f1..2ceef34fedf 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/InventoryCleaner.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/InventoryCleaner.kt @@ -12,15 +12,14 @@ import net.ccbluex.liquidbounce.features.module.Module import net.ccbluex.liquidbounce.features.module.ModuleCategory import net.ccbluex.liquidbounce.features.module.modules.combat.AutoArmor import net.ccbluex.liquidbounce.features.module.modules.combat.AutoArmor.ARMOR_COMPARATOR -import net.ccbluex.liquidbounce.features.module.modules.movement.InventoryMove import net.ccbluex.liquidbounce.utils.ClientUtils.LOGGER -import net.ccbluex.liquidbounce.utils.InventoryUtils -import net.ccbluex.liquidbounce.utils.InventoryUtils.CLICK_TIMER -import net.ccbluex.liquidbounce.utils.InventoryUtils.serverOpenInventory import net.ccbluex.liquidbounce.utils.MovementUtils.isMoving import net.ccbluex.liquidbounce.utils.PacketUtils.sendPacket -import net.ccbluex.liquidbounce.utils.item.* -import net.ccbluex.liquidbounce.utils.timer.TimeUtils.randomDelay +import net.ccbluex.liquidbounce.utils.inventory.* +import net.ccbluex.liquidbounce.utils.inventory.InventoryManager.canClickInventory +import net.ccbluex.liquidbounce.utils.inventory.InventoryUtils.CLICK_TIMER +import net.ccbluex.liquidbounce.utils.inventory.InventoryUtils.serverOpenInventory +import net.ccbluex.liquidbounce.utils.timing.TimeUtils.randomDelay import net.ccbluex.liquidbounce.value.BoolValue import net.ccbluex.liquidbounce.value.IntegerValue import net.ccbluex.liquidbounce.value.ListValue @@ -52,12 +51,12 @@ object InventoryCleaner : Module("InventoryCleaner", ModuleCategory.PLAYER) { } private val itemDelay by IntegerValue("ItemDelay", 0, 0..5000) - private val invOpen by BoolValue("InvOpen", false) - private val simulateInventory by BoolValue("SimulateInventory", true) { !invOpen } + private val invOpen by InventoryManager.invOpenValue + private val simulateInventory by InventoryManager.simulateInventoryValue - private val noMove by BoolValue("NoMoveClicks", false) - private val noMoveAir by BoolValue("NoClicksInAir", false) { noMove } - private val noMoveGround by BoolValue("NoClicksOnGround", true) { noMove } + private val noMove by InventoryManager.noMoveValue + private val noMoveAir by InventoryManager.noMoveAirValue + private val noMoveGround by InventoryManager.noMoveGroundValue private val ignoreVehicles by BoolValue("IgnoreVehicles", false) private val hotbar by BoolValue("Hotbar", true) @@ -93,7 +92,7 @@ object InventoryCleaner : Module("InventoryCleaner", ModuleCategory.PLAYER) { return // Check if movement clicking isn't blocked by InventoryMove itself - if (!InventoryMove.canClickInventory()) + if (!canClickInventory()) return if (noMove && isMoving && if (mc.thePlayer.onGround) noMoveGround else noMoveAir) @@ -277,7 +276,7 @@ object InventoryCleaner : Module("InventoryCleaner", ModuleCategory.PLAYER) { val item = stack.item if (item is ItemFood && item !is ItemAppleGold && type(index) != "Food") { - val replaceCurr = slotStack.isEmpty || slotStack?.item !is ItemFood + val replaceCurr = slotStack.isEmpty() || slotStack.item !is ItemFood return if (replaceCurr) index else null } @@ -291,7 +290,7 @@ object InventoryCleaner : Module("InventoryCleaner", ModuleCategory.PLAYER) { val item = stack.item if (item is ItemBlock && item.block !in InventoryUtils.BLOCK_BLACKLIST && type(index) != "Block") { - val replaceCurr = slotStack.isEmpty || slotStack?.item !is ItemBlock + val replaceCurr = slotStack.isEmpty() || slotStack.item !is ItemBlock return if (replaceCurr) index else null } @@ -306,7 +305,7 @@ object InventoryCleaner : Module("InventoryCleaner", ModuleCategory.PLAYER) { if (item is ItemBucket && item.isFull == Blocks.flowing_water && type(index) != "Water") { val replaceCurr = - slotStack.isEmpty || slotStack?.item !is ItemBucket || (slotStack.item as ItemBucket).isFull != Blocks.flowing_water + slotStack.isEmpty() || slotStack.item !is ItemBucket || (slotStack.item as ItemBucket).isFull != Blocks.flowing_water return if (replaceCurr) index else null } @@ -320,7 +319,7 @@ object InventoryCleaner : Module("InventoryCleaner", ModuleCategory.PLAYER) { val item = stack.item if (item is ItemAppleGold && type(index) != "Gapple") { - val replaceCurr = slotStack.isEmpty || slotStack?.item !is ItemAppleGold + val replaceCurr = slotStack.isEmpty() || slotStack.item !is ItemAppleGold return if (replaceCurr) index else null } @@ -334,7 +333,7 @@ object InventoryCleaner : Module("InventoryCleaner", ModuleCategory.PLAYER) { val item = stack.item if (item is ItemEnderPearl && type(index) != "Pearl") { - val replaceCurr = slotStack.isEmpty || slotStack?.item !is ItemEnderPearl + val replaceCurr = slotStack.isEmpty() || slotStack.item !is ItemEnderPearl return if (replaceCurr) index else null } @@ -355,7 +354,7 @@ object InventoryCleaner : Module("InventoryCleaner", ModuleCategory.PLAYER) { for (i in endInclusive downTo startInclusive) { val itemStack = mc.thePlayer.inventoryContainer.getSlot(i).stack ?: continue - if (itemStack.isEmpty) { + if (itemStack.isEmpty()) { continue } @@ -363,7 +362,7 @@ object InventoryCleaner : Module("InventoryCleaner", ModuleCategory.PLAYER) { continue } - if (itemStack.hasItemDelayPassed(itemDelay)) { + if (itemStack.hasItemAgePassed(itemDelay)) { items[i] = itemStack } } diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/KeepAlive.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/KeepAlive.kt index e2a40c4ea30..7fbccbf2dc1 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/KeepAlive.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/KeepAlive.kt @@ -9,8 +9,8 @@ import net.ccbluex.liquidbounce.event.EventTarget import net.ccbluex.liquidbounce.event.MotionEvent import net.ccbluex.liquidbounce.features.module.Module import net.ccbluex.liquidbounce.features.module.ModuleCategory -import net.ccbluex.liquidbounce.utils.InventoryUtils import net.ccbluex.liquidbounce.utils.PacketUtils.sendPackets +import net.ccbluex.liquidbounce.utils.inventory.InventoryUtils import net.ccbluex.liquidbounce.value.ListValue import net.minecraft.init.Items import net.minecraft.network.play.client.C08PacketPlayerBlockPlacement diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/KeyPearl.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/KeyPearl.kt index 23320d2d1c2..34d3416d19b 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/KeyPearl.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/KeyPearl.kt @@ -6,19 +6,19 @@ package net.ccbluex.liquidbounce.features.module.modules.player import net.ccbluex.liquidbounce.event.EventTarget +import net.ccbluex.liquidbounce.event.TickEvent import net.ccbluex.liquidbounce.features.module.Module import net.ccbluex.liquidbounce.features.module.ModuleCategory -import net.ccbluex.liquidbounce.event.TickEvent -import net.ccbluex.liquidbounce.value.BoolValue -import net.ccbluex.liquidbounce.value.TextValue import net.ccbluex.liquidbounce.utils.ClientUtils.displayChatMessage -import net.ccbluex.liquidbounce.utils.InventoryUtils import net.ccbluex.liquidbounce.utils.PacketUtils.sendPackets +import net.ccbluex.liquidbounce.utils.inventory.InventoryUtils +import net.ccbluex.liquidbounce.value.BoolValue import net.ccbluex.liquidbounce.value.ListValue +import net.ccbluex.liquidbounce.value.TextValue +import net.minecraft.init.Items import net.minecraft.network.play.client.C08PacketPlayerBlockPlacement import net.minecraft.network.play.client.C09PacketHeldItemChange import net.minecraft.world.WorldSettings -import net.minecraft.init.Items import org.lwjgl.input.Keyboard import org.lwjgl.input.Mouse diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/Refill.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/Refill.kt index 5dd1439fcbb..09865240d55 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/Refill.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/Refill.kt @@ -1,54 +1,50 @@ package net.ccbluex.liquidbounce.features.module.modules.player import net.ccbluex.liquidbounce.event.EventTarget -import net.ccbluex.liquidbounce.event.UpdateEvent +import net.ccbluex.liquidbounce.event.TickEvent import net.ccbluex.liquidbounce.features.module.Module import net.ccbluex.liquidbounce.features.module.ModuleCategory -import net.ccbluex.liquidbounce.utils.InventoryUtils.serverOpenInventory -import net.ccbluex.liquidbounce.utils.MovementUtils.isMoving import net.ccbluex.liquidbounce.utils.PacketUtils.sendPacket -import net.ccbluex.liquidbounce.utils.item.hasItemDelayPassed -import net.ccbluex.liquidbounce.utils.timer.MSTimer +import net.ccbluex.liquidbounce.utils.inventory.InventoryManager +import net.ccbluex.liquidbounce.utils.inventory.InventoryManager.canClickInventory +import net.ccbluex.liquidbounce.utils.inventory.InventoryUtils.CLICK_TIMER +import net.ccbluex.liquidbounce.utils.inventory.InventoryUtils.serverOpenInventory +import net.ccbluex.liquidbounce.utils.inventory.hasItemAgePassed import net.ccbluex.liquidbounce.value.BoolValue import net.ccbluex.liquidbounce.value.IntegerValue import net.ccbluex.liquidbounce.value.ListValue import net.minecraft.client.gui.inventory.GuiInventory import net.minecraft.item.ItemStack -import net.minecraft.network.play.client.C0DPacketCloseWindow import net.minecraft.network.play.client.C0EPacketClickWindow -import net.minecraft.network.play.client.C16PacketClientStatus -import net.minecraft.network.play.client.C16PacketClientStatus.EnumState.OPEN_INVENTORY_ACHIEVEMENT object Refill : Module("Refill", ModuleCategory.PLAYER) { private val delay by IntegerValue("Delay", 400, 10..1000) - private val itemDelay by IntegerValue("ItemDelay", 400, 0..1000) + private val minItemAge by IntegerValue("MinItemAge", 400, 0..1000) private val mode by ListValue("Mode", arrayOf("Swap", "Merge"), "Swap") private val invOpen by BoolValue("InvOpen", false) private val simulateInventory by BoolValue("SimulateInventory", false) { !invOpen } - private val noMove by BoolValue("NoMoveClicks", false) - private val noMoveAir by BoolValue("NoClicksInAir", false) { noMove } - private val noMoveGround by BoolValue("NoClicksOnGround", true) { noMove } - - private val timer = MSTimer() + private val noMove by InventoryManager.noMoveValue + private val noMoveAir by InventoryManager.noMoveAirValue + private val noMoveGround by InventoryManager.noMoveGroundValue @EventTarget - fun onUpdate(event: UpdateEvent) { - if (!timer.hasTimePassed(delay)) + fun onTick(event: TickEvent) { + if (!CLICK_TIMER.hasTimePassed(delay)) return if (invOpen && mc.currentScreen !is GuiInventory) return - if (noMove && isMoving && if (mc.thePlayer.onGround) noMoveGround else noMoveAir) + if (!canClickInventory()) return for (slot in 36..44) { val stack = mc.thePlayer.inventoryContainer.getSlot(slot).stack ?: continue - if (stack.stackSize == stack.maxStackSize || !stack.hasItemDelayPassed(itemDelay)) continue + if (stack.stackSize == stack.maxStackSize || !stack.hasItemAgePassed(minItemAge)) continue when (mode) { "Swap" -> { @@ -91,18 +87,15 @@ object Refill : Module("Refill", ModuleCategory.PLAYER) { } if (simulateInventory && serverOpenInventory && mc.currentScreen !is GuiInventory) - sendPacket(C0DPacketCloseWindow(mc.thePlayer.openContainer.windowId)) + serverOpenInventory = false } fun click(slot: Int, button: Int, mode: Int, stack: ItemStack) { - if (simulateInventory && !serverOpenInventory) - sendPacket(C16PacketClientStatus(OPEN_INVENTORY_ACHIEVEMENT)) + if (simulateInventory) serverOpenInventory = true sendPacket( C0EPacketClickWindow(mc.thePlayer.openContainer.windowId, slot, button, mode, stack, mc.thePlayer.openContainer.getNextTransactionID(mc.thePlayer.inventory)) ) - - timer.reset() } } \ No newline at end of file diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/Regen.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/Regen.kt index 4ba8b474314..15113f0f0d1 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/Regen.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/Regen.kt @@ -11,7 +11,7 @@ import net.ccbluex.liquidbounce.features.module.Module import net.ccbluex.liquidbounce.features.module.ModuleCategory import net.ccbluex.liquidbounce.utils.MovementUtils.isMoving import net.ccbluex.liquidbounce.utils.PacketUtils.sendPacket -import net.ccbluex.liquidbounce.utils.timer.MSTimer +import net.ccbluex.liquidbounce.utils.timing.MSTimer import net.ccbluex.liquidbounce.value.BoolValue import net.ccbluex.liquidbounce.value.IntegerValue import net.ccbluex.liquidbounce.value.ListValue diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/nofallmodes/other/MLG.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/nofallmodes/other/MLG.kt index 7bfe7d4226b..1a1a96e5a55 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/nofallmodes/other/MLG.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/nofallmodes/other/MLG.kt @@ -4,18 +4,16 @@ import net.ccbluex.liquidbounce.event.EventState.PRE import net.ccbluex.liquidbounce.event.MotionEvent import net.ccbluex.liquidbounce.features.module.modules.player.NoFall.minFallDistance import net.ccbluex.liquidbounce.features.module.modules.player.nofallmodes.NoFallMode -import net.ccbluex.liquidbounce.utils.InventoryUtils.serverSlot -import net.ccbluex.liquidbounce.utils.PacketUtils.sendPacket import net.ccbluex.liquidbounce.utils.RotationUtils.faceBlock import net.ccbluex.liquidbounce.utils.VecRotation import net.ccbluex.liquidbounce.utils.extensions.eyes +import net.ccbluex.liquidbounce.utils.inventory.InventoryUtils.serverSlot import net.ccbluex.liquidbounce.utils.misc.FallingPlayer -import net.ccbluex.liquidbounce.utils.timer.TickTimer +import net.ccbluex.liquidbounce.utils.timing.TickTimer import net.minecraft.init.Blocks.web import net.minecraft.init.Items.water_bucket import net.minecraft.item.ItemBlock import net.minecraft.item.ItemBucket -import net.minecraft.network.play.client.C09PacketHeldItemChange import net.minecraft.util.BlockPos import net.minecraft.util.Vec3 import kotlin.math.ceil @@ -65,9 +63,7 @@ object MLG : NoFallMode("MLG") { currentMlgBlock = collision.pos - if (thePlayer.inventory.currentItem != index) { - sendPacket(C09PacketHeldItemChange(index)) - } + serverSlot = index currentMlgRotation = faceBlock(collision.pos) currentMlgRotation?.rotation?.toPlayer(thePlayer) @@ -81,7 +77,7 @@ object MLG : NoFallMode("MLG") { mlgTimer.reset() } - if (thePlayer.inventory.currentItem != serverSlot) sendPacket(C09PacketHeldItemChange(thePlayer.inventory.currentItem)) + serverSlot = thePlayer.inventory.currentItem } } } diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/nofallmodes/other/Spartan.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/nofallmodes/other/Spartan.kt index 0e6ffd050e6..725d1edf3f9 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/nofallmodes/other/Spartan.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/player/nofallmodes/other/Spartan.kt @@ -2,7 +2,7 @@ package net.ccbluex.liquidbounce.features.module.modules.player.nofallmodes.othe import net.ccbluex.liquidbounce.features.module.modules.player.nofallmodes.NoFallMode import net.ccbluex.liquidbounce.utils.PacketUtils.sendPackets -import net.ccbluex.liquidbounce.utils.timer.TickTimer +import net.ccbluex.liquidbounce.utils.timing.TickTimer import net.minecraft.network.play.client.C03PacketPlayer.C04PacketPlayerPosition object Spartan : NoFallMode("Spartan") { diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/render/Ambience.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/render/Ambience.kt index 08a8655a6c2..b0bc39d3c26 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/render/Ambience.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/render/Ambience.kt @@ -27,7 +27,7 @@ object Ambience : Module("Ambience", ModuleCategory.RENDER) { private val weatherStrength by FloatValue("WeatherStrength", 1f, 0f..1f) { weatherMode == "Rain" || weatherMode == "Thunder" } - var i = 0L + private var i = 0L override fun onDisable() { i = 0 diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/render/BlockESP.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/render/BlockESP.kt index 498fa38610a..68d7c717ae0 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/render/BlockESP.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/render/BlockESP.kt @@ -15,7 +15,7 @@ import net.ccbluex.liquidbounce.utils.block.BlockUtils.getBlockName import net.ccbluex.liquidbounce.utils.render.ColorUtils.rainbow import net.ccbluex.liquidbounce.utils.render.RenderUtils.draw2D import net.ccbluex.liquidbounce.utils.render.RenderUtils.drawBlockBox -import net.ccbluex.liquidbounce.utils.timer.MSTimer +import net.ccbluex.liquidbounce.utils.timing.MSTimer import net.ccbluex.liquidbounce.value.BlockValue import net.ccbluex.liquidbounce.value.BoolValue import net.ccbluex.liquidbounce.value.IntegerValue diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/render/ClickGUI.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/render/ClickGUI.kt index 5489fe42318..52abea25ab6 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/render/ClickGUI.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/render/ClickGUI.kt @@ -31,7 +31,7 @@ object ClickGUI : Module("ClickGUI", ModuleCategory.RENDER, Keyboard.KEY_RSHIFT, } var scale by FloatValue("Scale", 0.8f, 0.5f..1.5f) val maxElements by IntegerValue("MaxElements", 15, 1..30) - val fadeSpeed by FloatValue("FadeSpeed", 1f, 0.5f..2f) + val fadeSpeed by FloatValue("FadeSpeed", 1f, 0.5f..4f) val scrolls by BoolValue("Scrolls", false) val spacedModules by BoolValue("SpacedModules", false) val panelsForcedInBoundaries by BoolValue("PanelsForcedInBoundaries", true) diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/render/ESP.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/render/ESP.kt index a8a6d6d4517..ae991d678be 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/render/ESP.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/render/ESP.kt @@ -48,7 +48,7 @@ object ESP : Module("ESP", ModuleCategory.RENDER) { val wireframeWidth by FloatValue("WireFrame-Width", 2f, 0.5f..5f) { mode == "WireFrame" } - private val glowRenderScale by FloatValue("Glow-Renderscale", 1f, 0.1f..2f) { mode == "Glow" } + private val glowRenderScale by FloatValue("Glow-Renderscale", 1f, 0.5f..2f) { mode == "Glow" } private val glowRadius by IntegerValue("Glow-Radius", 4, 1..5) { mode == "Glow" } private val glowFade by IntegerValue("Glow-Fade", 10, 0..30) { mode == "Glow" } private val glowTargetAlpha by FloatValue("Glow-Target-Alpha", 0f, 0f..1f) { mode == "Glow" } @@ -65,7 +65,6 @@ object ESP : Module("ESP", ModuleCategory.RENDER) { @EventTarget fun onRender3D(event: Render3DEvent) { - val mode = mode val mvMatrix = WorldToScreen.getMatrix(GL_MODELVIEW_MATRIX) val projectionMatrix = WorldToScreen.getMatrix(GL_PROJECTION_MATRIX) val real2d = mode == "Real2D" @@ -94,9 +93,9 @@ object ESP : Module("ESP", ModuleCategory.RENDER) { if (entity != mc.thePlayer && isSelected(entity, false)) { val color = getColor(entity) - when (mode.lowercase()) { - "box", "otherbox" -> drawEntityBox(entity, color, mode != "OtherBox") - "2d" -> { + when (mode) { + "Box", "OtherBox" -> drawEntityBox(entity, color, mode != "OtherBox") + "2D" -> { val renderManager = mc.renderManager val timer = mc.timer val posX = @@ -107,7 +106,7 @@ object ESP : Module("ESP", ModuleCategory.RENDER) { entity.lastTickPosZ + (entity.posZ - entity.lastTickPosZ) * timer.renderPartialTicks - renderManager.renderPosZ draw2D(entity, posX, posY, posZ, color.rgb, Color.BLACK.rgb) } - "real2d" -> { + "Real2D" -> { val renderManager = mc.renderManager val timer = mc.timer val bb = entity.hitBox @@ -173,59 +172,59 @@ object ESP : Module("ESP", ModuleCategory.RENDER) { @EventTarget fun onRender2D(event: Render2DEvent) { - val mode = mode.lowercase() - val partialTicks = event.partialTicks - val shader = if (mode == "glow") GlowShader.GLOW_SHADER else null ?: return - shader.startDraw(event.partialTicks, glowRenderScale) - renderNameTags = false + if (mc.theWorld == null || mode != "Glow") + return + + GlowShader.startDraw(event.partialTicks, glowRenderScale) - if(mc.theWorld == null) return + renderNameTags = false try { - val entityMap = mutableMapOf>() mc.theWorld.loadedEntityList .filter { isSelected(it, false) } .filterIsInstance() - .filterNot { isBot(it) && bot }.forEach { entity -> - val color = getColor(entity) - if (color !in entityMap) { - entityMap[color] = ArrayList() - } - entityMap[color]!! += entity - } + .filterNot { isBot(it) && bot } + .groupBy { getColor(it) } + .forEach { (color, entities) -> + GlowShader.startDraw(event.partialTicks, glowRenderScale) + + for (entity in entities) { + mc.renderManager.renderEntitySimple(entity, event.partialTicks) + } - entityMap.forEach { (color, entities) -> - shader.startDraw(partialTicks, glowRenderScale) - for (entity in entities) { - mc.renderManager.renderEntitySimple(entity, partialTicks) + GlowShader.stopDraw(color, glowRadius, glowFade, glowTargetAlpha) } - shader.stopDraw(color, glowRadius, glowFade, glowTargetAlpha) - } } catch (ex: Exception) { LOGGER.error("An error occurred while rendering all entities for shader esp", ex) } + renderNameTags = true - shader.stopDraw(getColor(null), glowRadius, glowFade, glowTargetAlpha) + + GlowShader.stopDraw(getColor(), glowRadius, glowFade, glowTargetAlpha) } override val tag get() = mode - fun getColor(entity: Entity?): Color { + fun getColor(entity: Entity? = null): Color { run { if (entity != null && entity is EntityLivingBase) { if (entity.hurtTime > 0) return Color.RED + if (entity is EntityPlayer && entity.isClientFriend()) return Color.BLUE if (colorTeam) { val chars = (entity.displayName ?: return@run).formattedText.toCharArray() var color = Int.MAX_VALUE + for (i in chars.indices) { if (chars[i] != '§' || i + 1 >= chars.size) continue + val index = getColorIndex(chars[i + 1]) if (index < 0 || index > 15) continue + color = ColorUtils.hexColors[index] break } @@ -235,11 +234,7 @@ object ESP : Module("ESP", ModuleCategory.RENDER) { } } - return if (colorRainbow) rainbow() else Color( - colorRed, - colorGreen, - colorBlue - ) + return if (colorRainbow) rainbow() else Color(colorRed, colorGreen, colorBlue) } } \ No newline at end of file diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/render/ItemESP.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/render/ItemESP.kt index 83b91b498c8..88054a9c258 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/render/ItemESP.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/render/ItemESP.kt @@ -10,6 +10,7 @@ import net.ccbluex.liquidbounce.event.Render2DEvent import net.ccbluex.liquidbounce.event.Render3DEvent import net.ccbluex.liquidbounce.features.module.Module import net.ccbluex.liquidbounce.features.module.ModuleCategory +import net.ccbluex.liquidbounce.features.module.modules.beta.CoroutineCleaner import net.ccbluex.liquidbounce.utils.ClientUtils.LOGGER import net.ccbluex.liquidbounce.utils.render.ColorUtils.rainbow import net.ccbluex.liquidbounce.utils.render.RenderUtils.drawEntityBox @@ -19,13 +20,12 @@ import net.ccbluex.liquidbounce.value.FloatValue import net.ccbluex.liquidbounce.value.IntegerValue import net.ccbluex.liquidbounce.value.ListValue import net.minecraft.entity.item.EntityItem -import net.minecraft.entity.projectile.EntityArrow import java.awt.Color object ItemESP : Module("ItemESP", ModuleCategory.RENDER) { private val mode by ListValue("Mode", arrayOf("Box", "OtherBox", "Glow"), "Box") - private val glowRenderScale by FloatValue("Glow-Renderscale", 1f, 0.1f..2f) { mode == "Glow" } + private val glowRenderScale by FloatValue("Glow-Renderscale", 1f, 0.5f..2f) { mode == "Glow" } private val glowRadius by IntegerValue("Glow-Radius", 4, 1..5) { mode == "Glow" } private val glowFade by IntegerValue("Glow-Fade", 10, 0..30) { mode == "Glow" } private val glowTargetAlpha by FloatValue("Glow-Target-Alpha", 0f, 0f..1f) { mode == "Glow" } @@ -35,40 +35,59 @@ object ItemESP : Module("ItemESP", ModuleCategory.RENDER) { private val colorGreen by IntegerValue("G", 255, 0..255) { !colorRainbow } private val colorBlue by IntegerValue("B", 0, 0..255) { !colorRainbow } + val color + get() = if (colorRainbow) rainbow() else Color(colorRed, colorGreen, colorBlue) + + // TODO: Removed highlighting of EntityArrow to not complicate things even further + @EventTarget fun onRender3D(event: Render3DEvent) { + if (mc.theWorld == null || mc.thePlayer == null || mode == "Glow") + return - if(mc.theWorld == null) return - - mc.theWorld.loadedEntityList.filter { it is EntityItem || it is EntityArrow }.forEach { entity -> - when (mode.lowercase()) { - "box" -> drawEntityBox(entity, getColor(), true) - "otherbox" -> drawEntityBox(entity, getColor(), false) - } + renderESP { isUseful, entity -> + // Only render green boxes on useful items, if ItemESP is enabled, render boxes of ItemESP.color on useless items as well + drawEntityBox(entity, if (isUseful) Color.green else color, mode == "Box") } } @EventTarget fun onRender2D(event: Render2DEvent) { - val mode = mode.lowercase() - val partialTicks = event.partialTicks - val shader = if (mode == "glow") GlowShader.GLOW_SHADER else null ?: return + if (mc.theWorld == null || mc.thePlayer == null || mode != "Glow") + return + + renderESP { isUseful, entity -> + GlowShader.startDraw(event.partialTicks, glowRenderScale) + + mc.renderManager.renderEntityStatic(entity, event.partialTicks, true) + + // Only render green boxes on useful items, if ItemESP is enabled, render boxes of ItemESP.color on useless items as well + GlowShader.stopDraw(if (isUseful) Color.green else color, glowRadius, glowFade, glowTargetAlpha) + } + } - if(mc.theWorld == null) return + private fun renderESP(action: (Boolean, EntityItem) -> Unit) { + val entityStacksMap = mc.theWorld.loadedEntityList + .filterIsInstance() + .associateBy { it.entityItem } + + val stacks = mc.thePlayer.openContainer.inventory - shader.startDraw(partialTicks, glowRenderScale) try { - mc.theWorld.loadedEntityList.filter { it is EntityItem || it is EntityArrow }.forEach { entity -> - mc.renderManager.renderEntityStatic(entity, event.partialTicks, true) + entityStacksMap.forEach { (stack, entity) -> + val isUseful = CoroutineCleaner.state && CoroutineCleaner.highlightUseful + && CoroutineCleaner.isStackUseful(stack, stacks, entityStacksMap) + + // If ItemESP is disabled, only render boxes on useful items + if (!state && !isUseful) + return@forEach + + action(isUseful, entity) } } catch (ex: Exception) { - LOGGER.error("An error occurred while rendering all item entities for shader esp", ex) + LOGGER.error("An error occurred while rendering ItemESP!", ex) } - shader.stopDraw(getColor(), glowRadius, glowFade, glowTargetAlpha) - } - - private fun getColor():Color{ - return if (colorRainbow) rainbow() else Color(colorRed, colorGreen, colorBlue) } + override fun handleEvents() = state || (CoroutineCleaner.state && CoroutineCleaner.highlightUseful) } \ No newline at end of file diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/render/Projectiles.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/render/Projectiles.kt index 487493480cd..a4149adb160 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/render/Projectiles.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/render/Projectiles.kt @@ -13,6 +13,7 @@ import net.ccbluex.liquidbounce.utils.RotationUtils.targetRotation import net.ccbluex.liquidbounce.utils.block.BlockUtils.getState import net.ccbluex.liquidbounce.utils.extensions.toRadians import net.ccbluex.liquidbounce.utils.extensions.toRadiansD +import net.ccbluex.liquidbounce.utils.inventory.isSplashPotion import net.ccbluex.liquidbounce.utils.render.ColorUtils import net.ccbluex.liquidbounce.utils.render.ColorUtils.interpolateHSB import net.ccbluex.liquidbounce.utils.render.RenderUtils.disableGlCap @@ -50,9 +51,9 @@ object Projectiles : Module("Projectiles", ModuleCategory.RENDER) { val thePlayer = mc.thePlayer ?: return val theWorld = mc.theWorld ?: return - val heldItem = thePlayer.heldItem ?: return + val heldStack = thePlayer.heldItem ?: return - val item = heldItem.item + val item = heldStack.item val renderManager = mc.renderManager var isBow = false var motionFactor = 1.5F @@ -83,7 +84,7 @@ object Projectiles : Module("Projectiles", ModuleCategory.RENDER) { gravity = 0.04F size = 0.25F motionSlowdown = 0.92F - } else if (item is ItemPotion && ItemPotion.isSplash(mc.thePlayer.heldItem.itemDamage)) { + } else if (item is ItemPotion && heldStack.isSplashPotion()) { gravity = 0.05F size = 0.25F motionFactor = 0.5F @@ -111,7 +112,7 @@ object Projectiles : Module("Projectiles", ModuleCategory.RENDER) { // Motions var motionX = -sin(yawRadians) * cos(pitchRadians) * if (isBow) 1.0 else 0.4 var motionY = -sin( - (pitch + if (item is ItemPotion && ItemPotion.isSplash(mc.thePlayer.heldItem.itemDamage)) -20 else 0).toRadians() + (pitch + if (item is ItemPotion && heldStack.isSplashPotion()) -20 else 0).toRadians() ) * if (isBow) 1.0 else 0.4 var motionZ = cos(yawRadians) * cos(pitchRadians) * if (isBow) 1.0 else 0.4 val distance = sqrt(motionX * motionX + motionY * motionY + motionZ * motionZ) diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/render/ProphuntESP.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/render/ProphuntESP.kt index 6b42cc2a415..40eea43a3e1 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/render/ProphuntESP.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/render/ProphuntESP.kt @@ -28,7 +28,7 @@ object ProphuntESP : Module("ProphuntESP", ModuleCategory.RENDER) { private val mode by ListValue("Mode", arrayOf("Box", "OtherBox", "Glow"), "OtherBox") - private val glowRenderScale by FloatValue("Glow-Renderscale", 1f, 0.1f..2f) { mode == "Glow" } + private val glowRenderScale by FloatValue("Glow-Renderscale", 1f, 0.5f..2f) { mode == "Glow" } private val glowRadius by IntegerValue("Glow-Radius", 4, 1..5) { mode == "Glow" } private val glowFade by IntegerValue("Glow-Fade", 10, 0..30) { mode == "Glow" } private val glowTargetAlpha by FloatValue("Glow-Target-Alpha", 0f, 0f..1f) { mode == "Glow" } @@ -38,6 +38,8 @@ object ProphuntESP : Module("ProphuntESP", ModuleCategory.RENDER) { private val colorGreen by IntegerValue("G", 90, 0..255) { !colorRainbow } private val colorBlue by IntegerValue("B", 255, 0..255) { !colorRainbow } + private val color + get() = if (colorRainbow) rainbow() else Color(colorRed, colorGreen, colorBlue) override fun onDisable() { synchronized(blocks) { blocks.clear() } @@ -45,13 +47,13 @@ object ProphuntESP : Module("ProphuntESP", ModuleCategory.RENDER) { @EventTarget fun onRender3D(event: Render3DEvent) { - val mode = mode for (entity in mc.theWorld.loadedEntityList) { if (mode != "Box" && mode != "OtherBox") break if (entity !is EntityFallingBlock) continue - drawEntityBox(entity, getColor(), mode == "Box") + drawEntityBox(entity, color, mode == "Box") } + synchronized(blocks) { val iterator = blocks.entries.iterator() @@ -63,31 +65,28 @@ object ProphuntESP : Module("ProphuntESP", ModuleCategory.RENDER) { continue } - drawBlockBox(entry.key, getColor(), mode == "Box") + drawBlockBox(entry.key, color, mode == "Box") } } } @EventTarget fun onRender2D(event: Render2DEvent) { - val mode = mode.lowercase() - val shader = if (mode == "glow") GlowShader.GLOW_SHADER else null ?: return - val color = if (colorRainbow) rainbow() else Color(colorRed, colorGreen, colorBlue) + if (mc.theWorld == null || mode != "Glow") + return + - if(mc.theWorld == null) return + GlowShader.startDraw(event.partialTicks, glowRenderScale) - shader.startDraw(event.partialTicks, glowRenderScale) try { - mc.theWorld.loadedEntityList.filterNot{ it !is EntityFallingBlock }.forEach { entity -> - mc.renderManager.renderEntityStatic(entity, mc.timer.renderPartialTicks, true) + mc.theWorld.loadedEntityList.forEach { entity -> + if (entity is EntityFallingBlock) + mc.renderManager.renderEntityStatic(entity, mc.timer.renderPartialTicks, true) } } catch (ex: Exception) { LOGGER.error("An error occurred while rendering all entities for shader esp", ex) } - shader.stopDraw(color, glowRadius, glowFade, glowTargetAlpha) + GlowShader.stopDraw(color, glowRadius, glowFade, glowTargetAlpha) } - - private fun getColor() = if (colorRainbow) rainbow() else Color(colorRed, colorGreen, colorBlue) - } diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/render/StorageESP.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/render/StorageESP.kt index 1d462afdd5a..aaa9440bba0 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/render/StorageESP.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/render/StorageESP.kt @@ -33,7 +33,7 @@ object StorageESP : Module("StorageESP", ModuleCategory.RENDER) { private val mode by ListValue("Mode", arrayOf("Box", "OtherBox", "Outline", "Glow", "2D", "WireFrame"), "Outline") - private val glowRenderScale by FloatValue("Glow-Renderscale", 1f, 0.1f..2f) { mode == "Glow" } + private val glowRenderScale by FloatValue("Glow-Renderscale", 1f, 0.5f..2f) { mode == "Glow" } private val glowRadius by IntegerValue("Glow-Radius", 4, 1..5) { mode == "Glow" } private val glowFade by IntegerValue("Glow-Fade", 10, 0..30) { mode == "Glow" } private val glowTargetAlpha by FloatValue("Glow-Target-Alpha", 0f, 0f..1f) { mode == "Glow" } @@ -64,8 +64,6 @@ object StorageESP : Module("StorageESP", ModuleCategory.RENDER) { @EventTarget fun onRender3D(event: Render3DEvent) { try { - val mode = mode - if (mode == "Outline") { disableFastRender() OutlineUtils.checkSetupFBO() @@ -80,15 +78,15 @@ object StorageESP : Module("StorageESP", ModuleCategory.RENDER) { if (!(tileEntity is TileEntityChest || tileEntity is TileEntityEnderChest)) { drawBlockBox(tileEntity.pos, color, mode != "OtherBox") - if (tileEntity !is TileEntityEnchantmentTable) { + + if (tileEntity !is TileEntityEnchantmentTable) continue - } } - when (mode.lowercase()) { - "otherbox", "box" -> drawBlockBox(tileEntity.pos, color, mode != "OtherBox") + when (mode) { + "OtherBox", "Box" -> drawBlockBox(tileEntity.pos, color, mode != "OtherBox") - "2d" -> draw2D(tileEntity.pos, color.rgb, Color.BLACK.rgb) - "outline" -> { + "2D" -> draw2D(tileEntity.pos, color.rgb, Color.BLACK.rgb) + "Outline" -> { glColor(color) OutlineUtils.renderOne(3F) TileEntityRendererDispatcher.instance.renderTileEntity(tileEntity, event.partialTicks, -1) @@ -103,7 +101,7 @@ object StorageESP : Module("StorageESP", ModuleCategory.RENDER) { OutlineUtils.setColor(Color.WHITE) } - "wireframe" -> { + "WireFrame" -> { glPushMatrix() glPushAttrib(GL_ALL_ATTRIB_BITS) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) @@ -127,11 +125,11 @@ object StorageESP : Module("StorageESP", ModuleCategory.RENDER) { } for (entity in mc.theWorld.loadedEntityList) { if (entity is EntityMinecartChest) { - when (mode.lowercase()) { - "otherbox", "box" -> drawEntityBox(entity, Color(0, 66, 255), mode != "OtherBox") + when (mode) { + "OtherBox", "Box" -> drawEntityBox(entity, Color(0, 66, 255), mode != "OtherBox") "2d" -> draw2D(entity.position, Color(0, 66, 255).rgb, Color.BLACK.rgb) - "outline" -> { + "Outline" -> { val entityShadow = mc.gameSettings.entityShadows mc.gameSettings.entityShadows = false glColor(Color(0, 66, 255)) @@ -148,7 +146,7 @@ object StorageESP : Module("StorageESP", ModuleCategory.RENDER) { mc.gameSettings.entityShadows = entityShadow } - "wireframe" -> { + "WireFrame" -> { val entityShadow = mc.gameSettings.entityShadows mc.gameSettings.entityShadows = false glPushMatrix() @@ -172,6 +170,7 @@ object StorageESP : Module("StorageESP", ModuleCategory.RENDER) { } } } + glColor(Color(255, 255, 255, 255)) mc.gameSettings.gammaSetting = gamma } catch (ignored: Exception) { @@ -180,44 +179,36 @@ object StorageESP : Module("StorageESP", ModuleCategory.RENDER) { @EventTarget fun onRender2D(event: Render2DEvent) { - val mode = mode.lowercase() - val partialTicks = event.partialTicks - val shader = if (mode == "glow") GlowShader.GLOW_SHADER else null ?: return - val renderManager = mc.renderManager - shader.startDraw(event.partialTicks, glowRenderScale) + if (mc.theWorld == null || mode != "Glow") + return - if (mc.theWorld == null) return + val renderManager = mc.renderManager + GlowShader.startDraw(event.partialTicks, glowRenderScale) try { - val tileEntityMap = hashMapOf>() - - mc.theWorld.loadedTileEntityList.forEach { tileEntity -> - val color = getColor(tileEntity) ?: return@forEach - if (color !in tileEntityMap) { - tileEntityMap[color] = ArrayList() - } - - tileEntityMap[color]!! += tileEntity - } + mc.theWorld.loadedTileEntityList + .groupBy { getColor(it) } + .forEach { (color, tileEntities) -> + color ?: return@forEach + + GlowShader.startDraw(event.partialTicks, glowRenderScale) + + for (entity in tileEntities) { + TileEntityRendererDispatcher.instance.renderTileEntityAt( + entity, + entity.pos.x - renderManager.renderPosX, + entity.pos.y - renderManager.renderPosY, + entity.pos.z - renderManager.renderPosZ, + event.partialTicks + ) + } - tileEntityMap.forEach { (color, tileEntites) -> - shader.startDraw(partialTicks, glowRenderScale) - - for (entity in tileEntites) { - TileEntityRendererDispatcher.instance.renderTileEntityAt( - entity, - entity.pos.x - renderManager.renderPosX, - entity.pos.y - renderManager.renderPosY, - entity.pos.z - renderManager.renderPosZ, - partialTicks - ) + GlowShader.stopDraw(color, glowRadius, glowFade, glowTargetAlpha) } - shader.stopDraw(color, glowRadius, glowFade, glowTargetAlpha) - } } catch (ex: Exception) { LOGGER.error("An error occurred while rendering all storages for shader esp", ex) } - shader.stopDraw(Color(0, 66, 255), glowRadius, glowFade, glowTargetAlpha) + GlowShader.stopDraw(Color(0, 66, 255), glowRadius, glowFade, glowTargetAlpha) } } diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/world/ChestAura.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/world/ChestAura.kt index 121940b78a3..6a1e36d53d9 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/world/ChestAura.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/world/ChestAura.kt @@ -19,7 +19,7 @@ import net.ccbluex.liquidbounce.utils.block.BlockUtils.getCenterDistance import net.ccbluex.liquidbounce.utils.block.BlockUtils.searchBlocks import net.ccbluex.liquidbounce.utils.extensions.eyes import net.ccbluex.liquidbounce.utils.extensions.getVec -import net.ccbluex.liquidbounce.utils.timer.MSTimer +import net.ccbluex.liquidbounce.utils.timing.MSTimer import net.ccbluex.liquidbounce.value.BlockValue import net.ccbluex.liquidbounce.value.BoolValue import net.ccbluex.liquidbounce.value.FloatValue diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/world/ChestStealer.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/world/ChestStealer.kt index 8534ecdff3f..68c15ea8e18 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/world/ChestStealer.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/world/ChestStealer.kt @@ -11,11 +11,11 @@ import net.ccbluex.liquidbounce.event.Render3DEvent import net.ccbluex.liquidbounce.features.module.Module import net.ccbluex.liquidbounce.features.module.ModuleCategory import net.ccbluex.liquidbounce.features.module.modules.player.InventoryCleaner -import net.ccbluex.liquidbounce.utils.TickedActions -import net.ccbluex.liquidbounce.utils.item.isEmpty +import net.ccbluex.liquidbounce.utils.inventory.InventoryUtils.hasSpaceInInventory +import net.ccbluex.liquidbounce.utils.inventory.isEmpty import net.ccbluex.liquidbounce.utils.misc.RandomUtils.nextInt -import net.ccbluex.liquidbounce.utils.timer.MSTimer -import net.ccbluex.liquidbounce.utils.timer.TimeUtils.randomDelay +import net.ccbluex.liquidbounce.utils.timing.MSTimer +import net.ccbluex.liquidbounce.utils.timing.TimeUtils.randomDelay import net.ccbluex.liquidbounce.value.BoolValue import net.ccbluex.liquidbounce.value.IntegerValue import net.minecraft.client.gui.inventory.GuiChest @@ -102,7 +102,7 @@ object ChestStealer : Module("ChestStealer", ModuleCategory.WORLD) { if (screen !is GuiChest || mc.currentScreen == null) { if (delayOnFirst) delayTimer.reset() autoCloseTimer.reset() - TickedActions.clear(this) + TickScheduler.clear() return } @@ -129,7 +129,7 @@ object ChestStealer : Module("ChestStealer", ModuleCategory.WORLD) { } // Is empty? - if (!isEmpty(screen) && (!closeOnFull || !fullInventory)) { + if (!isEmpty(screen) && (!closeOnFull || hasSpaceInInventory())) { autoCloseTimer.reset() // Randomized @@ -144,7 +144,7 @@ object ChestStealer : Module("ChestStealer", ModuleCategory.WORLD) { if (stack != null && (!onlyItems || stack.item !is ItemBlock) && (!InventoryCleaner.state || InventoryCleaner.isUseful( stack, -1 - )) && !TickedActions.containsId(slot.slotNumber, this) + )) && slot.slotNumber !in TickScheduler ) items += slot } @@ -152,7 +152,7 @@ object ChestStealer : Module("ChestStealer", ModuleCategory.WORLD) { val randomSlot = nextInt(endExclusive = items.size) val slot = items[randomSlot] - if (TickedActions.add({ move(screen, slot) }, slot.slotNumber, this)) { + if (TickScheduler.schedule(slot.slotNumber) { move(screen, slot) }) { resetDelay() } } @@ -167,25 +167,21 @@ object ChestStealer : Module("ChestStealer", ModuleCategory.WORLD) { val stack = slot.stack if (delayTimer.hasTimePassed(nextDelay) && shouldTake(stack, slot.slotNumber)) { - if (TickedActions.add({ move(screen, slot) }, slot.slotNumber, this)) { + if (TickScheduler.schedule(slot.slotNumber) { move(screen, slot) }) { resetDelay() } } } - } else if (autoClose && screen.inventorySlots.windowId == contentReceived && autoCloseTimer.hasTimePassed( - nextCloseDelay - ) + } else if (autoClose && screen.inventorySlots.windowId == contentReceived + && autoCloseTimer.hasTimePassed(nextCloseDelay) ) { - if (TickedActions.add({ thePlayer.closeScreen() }, -1, this)) { + TickScheduler += { + thePlayer.closeScreen() nextCloseDelay = randomDelay(autoCloseMinDelay, autoCloseMaxDelay) } } } - override fun onToggle(state: Boolean) { - TickedActions.clear(this) - } - @EventTarget private fun onPacket(event: PacketEvent) { val packet = event.packet @@ -201,9 +197,9 @@ object ChestStealer : Module("ChestStealer", ModuleCategory.WORLD) { } private fun shouldTake(stack: ItemStack?, slot: Int): Boolean { - return stack != null && !stack.isEmpty && (!onlyItems || stack.item !is ItemBlock) && (!InventoryCleaner.state || InventoryCleaner.isUseful( - stack, -1 - )) && !TickedActions.containsId(slot, this) + return !stack.isEmpty() && (!onlyItems || stack.item !is ItemBlock) + && slot !in TickScheduler + && (!InventoryCleaner.state || InventoryCleaner.isUseful(stack, -1)) } private fun move(screen: GuiChest, slot: Slot) { @@ -226,7 +222,4 @@ object ChestStealer : Module("ChestStealer", ModuleCategory.WORLD) { return true } - - private val fullInventory - get() = mc.thePlayer?.inventory?.mainInventory?.none(ItemStack::isEmpty) ?: false } diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/world/Fucker.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/world/Fucker.kt index 354c53bff9f..b351f993f1b 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/world/Fucker.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/world/Fucker.kt @@ -22,7 +22,7 @@ import net.ccbluex.liquidbounce.utils.block.BlockUtils.isFullBlock import net.ccbluex.liquidbounce.utils.extensions.eyes import net.ccbluex.liquidbounce.utils.extensions.getBlock import net.ccbluex.liquidbounce.utils.render.RenderUtils.drawBlockBox -import net.ccbluex.liquidbounce.utils.timer.MSTimer +import net.ccbluex.liquidbounce.utils.timing.MSTimer import net.ccbluex.liquidbounce.value.* import net.minecraft.block.Block import net.minecraft.init.Blocks.air diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/world/Nuker.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/world/Nuker.kt index bb13a3507e5..5b011ab0ec4 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/world/Nuker.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/world/Nuker.kt @@ -19,7 +19,7 @@ import net.ccbluex.liquidbounce.utils.block.BlockUtils.getCenterDistance import net.ccbluex.liquidbounce.utils.block.BlockUtils.searchBlocks import net.ccbluex.liquidbounce.utils.extensions.eyes import net.ccbluex.liquidbounce.utils.render.RenderUtils.drawBlockBox -import net.ccbluex.liquidbounce.utils.timer.TickTimer +import net.ccbluex.liquidbounce.utils.timing.TickTimer import net.ccbluex.liquidbounce.value.BoolValue import net.ccbluex.liquidbounce.value.FloatValue import net.ccbluex.liquidbounce.value.IntegerValue diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/world/Scaffold.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/world/Scaffold.kt index 2d8fd6b218d..b4e8a4d157c 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/world/Scaffold.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/world/Scaffold.kt @@ -3,6 +3,7 @@ * A free open source mixin-based injection hacked client for Minecraft using Minecraft Forge. * https://github.com/CCBlueX/LiquidBounce/ */ + package net.ccbluex.liquidbounce.features.module.modules.world import net.ccbluex.liquidbounce.event.* @@ -10,11 +11,12 @@ import net.ccbluex.liquidbounce.features.module.Module import net.ccbluex.liquidbounce.features.module.ModuleCategory import net.ccbluex.liquidbounce.features.module.modules.render.BlockOverlay import net.ccbluex.liquidbounce.ui.font.Fonts -import net.ccbluex.liquidbounce.utils.* -import net.ccbluex.liquidbounce.utils.InventoryUtils.serverSlot +import net.ccbluex.liquidbounce.utils.CPSCounter import net.ccbluex.liquidbounce.utils.MovementUtils.isMoving import net.ccbluex.liquidbounce.utils.MovementUtils.strafe import net.ccbluex.liquidbounce.utils.PacketUtils.sendPacket +import net.ccbluex.liquidbounce.utils.PlaceRotation +import net.ccbluex.liquidbounce.utils.Rotation import net.ccbluex.liquidbounce.utils.RotationUtils.getAngleDifference import net.ccbluex.liquidbounce.utils.RotationUtils.getRotationDifference import net.ccbluex.liquidbounce.utils.RotationUtils.getVectorForRotation @@ -27,12 +29,16 @@ import net.ccbluex.liquidbounce.utils.block.BlockUtils.getCenterDistance import net.ccbluex.liquidbounce.utils.block.BlockUtils.isReplaceable import net.ccbluex.liquidbounce.utils.block.PlaceInfo import net.ccbluex.liquidbounce.utils.extensions.* +import net.ccbluex.liquidbounce.utils.inventory.InventoryUtils +import net.ccbluex.liquidbounce.utils.inventory.InventoryUtils.serverSlot import net.ccbluex.liquidbounce.utils.misc.RandomUtils.nextFloat import net.ccbluex.liquidbounce.utils.render.RenderUtils.drawBlockBox import net.ccbluex.liquidbounce.utils.render.RenderUtils.drawBorderedRect -import net.ccbluex.liquidbounce.utils.timer.MSTimer -import net.ccbluex.liquidbounce.utils.timer.TimeUtils.randomClickDelay -import net.ccbluex.liquidbounce.utils.timer.TimeUtils.randomDelay +import net.ccbluex.liquidbounce.utils.timing.DelayTimer +import net.ccbluex.liquidbounce.utils.timing.MSTimer +import net.ccbluex.liquidbounce.utils.timing.TickDelayTimer +import net.ccbluex.liquidbounce.utils.timing.TimeUtils.randomClickDelay +import net.ccbluex.liquidbounce.utils.timing.TimeUtils.randomDelay import net.ccbluex.liquidbounce.value.BoolValue import net.ccbluex.liquidbounce.value.FloatValue import net.ccbluex.liquidbounce.value.IntegerValue @@ -43,7 +49,6 @@ import net.minecraft.client.renderer.GlStateManager.resetColor import net.minecraft.client.settings.GameSettings import net.minecraft.item.ItemBlock import net.minecraft.item.ItemStack -import net.minecraft.network.play.client.C09PacketHeldItemChange import net.minecraft.network.play.client.C0APacketAnimation import net.minecraft.network.play.client.C0BPacketEntityAction import net.minecraft.network.play.client.C0BPacketEntityAction.Action.START_SNEAKING @@ -68,22 +73,23 @@ object Scaffold : Module("Scaffold", ModuleCategory.WORLD, Keyboard.KEY_I) { private val expandLength by IntegerValue("ExpandLength", 1, 1..6) { mode == "Expand" } // Placeable delay - private val placeDelay: BoolValue = object : BoolValue("PlaceDelay", true) { + private val placeDelayValue: BoolValue = object : BoolValue("PlaceDelay", true) { override fun isSupported() = mode != "GodBridge" } private val maxDelayValue: IntegerValue = object : IntegerValue("MaxDelay", 0, 0..1000) { override fun onChange(oldValue: Int, newValue: Int) = newValue.coerceAtLeast(minDelay) - override fun isSupported() = placeDelay.isActive() + override fun isSupported() = placeDelayValue.isActive() } private val maxDelay by maxDelayValue - private val minDelay by object : IntegerValue("MinDelay", 0, 0..1000) { + private val minDelayValue = object : IntegerValue("MinDelay", 0, 0..1000) { override fun onChange(oldValue: Int, newValue: Int) = newValue.coerceAtMost(maxDelay) - override fun isSupported() = placeDelay.isActive() && !maxDelayValue.isMinimal() + override fun isSupported() = placeDelayValue.isActive() && !maxDelayValue.isMinimal() } + private val minDelay by minDelayValue // Extra clicks private val extraClicks by BoolValue("DoExtraClicks", false) @@ -189,9 +195,7 @@ object Scaffold : Module("Scaffold", ModuleCategory.WORLD, Keyboard.KEY_I) { private val rotationMode by ListValue("Rotations", arrayOf("Off", "Normal", "Stabilized"), "Normal") private val strafe by BoolValue("Strafe", false) { rotationMode != "Off" && silentRotation } private val silentRotation by BoolValue("SilentRotation", true) { rotationMode != "Off" } - private val keepRotation by object : BoolValue("KeepRotation", true) { - override fun isSupported() = rotationMode != "Off" - } + private val keepRotation by BoolValue("KeepRotation", true) { rotationMode != "Off" } private val keepTicks by object : IntegerValue("KeepTicks", 1, 1..20) { override fun onChange(oldValue: Int, newValue: Int) = newValue.coerceAtLeast(minimum) override fun isSupported() = rotationMode != "Off" && mode != "Telly" @@ -269,13 +273,12 @@ object Scaffold : Module("Scaffold", ModuleCategory.WORLD, Keyboard.KEY_I) { // Zitter private var zitterDirection = false - private var ticksSinceZitter = 0 // Delay - private val delayTimer = MSTimer() - private val zitterTimer = MSTimer() - private var zitterTicks = randomDelay(minZitterTicks, maxZitterTicks) - private var delay = 0 + private val delayTimer = object : DelayTimer(minDelayValue, maxDelayValue, MSTimer()) { + override fun hasTimePassed() = !placeDelayValue.isActive() || super.hasTimePassed() + } + private val zitterTickTimer = TickDelayTimer(minZitterTicksValue, maxZitterTicksValue) // Eagle private var placedBlocksWithoutEagle = 0 @@ -407,13 +410,11 @@ object Scaffold : Module("Scaffold", ModuleCategory.WORLD, Keyboard.KEY_I) { mc.gameSettings.keyBindLeft.pressed = false } - if (ticksSinceZitter >= zitterTicks) { - ticksSinceZitter = 0 + if (zitterTickTimer.hasTimePassed()) { zitterDirection = !zitterDirection - zitterTicks = randomDelay(minZitterTicks, maxZitterTicks) + zitterTickTimer.reset() } else { - ticksSinceZitter++ - zitterTimer.reset() + zitterTickTimer.update() } if (zitterDirection) { @@ -475,7 +476,7 @@ object Scaffold : Module("Scaffold", ModuleCategory.WORLD, Keyboard.KEY_I) { } if (target == null) { - if (placeDelay.isActive()) { + if (placeDelayValue.isActive()) { delayTimer.reset() } return @@ -572,10 +573,10 @@ object Scaffold : Module("Scaffold", ModuleCategory.WORLD, Keyboard.KEY_I) { val yaw = player.rotationYaw.toRadiansD() val x = if (omniDirectionalExpand) -sin(yaw).roundToInt() else player.horizontalFacing.directionVec.x val z = if (omniDirectionalExpand) cos(yaw).roundToInt() else player.horizontalFacing.directionVec.z - for (i in 0 until expandLength) { - if (search(blockPosition.add(x * i, 0, z * i), false, area)) { + + repeat(expandLength) { + if (search(blockPosition.add(x * it, 0, z * it), false, area)) return - } } return } @@ -607,9 +608,8 @@ object Scaffold : Module("Scaffold", ModuleCategory.WORLD, Keyboard.KEY_I) { val player = mc.thePlayer ?: return val world = mc.theWorld ?: return - if (!delayTimer.hasTimePassed(delay) || shouldKeepLaunchPosition && launchY - 1 != placeInfo.vec3.yCoord.toInt()) { + if (!delayTimer.hasTimePassed() || shouldKeepLaunchPosition && launchY - 1 != placeInfo.vec3.yCoord.toInt()) return - } var itemStack = player.inventoryContainer.getSlot(serverSlot + 36).stack @@ -629,11 +629,7 @@ object Scaffold : Module("Scaffold", ModuleCategory.WORLD, Keyboard.KEY_I) { mc.playerController.updateController() } - "spoof", "switch" -> { - if (blockSlot - 36 != serverSlot) { - sendPacket(C09PacketHeldItemChange(blockSlot - 36)) - } - } + "spoof", "switch" -> serverSlot = blockSlot - 36 } itemStack = player.inventoryContainer.getSlot(blockSlot).stack } @@ -643,7 +639,6 @@ object Scaffold : Module("Scaffold", ModuleCategory.WORLD, Keyboard.KEY_I) { ) ) { delayTimer.reset() - delay = if (!placeDelay.isActive()) 0 else randomDelay(minDelay, maxDelay) if (player.onGround) { player.motionX *= speedModifier @@ -667,11 +662,8 @@ object Scaffold : Module("Scaffold", ModuleCategory.WORLD, Keyboard.KEY_I) { } } - if (autoBlock == "Switch") { - if (serverSlot != player.inventory.currentItem) { - sendPacket(C09PacketHeldItemChange(player.inventory.currentItem)) - } - } + if (autoBlock == "Switch") + serverSlot = player.inventory.currentItem // Since we violate vanilla slot switch logic if we send the packets now, we arrange them for the next tick switchBlockNextTickIfPossible(itemStack) @@ -767,11 +759,9 @@ object Scaffold : Module("Scaffold", ModuleCategory.WORLD, Keyboard.KEY_I) { placeRotation = null mc.timer.timerSpeed = 1f - if (serverSlot != player.inventory.currentItem) { - sendPacket(C09PacketHeldItemChange(player.inventory.currentItem)) - } + serverSlot = player.inventory.currentItem - TickedActions.clear(this) + TickScheduler.clear() } // Entity movement event @@ -847,20 +837,20 @@ object Scaffold : Module("Scaffold", ModuleCategory.WORLD, Keyboard.KEY_I) { return } - for (i in 0 until if (mode == "Expand") expandLength + 1 else 2) { + repeat(if (mode == "Expand") expandLength + 1 else 2) { val yaw = player.rotationYaw.toRadiansD() val x = if (omniDirectionalExpand) -sin(yaw).roundToInt() else player.horizontalFacing.directionVec.x val z = if (omniDirectionalExpand) cos(yaw).roundToInt() else player.horizontalFacing.directionVec.z val blockPos = BlockPos( - player.posX + x * i, + player.posX + x * it, if (shouldKeepLaunchPosition && launchY <= player.posY) launchY - 1.0 else player.posY - (if (player.posY == player.posY + 0.5) 0.0 else 1.0) - if (shouldGoDown) 1.0 else 0.0, - player.posZ + z * i + player.posZ + z * it ) val placeInfo = PlaceInfo.get(blockPos) if (isReplaceable(blockPos) && placeInfo != null) { drawBlockBox(blockPos, Color(68, 117, 255, 100), false) - break + return } } } @@ -1112,14 +1102,14 @@ object Scaffold : Module("Scaffold", ModuleCategory.WORLD, Keyboard.KEY_I) { if (autoBlock !in arrayOf("Off", "Switch") && stack.stackSize <= 0) { InventoryUtils.findBlockInHotbar()?.let { - TickedActions.add({ + TickScheduler += { if (autoBlock == "Pick") { player.inventory.currentItem = it - 36 mc.playerController.updateController() } else { - sendPacket(C09PacketHeldItemChange(it - 36)) + serverSlot = it - 36 } - }, 1, this) + } } } } @@ -1149,12 +1139,7 @@ object Scaffold : Module("Scaffold", ModuleCategory.WORLD, Keyboard.KEY_I) { // The target rotation will either be the module's placeRotation or a forced rotation (usually that's where the GodBridge mode aims) val targetRotation = run { val yaw = arrayOf(-135f, -45f, 45f, 135f).minByOrNull { - abs( - getAngleDifference( - it, - MathHelper.wrapAngleTo180_float(currRotation.yaw) - ) - ) + abs(getAngleDifference(it, MathHelper.wrapAngleTo180_float(currRotation.yaw))) } ?: return placeRotation?.rotation ?: Rotation(yaw, 73f) diff --git a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/world/Tower.kt b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/world/Tower.kt index a6739778262..e8397c3e5f8 100644 --- a/src/main/java/net/ccbluex/liquidbounce/features/module/modules/world/Tower.kt +++ b/src/main/java/net/ccbluex/liquidbounce/features/module/modules/world/Tower.kt @@ -10,8 +10,6 @@ import net.ccbluex.liquidbounce.features.module.Module import net.ccbluex.liquidbounce.features.module.ModuleCategory import net.ccbluex.liquidbounce.features.module.modules.render.BlockOverlay import net.ccbluex.liquidbounce.ui.font.Fonts -import net.ccbluex.liquidbounce.utils.InventoryUtils -import net.ccbluex.liquidbounce.utils.InventoryUtils.serverSlot import net.ccbluex.liquidbounce.utils.PacketUtils.sendPacket import net.ccbluex.liquidbounce.utils.PacketUtils.sendPackets import net.ccbluex.liquidbounce.utils.PlaceRotation @@ -26,8 +24,10 @@ import net.ccbluex.liquidbounce.utils.block.BlockUtils.getBlock import net.ccbluex.liquidbounce.utils.block.BlockUtils.isReplaceable import net.ccbluex.liquidbounce.utils.block.PlaceInfo import net.ccbluex.liquidbounce.utils.extensions.* +import net.ccbluex.liquidbounce.utils.inventory.InventoryUtils +import net.ccbluex.liquidbounce.utils.inventory.InventoryUtils.serverSlot import net.ccbluex.liquidbounce.utils.render.RenderUtils.drawBorderedRect -import net.ccbluex.liquidbounce.utils.timer.TickTimer +import net.ccbluex.liquidbounce.utils.timing.TickTimer import net.ccbluex.liquidbounce.value.BoolValue import net.ccbluex.liquidbounce.value.FloatValue import net.ccbluex.liquidbounce.value.IntegerValue @@ -38,7 +38,6 @@ import net.minecraft.client.renderer.GlStateManager.resetColor import net.minecraft.init.Blocks.air import net.minecraft.item.ItemBlock import net.minecraft.network.play.client.C03PacketPlayer.C04PacketPlayerPosition -import net.minecraft.network.play.client.C09PacketHeldItemChange import net.minecraft.network.play.client.C0APacketAnimation import net.minecraft.stats.StatList import net.minecraft.util.BlockPos @@ -105,9 +104,7 @@ object Tower : Module("Tower", ModuleCategory.WORLD, Keyboard.KEY_O) { mc.timer.timerSpeed = 1f lockRotation = null - if (serverSlot != thePlayer.inventory.currentItem) { - sendPacket(C09PacketHeldItemChange(thePlayer.inventory.currentItem)) - } + serverSlot = thePlayer.inventory.currentItem } @EventTarget @@ -262,11 +259,7 @@ object Tower : Module("Tower", ModuleCategory.WORLD, Keyboard.KEY_O) { mc.playerController.updateController() } - "Spoof", "Switch" -> { - if (blockSlot - 36 != serverSlot) { - sendPacket(C09PacketHeldItemChange(blockSlot - 36)) - } - } + "Spoof", "Switch" -> serverSlot = blockSlot - 36 } itemStack = thePlayer.inventoryContainer.getSlot(blockSlot).stack } @@ -282,8 +275,9 @@ object Tower : Module("Tower", ModuleCategory.WORLD, Keyboard.KEY_O) { sendPacket(C0APacketAnimation()) } } - if (autoBlock == "Switch" && serverSlot != mc.thePlayer.inventory.currentItem) - sendPacket(C09PacketHeldItemChange(mc.thePlayer.inventory.currentItem)) + + if (autoBlock == "Switch") + serverSlot = thePlayer.inventory.currentItem placeInfo = null } diff --git a/src/main/java/net/ccbluex/liquidbounce/injection/forge/mixins/entity/MixinEntityLivingBase.java b/src/main/java/net/ccbluex/liquidbounce/injection/forge/mixins/entity/MixinEntityLivingBase.java index 42611347f13..2fa9791f25b 100644 --- a/src/main/java/net/ccbluex/liquidbounce/injection/forge/mixins/entity/MixinEntityLivingBase.java +++ b/src/main/java/net/ccbluex/liquidbounce/injection/forge/mixins/entity/MixinEntityLivingBase.java @@ -16,6 +16,7 @@ import net.ccbluex.liquidbounce.utils.MovementUtils; import net.ccbluex.liquidbounce.utils.Rotation; import net.ccbluex.liquidbounce.utils.RotationUtils; +import net.ccbluex.liquidbounce.utils.extensions.MathExtensionsKt; import net.minecraft.block.Block; import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.entity.EntityLivingBase; @@ -96,7 +97,7 @@ protected void jump() { final Sprint sprint = Sprint.INSTANCE; if (sprint.getState() && sprint.getAllDirections() && sprint.getJumpDirections()) { - fixedYaw += MovementUtils.INSTANCE.getMovingYaw() - this.rotationYaw; + fixedYaw += MathExtensionsKt.toDegreesF(MovementUtils.INSTANCE.getDirection()) - this.rotationYaw; } final float f = fixedYaw * 0.017453292F; diff --git a/src/main/java/net/ccbluex/liquidbounce/injection/forge/mixins/entity/MixinPlayerControllerMP.java b/src/main/java/net/ccbluex/liquidbounce/injection/forge/mixins/entity/MixinPlayerControllerMP.java index 3c7a90d23e0..c9c1ede3963 100644 --- a/src/main/java/net/ccbluex/liquidbounce/injection/forge/mixins/entity/MixinPlayerControllerMP.java +++ b/src/main/java/net/ccbluex/liquidbounce/injection/forge/mixins/entity/MixinPlayerControllerMP.java @@ -10,7 +10,7 @@ import net.ccbluex.liquidbounce.event.EventManager; import net.ccbluex.liquidbounce.features.module.modules.exploit.AbortBreaking; import net.ccbluex.liquidbounce.utils.CooldownHelper; -import net.ccbluex.liquidbounce.utils.InventoryUtils; +import net.ccbluex.liquidbounce.utils.inventory.InventoryUtils; import net.minecraft.client.multiplayer.PlayerControllerMP; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; diff --git a/src/main/java/net/ccbluex/liquidbounce/script/Script.kt b/src/main/java/net/ccbluex/liquidbounce/script/Script.kt index 90c51fa323b..bdc83e15699 100644 --- a/src/main/java/net/ccbluex/liquidbounce/script/Script.kt +++ b/src/main/java/net/ccbluex/liquidbounce/script/Script.kt @@ -9,7 +9,6 @@ import jdk.internal.dynalink.beans.StaticClass import jdk.nashorn.api.scripting.JSObject import jdk.nashorn.api.scripting.NashornScriptEngineFactory import jdk.nashorn.api.scripting.ScriptUtils -import net.ccbluex.liquidbounce.LiquidBounce import net.ccbluex.liquidbounce.LiquidBounce.commandManager import net.ccbluex.liquidbounce.LiquidBounce.moduleManager import net.ccbluex.liquidbounce.LiquidBounce.scriptManager @@ -41,7 +40,7 @@ class Script(val scriptFile: File) : MinecraftInstance() { private var state = false - private val events = HashMap() + private val events = mutableMapOf() private val registeredModules = mutableListOf() private val registeredCommands = mutableListOf() @@ -51,19 +50,21 @@ class Script(val scriptFile: File) : MinecraftInstance() { scriptEngine = NashornScriptEngineFactory().getScriptEngine(*engineFlags) // Global classes - scriptEngine.put("Chat", StaticClass.forClass(Chat::class.java)) - scriptEngine.put("Setting", StaticClass.forClass(Setting::class.java)) - scriptEngine.put("Item", StaticClass.forClass(Item::class.java)) + scriptEngine.run { + put("Chat", StaticClass.forClass(Chat::class.java)) + put("Setting", StaticClass.forClass(Setting::class.java)) + put("Item", StaticClass.forClass(Item::class.java)) - // Global instances - scriptEngine.put("mc", mc) + // Global instances + put("mc", mc) - scriptEngine.put("moduleManager", moduleManager) - scriptEngine.put("commandManager", commandManager) - scriptEngine.put("scriptManager", scriptManager) + put("moduleManager", moduleManager) + put("commandManager", commandManager) + put("scriptManager", scriptManager) - // Global functions - scriptEngine.put("registerScript", RegisterScript()) + // Global functions + put("registerScript", RegisterScript()) + } } fun initScript() { diff --git a/src/main/java/net/ccbluex/liquidbounce/script/api/ScriptTab.kt b/src/main/java/net/ccbluex/liquidbounce/script/api/ScriptTab.kt index f4bc0f068fb..a11a9c5ac4e 100644 --- a/src/main/java/net/ccbluex/liquidbounce/script/api/ScriptTab.kt +++ b/src/main/java/net/ccbluex/liquidbounce/script/api/ScriptTab.kt @@ -7,7 +7,7 @@ package net.ccbluex.liquidbounce.script.api import jdk.nashorn.api.scripting.JSObject import jdk.nashorn.api.scripting.ScriptUtils -import net.ccbluex.liquidbounce.utils.item.ItemUtils +import net.ccbluex.liquidbounce.utils.inventory.ItemUtils import net.minecraft.creativetab.CreativeTabs import net.minecraft.item.ItemStack diff --git a/src/main/java/net/ccbluex/liquidbounce/script/api/global/Item.kt b/src/main/java/net/ccbluex/liquidbounce/script/api/global/Item.kt index 0486b89c192..509eeefaf40 100644 --- a/src/main/java/net/ccbluex/liquidbounce/script/api/global/Item.kt +++ b/src/main/java/net/ccbluex/liquidbounce/script/api/global/Item.kt @@ -5,7 +5,7 @@ */ package net.ccbluex.liquidbounce.script.api.global -import net.ccbluex.liquidbounce.utils.item.ItemUtils +import net.ccbluex.liquidbounce.utils.inventory.ItemUtils import net.minecraft.item.ItemStack /** diff --git a/src/main/java/net/ccbluex/liquidbounce/tabs/ExploitsTab.kt b/src/main/java/net/ccbluex/liquidbounce/tabs/ExploitsTab.kt index 452e8c5523d..ae56efaaae8 100644 --- a/src/main/java/net/ccbluex/liquidbounce/tabs/ExploitsTab.kt +++ b/src/main/java/net/ccbluex/liquidbounce/tabs/ExploitsTab.kt @@ -5,7 +5,7 @@ */ package net.ccbluex.liquidbounce.tabs -import net.ccbluex.liquidbounce.utils.item.ItemUtils +import net.ccbluex.liquidbounce.utils.inventory.ItemUtils import net.minecraft.creativetab.CreativeTabs import net.minecraft.init.Blocks import net.minecraft.init.Items diff --git a/src/main/java/net/ccbluex/liquidbounce/tabs/HeadsTab.kt b/src/main/java/net/ccbluex/liquidbounce/tabs/HeadsTab.kt index 6c3583f2c2b..cb1c95ec6f6 100644 --- a/src/main/java/net/ccbluex/liquidbounce/tabs/HeadsTab.kt +++ b/src/main/java/net/ccbluex/liquidbounce/tabs/HeadsTab.kt @@ -8,7 +8,7 @@ package net.ccbluex.liquidbounce.tabs import com.google.gson.JsonParser import net.ccbluex.liquidbounce.LiquidBounce.CLIENT_CLOUD import net.ccbluex.liquidbounce.utils.ClientUtils.LOGGER -import net.ccbluex.liquidbounce.utils.item.ItemUtils +import net.ccbluex.liquidbounce.utils.inventory.ItemUtils import net.ccbluex.liquidbounce.utils.misc.HttpUtils.get import net.minecraft.creativetab.CreativeTabs import net.minecraft.init.Items diff --git a/src/main/java/net/ccbluex/liquidbounce/ui/client/GuiMainMenu.kt b/src/main/java/net/ccbluex/liquidbounce/ui/client/GuiMainMenu.kt index 167ff0433a2..8c6f8d0f0d5 100644 --- a/src/main/java/net/ccbluex/liquidbounce/ui/client/GuiMainMenu.kt +++ b/src/main/java/net/ccbluex/liquidbounce/ui/client/GuiMainMenu.kt @@ -46,7 +46,7 @@ class GuiMainMenu : GuiScreen() { Fonts.fontBold180.drawCenteredString(CLIENT_NAME, width / 2F, height / 8F, 4673984, true) Fonts.font35.drawCenteredString(clientVersionText, width / 2F + 148, height / 8F + Fonts.font35.fontHeight, 0xffffff, true) - val messageOfTheDay = messageOfTheDay?.message; + val messageOfTheDay = messageOfTheDay?.message if (messageOfTheDay?.isNotBlank() == true) { // Draw rect below main rect and within draw MOTD text drawRect(width / 2f - 115, height / 4f + 190, width / 2f + 115, height / 4f + 200 + Fonts.font35.fontHeight, Integer.MIN_VALUE) diff --git a/src/main/java/net/ccbluex/liquidbounce/utils/CoroutineUtils.kt b/src/main/java/net/ccbluex/liquidbounce/utils/CoroutineUtils.kt new file mode 100644 index 00000000000..b1e4887faf1 --- /dev/null +++ b/src/main/java/net/ccbluex/liquidbounce/utils/CoroutineUtils.kt @@ -0,0 +1,8 @@ +package net.ccbluex.liquidbounce.utils + +@Suppress("ControlFlowWithEmptyBody") +object CoroutineUtils { + fun waitUntil(condition: () -> Boolean) { + while (!condition()) {} + } +} \ No newline at end of file diff --git a/src/main/java/net/ccbluex/liquidbounce/utils/MovementUtils.kt b/src/main/java/net/ccbluex/liquidbounce/utils/MovementUtils.kt index 233911e369e..9ce23e7ece3 100644 --- a/src/main/java/net/ccbluex/liquidbounce/utils/MovementUtils.kt +++ b/src/main/java/net/ccbluex/liquidbounce/utils/MovementUtils.kt @@ -5,61 +5,92 @@ */ package net.ccbluex.liquidbounce.utils +import net.ccbluex.liquidbounce.event.EventTarget +import net.ccbluex.liquidbounce.event.Listenable +import net.ccbluex.liquidbounce.event.PacketEvent import net.ccbluex.liquidbounce.utils.extensions.stopXZ import net.ccbluex.liquidbounce.utils.extensions.toRadiansD +import net.minecraft.network.play.client.C03PacketPlayer import kotlin.math.cos import kotlin.math.sin import kotlin.math.sqrt -object MovementUtils : MinecraftInstance() { +object MovementUtils : MinecraftInstance(), Listenable { var speed - get() = sqrt(mc.thePlayer.motionX * mc.thePlayer.motionX + mc.thePlayer.motionZ * mc.thePlayer.motionZ).toFloat() - set(value) = strafe(value) + get() = mc.thePlayer?.run { sqrt(motionX * motionX + motionZ * motionZ).toFloat() } ?: .0f + set(value) { strafe(value) } val isMoving - get() = mc.thePlayer != null && (mc.thePlayer.movementInput.moveForward != 0f || mc.thePlayer.movementInput.moveStrafe != 0f) - - val movingYaw: Float - get() = (direction * 180f / Math.PI).toFloat() + get() = mc.thePlayer?.movementInput?.run { moveForward != 0f || moveStrafe != 0f } ?: false val hasMotion - get() = mc.thePlayer.motionX != 0.0 && mc.thePlayer.motionZ != 0.0 && mc.thePlayer.motionY != 0.0 + get() = mc.thePlayer?.run { motionX != .0 || motionY != .0 || motionZ != .0 } ?: false - fun strafe(speed: Float = this.speed, stopWhenNoInput: Boolean = false) { - if (!isMoving) { - if (stopWhenNoInput) - mc.thePlayer.stopXZ() + fun strafe(speed: Float = this.speed, stopWhenNoInput: Boolean = false) = + mc.thePlayer?.run { + if (!isMoving) { + if (stopWhenNoInput) + stopXZ() - return + return@run + } + + val yaw = direction + motionX = -sin(yaw) * speed + motionZ = cos(yaw) * speed } - val yaw = direction - mc.thePlayer.motionX = -sin(yaw) * speed - mc.thePlayer.motionZ = cos(yaw) * speed - } + fun forward(distance: Double) = + mc.thePlayer?.run { + val yaw = rotationYaw.toRadiansD() + setPosition(posX - sin(yaw) * distance, posY, posZ + cos(yaw) * distance) + } - fun forward(length: Double) { - val thePlayer = mc.thePlayer ?: return - val yaw = thePlayer.rotationYaw.toRadiansD() - thePlayer.setPosition(thePlayer.posX + -sin(yaw) * length, thePlayer.posY, thePlayer.posZ + cos(yaw) * length) - } + val direction + get() = mc.thePlayer?.run { + var yaw = rotationYaw + var forward = 1f - val direction: Double - get() { - val thePlayer = mc.thePlayer - var rotationYaw = thePlayer.rotationYaw - if (thePlayer.moveForward < 0f) rotationYaw += 180f - var forward = 1f - if (thePlayer.moveForward < 0f) forward = -0.5f else if (thePlayer.moveForward > 0f) forward = 0.5f - if (thePlayer.moveStrafing > 0f) rotationYaw -= 90f * forward - if (thePlayer.moveStrafing < 0f) rotationYaw += 90f * forward - return rotationYaw.toRadiansD() - } + if (moveForward < 0f) { + yaw += 180f + forward = -0.5f + } else if (moveForward > 0f) + forward = 0.5f + + if (moveStrafing < 0f) yaw += 90f * forward + else if (moveStrafing > 0f) yaw -= 90f * forward + + yaw.toRadiansD() + } ?: 0.0 fun isOnGround(height: Double) = - mc.theWorld.getCollidingBoundingBoxes( - mc.thePlayer, - mc.thePlayer.entityBoundingBox.offset(0.0, -height, 0.0) - ).isNotEmpty() + mc.theWorld != null && mc.thePlayer != null && + mc.theWorld.getCollidingBoundingBoxes(mc.thePlayer, mc.thePlayer.entityBoundingBox.offset(0.0, -height, 0.0)).isNotEmpty() + + var serverOnGround = false + + var serverX = .0 + var serverY = .0 + var serverZ = .0 + + @EventTarget + fun onPacket(event: PacketEvent) { + if (event.isCancelled) + return + + val packet = event.packet + + if (packet is C03PacketPlayer) { + serverOnGround = packet.onGround + + if (packet.isMoving) { + serverX = packet.x + serverY = packet.y + serverZ = packet.z + } + } + } + + override fun handleEvents() = true } \ No newline at end of file diff --git a/src/main/java/net/ccbluex/liquidbounce/utils/TickedActions.kt b/src/main/java/net/ccbluex/liquidbounce/utils/TickedActions.kt deleted file mode 100644 index 3fece2b9f63..00000000000 --- a/src/main/java/net/ccbluex/liquidbounce/utils/TickedActions.kt +++ /dev/null @@ -1,54 +0,0 @@ -/* - * LiquidBounce Hacked Client - * A free open source mixin-based injection hacked client for Minecraft using Minecraft Forge. - * https://github.com/CCBlueX/LiquidBounce/ - */ -package net.ccbluex.liquidbounce.utils - -import com.google.common.collect.HashBasedTable -import com.google.common.collect.Table -import com.google.common.collect.Tables -import net.ccbluex.liquidbounce.event.EventTarget -import net.ccbluex.liquidbounce.event.Listenable -import net.ccbluex.liquidbounce.event.TickEvent -import net.ccbluex.liquidbounce.event.WorldEvent -import net.ccbluex.liquidbounce.features.module.Module - -object TickedActions : Listenable { - - private val actions: Table Unit, Int> = HashBasedTable.create() - - fun add(action: () -> Unit, id: Int, module: Module): Boolean { - val cell = Tables.immutableCell(module, action, id) - - if (!actions.cellSet().contains(cell)) { - actions.put(cell.rowKey, cell.columnKey, cell.value) - return true - } - - return false - } - - fun containsId(id: Int, module: Module): Boolean = - actions.cellSet().count { it.value == id && it.rowKey == module } == 1 - - fun clear(module: Module) { - actions.cellSet().removeIf { it.rowKey == module } - } - - @EventTarget(priority = 1) - fun onTick(event: TickEvent) { - for (action in actions.cellSet()) { - action.columnKey.invoke() - } - - actions.clear() - } - - @EventTarget - fun onWorld(event: WorldEvent) { - actions.clear() - } - - override fun handleEvents() = true -} \ No newline at end of file diff --git a/src/main/java/net/ccbluex/liquidbounce/utils/block/BlockUtils.kt b/src/main/java/net/ccbluex/liquidbounce/utils/block/BlockUtils.kt index bab7cf4941a..fa8d55a1114 100644 --- a/src/main/java/net/ccbluex/liquidbounce/utils/block/BlockUtils.kt +++ b/src/main/java/net/ccbluex/liquidbounce/utils/block/BlockUtils.kt @@ -6,9 +6,7 @@ package net.ccbluex.liquidbounce.utils.block import net.ccbluex.liquidbounce.utils.MinecraftInstance -import net.minecraft.block.Block -import net.minecraft.block.BlockContainer -import net.minecraft.block.BlockWorkbench +import net.minecraft.block.* import net.minecraft.block.state.IBlockState import net.minecraft.entity.item.EntityFallingBlock import net.minecraft.util.AxisAlignedBB @@ -44,14 +42,10 @@ object BlockUtils : MinecraftInstance() { val state = getState(blockPos) ?: return false val block = state.block ?: return false - return block.canCollideCheck( - state, - false - ) && blockPos in mc.theWorld.worldBorder && !block.material.isReplaceable && !block.hasTileEntity(state) && isFullBlock( - blockPos, - state, - true - ) && mc.theWorld.loadedEntityList.find { it is EntityFallingBlock && it.position == blockPos } == null && block !is BlockContainer && block !is BlockWorkbench + return block.canCollideCheck(state, false) && blockPos in mc.theWorld.worldBorder && !block.material.isReplaceable + && !block.hasTileEntity(state) && isFullBlock(blockPos, state, true) + && mc.theWorld.loadedEntityList.find { it is EntityFallingBlock && it.position == blockPos } == null + && block !is BlockContainer && block !is BlockWorkbench } /** @@ -71,8 +65,19 @@ object BlockUtils : MinecraftInstance() { return box.maxX - box.minX == 1.0 && (box.maxY - box.minY == 1.0 || supportSlabs && box.maxY % 1.0 == 0.0) && box.maxZ - box.minZ == 1.0 } - fun isFullBlock(block: Block) = - block.blockBoundsMaxX == 1.0 && block.blockBoundsMaxY == 1.0 && block.blockBoundsMaxZ == 1.0 + fun isFullBlock(block: Block): Boolean { + when (block) { + // Soul Sand is considered as full block?! + is BlockSoulSand -> return false + + // Glass isn't considered as full block?! + is BlockGlass, is BlockStainedGlass -> return true + } + + // Many translucent or non-full blocks have blockBounds set to 1.0 + return block.isFullBlock && block.isBlockNormalCube && + block.blockBoundsMaxX == 1.0 && block.blockBoundsMaxY == 1.0 && block.blockBoundsMaxZ == 1.0 + } /** * Get distance to center of [blockPos] diff --git a/src/main/java/net/ccbluex/liquidbounce/utils/extensions/MathExtensions.kt b/src/main/java/net/ccbluex/liquidbounce/utils/extensions/MathExtensions.kt index 2eac474a07a..93544ca7195 100644 --- a/src/main/java/net/ccbluex/liquidbounce/utils/extensions/MathExtensions.kt +++ b/src/main/java/net/ccbluex/liquidbounce/utils/extensions/MathExtensions.kt @@ -77,4 +77,10 @@ class RangeIterator(private val range: ClosedFloatingPointRange, private } } operator fun ClosedFloatingPointRange.iterator() = RangeIterator(this) -infix fun ClosedFloatingPointRange.step(step: Double) = RangeIterator(this, step) \ No newline at end of file +infix fun ClosedFloatingPointRange.step(step: Double) = RangeIterator(this, step) + +/** + * Conditionally shuffles an `Iterable` + * @param shuffle determines if the returned `Iterable` is shuffled + */ +fun Iterable.shuffled(shuffle: Boolean) = toMutableList().apply { if (shuffle) shuffle() } \ No newline at end of file diff --git a/src/main/java/net/ccbluex/liquidbounce/utils/item/ArmorComparator.java b/src/main/java/net/ccbluex/liquidbounce/utils/inventory/ArmorComparator.java similarity index 95% rename from src/main/java/net/ccbluex/liquidbounce/utils/item/ArmorComparator.java rename to src/main/java/net/ccbluex/liquidbounce/utils/inventory/ArmorComparator.java index 7f6795b673e..c0c6756acf3 100644 --- a/src/main/java/net/ccbluex/liquidbounce/utils/item/ArmorComparator.java +++ b/src/main/java/net/ccbluex/liquidbounce/utils/inventory/ArmorComparator.java @@ -3,7 +3,7 @@ * A free open source mixin-based injection hacked client for Minecraft using Minecraft Forge. * https://github.com/CCBlueX/LiquidBounce/ */ -package net.ccbluex.liquidbounce.utils.item; +package net.ccbluex.liquidbounce.utils.inventory; import net.ccbluex.liquidbounce.utils.MinecraftInstance; import net.minecraft.enchantment.Enchantment; @@ -14,8 +14,8 @@ import java.math.RoundingMode; import java.util.Comparator; -import static net.ccbluex.liquidbounce.utils.item.ItemUtilsKt.getEnchantmentCount; -import static net.ccbluex.liquidbounce.utils.item.ItemUtilsKt.getEnchantmentLevel; +import static net.ccbluex.liquidbounce.utils.inventory.ItemUtilsKt.getEnchantmentCount; +import static net.ccbluex.liquidbounce.utils.inventory.ItemUtilsKt.getEnchantmentLevel; public class ArmorComparator extends MinecraftInstance implements Comparator { diff --git a/src/main/java/net/ccbluex/liquidbounce/utils/item/ArmorPiece.java b/src/main/java/net/ccbluex/liquidbounce/utils/inventory/ArmorPiece.java similarity index 93% rename from src/main/java/net/ccbluex/liquidbounce/utils/item/ArmorPiece.java rename to src/main/java/net/ccbluex/liquidbounce/utils/inventory/ArmorPiece.java index 1457a1cafd2..d601fe55148 100644 --- a/src/main/java/net/ccbluex/liquidbounce/utils/item/ArmorPiece.java +++ b/src/main/java/net/ccbluex/liquidbounce/utils/inventory/ArmorPiece.java @@ -3,7 +3,7 @@ * A free open source mixin-based injection hacked client for Minecraft using Minecraft Forge. * https://github.com/CCBlueX/LiquidBounce/ */ -package net.ccbluex.liquidbounce.utils.item; +package net.ccbluex.liquidbounce.utils.inventory; import net.minecraft.item.ItemArmor; diff --git a/src/main/java/net/ccbluex/liquidbounce/utils/inventory/CoroutineArmorComparator.kt b/src/main/java/net/ccbluex/liquidbounce/utils/inventory/CoroutineArmorComparator.kt new file mode 100644 index 00000000000..a24b0cc246c --- /dev/null +++ b/src/main/java/net/ccbluex/liquidbounce/utils/inventory/CoroutineArmorComparator.kt @@ -0,0 +1,129 @@ +package net.ccbluex.liquidbounce.utils.inventory + +import net.ccbluex.liquidbounce.utils.MinecraftInstance +import net.minecraft.enchantment.Enchantment +import net.minecraft.entity.item.EntityItem +import net.minecraft.item.ItemArmor +import net.minecraft.item.ItemStack +import kotlin.math.ceil + +object CoroutineArmorComparator: MinecraftInstance() { + fun getBestArmorSet(stacks: List, entityStacksMap: Map? = null): ArmorSet? { + val thePlayer = mc.thePlayer ?: return null + + val armorMap = ( + ( + // Consider dropped armor pieces + if (!entityStacksMap.isNullOrEmpty()) + entityStacksMap.keys.mapNotNull { stack -> + if (stack.item is ItemArmor) -1 to stack + else null + } + else emptyList() + ) + ( + // Consider currently equipped armor, when searching useful stuff in chests + // Index is null for equipped armor when searching through a chest to prevent any accidental impossible interactions + if (thePlayer.openContainer.windowId != 0) + thePlayer.inventory.armorInventory.mapNotNull { null to (it ?: return@mapNotNull null) } + else emptyList() + ) + ( + stacks + .mapIndexedNotNull { index, itemStack -> + if (itemStack?.item is ItemArmor) index to itemStack + else null + } + ) + ) + .sortedBy { (index, stack) -> + // Sort items by distance from player, equipped items are always preferred with distance -1 + if (index == -1) + thePlayer.getDistanceSqToEntity(entityStacksMap?.get(stack) ?: return@sortedBy -1.0) + else -1.0 + } + // Prioritise sets that are in lower parts of inventory (not in chest) or equipped, prevents stealing multiple armor duplicates. + .sortedByDescending { it.first ?: Int.MAX_VALUE } + // Prioritise sets with more durability, enchantments + .sortedByDescending { it.second.totalDurability } + .sortedByDescending { it.second.enchantmentCount } + .sortedByDescending { it.second.enchantmentSum } + .groupBy { (it.second.item as ItemArmor).armorType } + + val helmets = armorMap[0] ?: NULL_LIST + val chestplates = armorMap[1] ?: NULL_LIST + val leggings = armorMap[2] ?: NULL_LIST + val boots = armorMap[3] ?: NULL_LIST + + val armorCombinations = + helmets.flatMap { helmet -> + chestplates.flatMap { chestplate -> + leggings.flatMap { leggings -> + boots.map { boots -> + ArmorSet(helmet, chestplate, leggings, boots) + } + } + } + } + // Prioritise armor sets that are mostly equipped + .sortedByDescending { set -> + set.count { + // Equipped items are additionally added to stacks map, when searching through a chest. + // Their slot ids are set to null, in order to make them easily distinguishable from real items in the chest. + it != null && (it.first == null || it.first in 5..8) + } + } + + return armorCombinations.maxByOrNull { it.defenseFactor } + } +} + +class ArmorSet(private vararg val armorPairs: Pair?) : Iterable?> { + /** + * 1.4.6 - 1.8.9 Armor calculations + * https://minecraft.fandom.com/wiki/Armor?oldid=927013#Enchantments + * + * @return Average defense of the whole armor set. + */ + val defenseFactor by lazy { + var baseDefensePercentage = 0 + var epf = 0 + + forEach { pair -> + val stack = pair?.second ?: return@forEach + val item = stack.item as ItemArmor + baseDefensePercentage += item.armorMaterial.getDamageReductionAmount(item.armorType) * 4 + + val protectionLvl = stack.getEnchantmentLevel(Enchantment.protection) + + // Protection 4 has enchantment protection factor hardcoded to 5, other levels are equal to their epf (see wiki) + epf += if (protectionLvl == 4) 5 else protectionLvl + } + + val baseDefense = baseDefensePercentage / 100f + + baseDefense + (1 - baseDefense) * ceil(epf.coerceAtMost(25) * 0.75f) * 0.04f + } + + override fun iterator() = armorPairs.iterator() + + operator fun contains(stack: ItemStack) = armorPairs.any { it?.second == stack } + + operator fun contains(index: Int) = armorPairs.any { it?.first == index } + + fun indexOf(stack: ItemStack) = armorPairs.find { it?.second == stack }?.first ?: -1 + + operator fun get(index: Int) = armorPairs.getOrNull(index) + + val helmet + get() = armorPairs[0]?.second + + val chestplate + get() = armorPairs[1]?.second + + val leggings + get() = armorPairs[2]?.second + + val boots + get() = armorPairs[3]?.second +} + +private val NULL_LIST = listOf?>(null) \ No newline at end of file diff --git a/src/main/java/net/ccbluex/liquidbounce/utils/inventory/InventoryManager.kt b/src/main/java/net/ccbluex/liquidbounce/utils/inventory/InventoryManager.kt new file mode 100644 index 00000000000..2a2789a7aa4 --- /dev/null +++ b/src/main/java/net/ccbluex/liquidbounce/utils/inventory/InventoryManager.kt @@ -0,0 +1,141 @@ +package net.ccbluex.liquidbounce.utils.inventory + +import kotlinx.coroutines.* +import net.ccbluex.liquidbounce.features.module.modules.beta.CoroutineArmorer +import net.ccbluex.liquidbounce.features.module.modules.beta.CoroutineCleaner +import net.ccbluex.liquidbounce.features.module.modules.beta.CoroutineStealer +import net.ccbluex.liquidbounce.utils.ClientUtils.displayChatMessage +import net.ccbluex.liquidbounce.utils.MinecraftInstance +import net.ccbluex.liquidbounce.utils.MovementUtils.isMoving +import net.ccbluex.liquidbounce.utils.MovementUtils.serverOnGround +import net.ccbluex.liquidbounce.utils.inventory.InventoryUtils.serverOpenInventory +import net.ccbluex.liquidbounce.value.BoolValue +import net.ccbluex.liquidbounce.value.IntegerValue +import net.minecraft.client.gui.inventory.GuiInventory + +object InventoryManager: MinecraftInstance() { + + // Shared no move click values + val noMoveValue = BoolValue("NoMoveClicks", false) + val noMoveAirValue = BoolValue("NoClicksInAir", false) { noMoveValue.get() } + val noMoveGroundValue = BoolValue("NoClicksOnGround", true) { noMoveValue.get() } + + // Shared values between AutoArmor and InventoryCleaner + val invOpenValue = BoolValue("InvOpen", false) + val simulateInventoryValue = BoolValue("SimulateInventory", true) { !invOpenValue.get() } + val autoCloseValue = BoolValue("AutoClose", false) { invOpenValue.get() } + + val startDelayValue = IntegerValue("StartDelay", 0, 0..500) { invOpenValue.get() || simulateInventoryValue.get() } + val closeDelayValue = IntegerValue("CloseDelay", 0, 0..500) { if (invOpenValue.get()) autoCloseValue.get() else simulateInventoryValue.get() } + + private lateinit var inventoryWorker: Job + + var hasScheduled = false + set(value) { + // If hasScheduled gets set to true any time during the searching loop, inventory can be closed when the loop finishes. + if (value) canCloseInventory = true + + field = value + } + + private var canCloseInventory = false + + private suspend fun manageInventory() { + + /** + * ChestStealer actions + */ + + CoroutineStealer.stealFromChest() + + /** + * AutoArmor actions + */ + + CoroutineArmorer.equipFromHotbar() + + // Following actions require inventory / simulated inventory, ... + + // TODO: This could be at start of each action? + // Don't wait for NoMove not to be violated, check if there is anything to equip from hotbar and such by looping again + if (!canClickInventory() || (invOpenValue.get() && mc.currentScreen !is GuiInventory)) + return + + canCloseInventory = false + + while (true) { + hasScheduled = false + + CoroutineArmorer.equipFromInventory() + + /** + * InventoryCleaner actions + */ + + // Compact multiple small stacks into one to free up inventory space + CoroutineCleaner.compactStacks() + + // Sort hotbar (with useful items without even dropping bad items first) + CoroutineCleaner.sortHotbar() + + // Drop bad items to free up inventory space + CoroutineCleaner.dropGarbage() + + // Stores which action should be executed to close open inventory or simulated inventory + // If no clicks were scheduled throughout any iteration (canCloseInventory == false), then it is null, to prevent closing inventory all the time + closingAction ?: return + + // Prepare for exiting the inventory + delay(closeDelayValue.get().toLong()) + + // Try to search through inventory one more time, only close when no actions were scheduled in current iteration + if (!hasScheduled) { + closingAction?.invoke() + return + } + } + } + + private val closingAction + get() = + // Check if any click was scheduled since inventory got open + if (!canCloseInventory) null + + // Prevent any other container guis from getting closed + else if (mc.thePlayer?.openContainer?.windowId != 0) null + + // Check if open inventory should be closed + else if (mc.currentScreen is GuiInventory && invOpenValue.get() && autoCloseValue.get()) + { { mc.thePlayer?.closeScreen() } } + + // Check if simulated inventory should be closed + else if (simulateInventoryValue.get() && serverOpenInventory && mc.currentScreen == null) + { { serverOpenInventory = false } } + + else null + + fun canClickInventory(closeWhenViolating: Boolean = false) = + if (noMoveValue.get() && isMoving && if (serverOnGround) noMoveGroundValue.get() else noMoveAirValue.get()) { + + // NoMove check is violated, close simulated inventory + if (closeWhenViolating) + serverOpenInventory = false + + false + } else true // Simulated inventory will get reopen before a window click, delaying it by start delay + + fun startCoroutine() { + inventoryWorker = CoroutineScope(Dispatchers.Default).launch { + while (isActive) { + runCatching { + manageInventory() + }.onFailure { + // TODO: Remove when stable + displayChatMessage("§cReworked coroutine inventory management had ran into an issue! Please report this: ${it.message ?: it.cause}") + + it.printStackTrace() + } + } + } + } +} \ No newline at end of file diff --git a/src/main/java/net/ccbluex/liquidbounce/utils/InventoryUtils.kt b/src/main/java/net/ccbluex/liquidbounce/utils/inventory/InventoryUtils.kt similarity index 57% rename from src/main/java/net/ccbluex/liquidbounce/utils/InventoryUtils.kt rename to src/main/java/net/ccbluex/liquidbounce/utils/inventory/InventoryUtils.kt index 4b57b569cf0..70290adec82 100644 --- a/src/main/java/net/ccbluex/liquidbounce/utils/InventoryUtils.kt +++ b/src/main/java/net/ccbluex/liquidbounce/utils/inventory/InventoryUtils.kt @@ -3,31 +3,55 @@ * A free open source mixin-based injection hacked client for Minecraft using Minecraft Forge. * https://github.com/CCBlueX/LiquidBounce/ */ -package net.ccbluex.liquidbounce.utils +package net.ccbluex.liquidbounce.utils.inventory import net.ccbluex.liquidbounce.event.* -import net.ccbluex.liquidbounce.utils.timer.MSTimer +import net.ccbluex.liquidbounce.utils.MinecraftInstance +import net.ccbluex.liquidbounce.utils.PacketUtils.sendPacket +import net.ccbluex.liquidbounce.utils.timing.MSTimer import net.minecraft.block.BlockBush import net.minecraft.init.Blocks import net.minecraft.item.Item import net.minecraft.item.ItemBlock -import net.minecraft.network.play.client.C08PacketPlayerBlockPlacement -import net.minecraft.network.play.client.C09PacketHeldItemChange -import net.minecraft.network.play.client.C0DPacketCloseWindow -import net.minecraft.network.play.client.C16PacketClientStatus +import net.minecraft.network.play.client.* import net.minecraft.network.play.client.C16PacketClientStatus.EnumState.OPEN_INVENTORY_ACHIEVEMENT import net.minecraft.network.play.server.S09PacketHeldItemChange +import net.minecraft.network.play.server.S2DPacketOpenWindow import net.minecraft.network.play.server.S2EPacketCloseWindow object InventoryUtils : MinecraftInstance(), Listenable { // What slot is selected on server-side? - var serverSlot = -1 - private set + // TODO: Is this equal to mc.playerController.currentPlayerItem? + var serverSlot + get() = _serverSlot + set(value) { + if (value != _serverSlot) { + sendPacket(C09PacketHeldItemChange(value)) + + _serverSlot = value + } + } // Is inventory open on server-side? - var serverOpenInventory = false - private set + var serverOpenInventory + get() = _serverOpenInventory + set(value) { + if (value != _serverOpenInventory) { + sendPacket( + if (value) C16PacketClientStatus(OPEN_INVENTORY_ACHIEVEMENT) + else C0DPacketCloseWindow(mc.thePlayer?.openContainer?.windowId ?: 0) + ) + + _serverOpenInventory = value + } + } + + // Backing fields + private var _serverSlot = 0 + private var _serverOpenInventory = false + + var isFirstInventoryClick = true val CLICK_TIMER = MSTimer() @@ -55,22 +79,24 @@ object InventoryUtils : MinecraftInstance(), Listenable { fun findItem(startInclusive: Int, endInclusive: Int, item: Item): Int? { for (i in startInclusive..endInclusive) - if (mc.thePlayer.inventoryContainer.getSlot(i).stack?.item == item) + if (mc.thePlayer.openContainer.getSlot(i).stack?.item == item) return i return null } - fun hasSpaceHotbar(): Boolean { + fun hasSpaceInHotbar(): Boolean { for (i in 36..44) - mc.thePlayer.inventoryContainer.getSlot(i).stack ?: return true + mc.thePlayer.openContainer.getSlot(i).stack ?: return true return false } + fun hasSpaceInInventory() = mc.thePlayer?.inventory?.firstEmptyStack != -1 + fun findBlockInHotbar(): Int? { val player = mc.thePlayer ?: return null - val inventory = player.inventoryContainer + val inventory = player.openContainer return (36..44).filter { val stack = inventory.getSlot(it).stack ?: return@filter false @@ -82,7 +108,7 @@ object InventoryUtils : MinecraftInstance(), Listenable { fun findLargestBlockStackInHotbar(): Int? { val player = mc.thePlayer ?: return null - val inventory = player.inventoryContainer + val inventory = player.openContainer return (36..44).filter { val stack = inventory.getSlot(it).stack ?: return@filter false @@ -97,33 +123,44 @@ object InventoryUtils : MinecraftInstance(), Listenable { if (event.isCancelled) return when (val packet = event.packet) { - is C08PacketPlayerBlockPlacement -> CLICK_TIMER.reset() + is C08PacketPlayerBlockPlacement, is C0EPacketClickWindow -> { + CLICK_TIMER.reset() + + if (packet is C0EPacketClickWindow) + isFirstInventoryClick = false + } is C16PacketClientStatus -> if (packet.status == OPEN_INVENTORY_ACHIEVEMENT) { - if (serverOpenInventory) event.cancelEvent() - else serverOpenInventory = true + if (_serverOpenInventory) event.cancelEvent() + else { + isFirstInventoryClick = true + _serverOpenInventory = true + } } - is C0DPacketCloseWindow, is S2EPacketCloseWindow -> serverOpenInventory = false + is C0DPacketCloseWindow, is S2EPacketCloseWindow, is S2DPacketOpenWindow -> { + isFirstInventoryClick = false + _serverOpenInventory = false + } is C09PacketHeldItemChange -> { // Support for Singleplayer // (client packets get sent and received, duplicates would get cancelled, making slot changing impossible) if (event.eventType == EventState.RECEIVE) return - if (packet.slotId == serverSlot) event.cancelEvent() - else serverSlot = packet.slotId + if (packet.slotId == _serverSlot) event.cancelEvent() + else _serverSlot = packet.slotId } - is S09PacketHeldItemChange -> serverSlot = packet.heldItemHotbarIndex + is S09PacketHeldItemChange -> _serverSlot = packet.heldItemHotbarIndex } } @EventTarget fun onWorld(event: WorldEvent) { - // Prevent desync - serverOpenInventory = false + // Prevents desync + _serverOpenInventory = false } override fun handleEvents() = true diff --git a/src/main/java/net/ccbluex/liquidbounce/utils/item/ItemUtils.kt b/src/main/java/net/ccbluex/liquidbounce/utils/inventory/ItemUtils.kt similarity index 52% rename from src/main/java/net/ccbluex/liquidbounce/utils/item/ItemUtils.kt rename to src/main/java/net/ccbluex/liquidbounce/utils/inventory/ItemUtils.kt index c02f95840cf..9811d2b0f55 100644 --- a/src/main/java/net/ccbluex/liquidbounce/utils/item/ItemUtils.kt +++ b/src/main/java/net/ccbluex/liquidbounce/utils/inventory/ItemUtils.kt @@ -3,18 +3,17 @@ * A free open source mixin-based injection hacked client for Minecraft using Minecraft Forge. * https://github.com/CCBlueX/LiquidBounce/ */ -package net.ccbluex.liquidbounce.utils.item + +package net.ccbluex.liquidbounce.utils.inventory import net.ccbluex.liquidbounce.injection.implementations.IMixinItemStack import net.ccbluex.liquidbounce.utils.MinecraftInstance import net.minecraft.enchantment.Enchantment -import net.minecraft.item.Item -import net.minecraft.item.ItemStack -import net.minecraft.item.ItemFood -import net.minecraft.item.ItemPotion -import net.minecraft.item.ItemBucketMilk +import net.minecraft.item.* import net.minecraft.nbt.JsonToNBT import net.minecraft.util.ResourceLocation +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.contract object ItemUtils : MinecraftInstance() { /** @@ -27,8 +26,8 @@ object ItemUtils : MinecraftInstance() { return try { val args = itemArguments.replace('&', '§').split(" ") - val amount = args.getOrNull(1)?.toInt() ?: 1 - val meta = args.getOrNull(2)?.toInt() ?: 0 + val amount = args.getOrNull(1)?.toIntOrNull() ?: 1 + val meta = args.getOrNull(2)?.toIntOrNull() ?: 0 val resourceLocation = ResourceLocation(args[0]) val item = Item.itemRegistry.getObject(resourceLocation) ?: return null @@ -55,10 +54,10 @@ object ItemUtils : MinecraftInstance() { for (i in startInclusive..endInclusive) { val itemStack = mc.thePlayer.inventoryContainer.getSlot(i).stack ?: continue - if (itemStack.isEmpty) + if (itemStack.isEmpty()) continue - if (itemDelay != null && !itemStack.hasItemDelayPassed(itemDelay)) + if (itemDelay != null && !itemStack.hasItemAgePassed(itemDelay)) continue if (filter?.invoke(itemStack, i) != false) @@ -73,9 +72,8 @@ object ItemUtils : MinecraftInstance() { * Allows you to check if player is consuming item */ fun isConsumingItem(): Boolean { - if (!mc.thePlayer.isUsingItem) { + if (!mc.thePlayer.isUsingItem) return false - } val usingItem = mc.thePlayer.itemInUse.item return usingItem is ItemFood || usingItem is ItemBucketMilk || usingItem is ItemPotion @@ -89,42 +87,53 @@ object ItemUtils : MinecraftInstance() { */ val ItemStack.durability - get() = this.maxDamage - this.itemDamage + get() = maxDamage - itemDamage -val ItemStack.enchantmentCount: Int +// Calculates how much estimated durability does the item have thanks to its unbreaking level +val ItemStack.totalDurability + get() = durability * (getEnchantmentLevel(Enchantment.unbreaking) + 1) + +val ItemStack.enchantments: Map get() { - if (this.enchantmentTagList == null || this.enchantmentTagList.hasNoTags()) - return 0 + val enchantments = mutableMapOf() + + if (this.enchantmentTagList == null || enchantmentTagList.hasNoTags()) + return enchantments - var count = 0 - for (i in 0 until this.enchantmentTagList.tagCount()) { - val tagCompound = this.enchantmentTagList.getCompoundTagAt(i) - if (tagCompound.hasKey("ench") || tagCompound.hasKey("id")) count++ + repeat(enchantmentTagList.tagCount()) { + val tagCompound = enchantmentTagList.getCompoundTagAt(it) + if (tagCompound.hasKey("ench") || tagCompound.hasKey("id")) + enchantments[Enchantment.getEnchantmentById(tagCompound.getInteger("id"))] = tagCompound.getInteger("lvl") } - return count + return enchantments } -fun ItemStack.getEnchantmentLevel(enchantment: Enchantment): Int { - if (this.enchantmentTagList == null || this.enchantmentTagList.hasNoTags()) - return 0 +val ItemStack.enchantmentCount + get() = enchantments.size - for (i in 0 until this.enchantmentTagList.tagCount()) { - val tagCompound = this.enchantmentTagList.getCompoundTagAt(i) - if (tagCompound.hasKey("ench") && tagCompound.getInteger("ench") == enchantment.effectId - || tagCompound.hasKey("id") && tagCompound.getInteger("id") == enchantment.effectId - ) return tagCompound.getInteger("lvl") +// Returns sum of levels of all enchantment levels +val ItemStack.enchantmentSum + get() = enchantments.values.sum() + +fun ItemStack.getEnchantmentLevel(enchantment: Enchantment) = enchantments.getOrDefault(enchantment, 0) + +// Makes Kotlin smart-cast the stack to not null ItemStack +@OptIn(ExperimentalContracts::class) +fun ItemStack?.isEmpty(): Boolean { + contract { + returns(false) implies (this@isEmpty != null) } - return 0 + return this == null || item == null } -val ItemStack?.isEmpty - get() = this == null || this.item == null - -fun ItemStack.hasItemDelayPassed(delay: Int) = - System.currentTimeMillis() - (this as IMixinItemStack).itemDelay >= delay +@Suppress("CAST_NEVER_SUCCEEDS") +fun ItemStack?.hasItemAgePassed(delay: Int) = this == null + || System.currentTimeMillis() - (this as IMixinItemStack).itemDelay >= delay val ItemStack.attackDamage - get() = (this.attributeModifiers["generic.attackDamage"].firstOrNull()?.amount ?: 0.0) + - 1.25 * this.getEnchantmentLevel(Enchantment.sharpness) \ No newline at end of file + get() = (attributeModifiers["generic.attackDamage"].firstOrNull()?.amount ?: 0.0) + + 1.25 * getEnchantmentLevel(Enchantment.sharpness) + +fun ItemStack.isSplashPotion() = item is ItemPotion && ItemPotion.isSplash(metadata) \ No newline at end of file diff --git a/src/main/java/net/ccbluex/liquidbounce/utils/misc/FallingPlayer.kt b/src/main/java/net/ccbluex/liquidbounce/utils/misc/FallingPlayer.kt index 786bb345d9e..cd88b3bde46 100644 --- a/src/main/java/net/ccbluex/liquidbounce/utils/misc/FallingPlayer.kt +++ b/src/main/java/net/ccbluex/liquidbounce/utils/misc/FallingPlayer.kt @@ -70,7 +70,7 @@ class FallingPlayer( } fun findCollision(ticks: Int): CollisionResult? { - for (i in 0 until ticks) { + repeat(ticks) { i -> val start = Vec3(x, y, z) calculateForTick() val end = Vec3(x, y, z) diff --git a/src/main/java/net/ccbluex/liquidbounce/utils/misc/RandomUtils.kt b/src/main/java/net/ccbluex/liquidbounce/utils/misc/RandomUtils.kt index 5a5ac1a10ae..72605e725e3 100644 --- a/src/main/java/net/ccbluex/liquidbounce/utils/misc/RandomUtils.kt +++ b/src/main/java/net/ccbluex/liquidbounce/utils/misc/RandomUtils.kt @@ -30,7 +30,11 @@ object RandomUtils { fun random(length: Int, chars: CharArray): String { val stringBuilder = StringBuilder() - for (i in 0 until length) stringBuilder.append(chars[Random.nextInt(chars.size)]) + + repeat(length) { + stringBuilder.append(chars[Random.nextInt(chars.size)]) + } + return stringBuilder.toString() } diff --git a/src/main/java/net/ccbluex/liquidbounce/utils/render/shader/shaders/GlowShader.kt b/src/main/java/net/ccbluex/liquidbounce/utils/render/shader/shaders/GlowShader.kt index 821a7d3a6f1..acef170d6f3 100644 --- a/src/main/java/net/ccbluex/liquidbounce/utils/render/shader/shaders/GlowShader.kt +++ b/src/main/java/net/ccbluex/liquidbounce/utils/render/shader/shaders/GlowShader.kt @@ -8,10 +8,7 @@ package net.ccbluex.liquidbounce.utils.render.shader.shaders import net.ccbluex.liquidbounce.utils.render.shader.FramebufferShader import org.lwjgl.opengl.GL20.* -class GlowShader : FramebufferShader("glow.frag") { - companion object { - val GLOW_SHADER = GlowShader() - } +object GlowShader : FramebufferShader("glow.frag") { override fun setupUniforms() { setupUniform("texture") diff --git a/src/main/java/net/ccbluex/liquidbounce/utils/timing/DelayTimer.kt b/src/main/java/net/ccbluex/liquidbounce/utils/timing/DelayTimer.kt new file mode 100644 index 00000000000..c60f348962c --- /dev/null +++ b/src/main/java/net/ccbluex/liquidbounce/utils/timing/DelayTimer.kt @@ -0,0 +1,47 @@ +package net.ccbluex.liquidbounce.utils.timing + +import net.ccbluex.liquidbounce.utils.inventory.InventoryUtils.CLICK_TIMER +import net.ccbluex.liquidbounce.utils.timing.TimeUtils.randomDelay +import net.ccbluex.liquidbounce.value.IntegerValue + +open class DelayTimer( + private val minDelayValue: IntegerValue, private val maxDelayValue: IntegerValue = minDelayValue, + private val baseTimer: MSTimer = CLICK_TIMER +) { + private var delay = 0 + + open fun hasTimePassed() = baseTimer.hasTimePassed(delay) + + fun resetDelay() { + delay = randomDelay(minDelayValue.get(), maxDelayValue.get()) + } + + fun resetTimer() = baseTimer.reset() + + fun reset() { + resetTimer() + resetDelay() + } +} + +open class TickDelayTimer( + private val minDelayValue: IntegerValue, private val maxDelayValue: IntegerValue = minDelayValue, + private val baseTimer: TickTimer = TickTimer() +) { + private var ticks = 0 + + open fun hasTimePassed() = baseTimer.hasTimePassed(ticks) + + fun resetTicks() { + ticks = randomDelay(minDelayValue.get(), maxDelayValue.get()) + } + + fun resetTimer() = baseTimer.reset() + + fun update() = baseTimer.update() + + fun reset() { + resetTimer() + resetTicks() + } +} \ No newline at end of file diff --git a/src/main/java/net/ccbluex/liquidbounce/utils/timer/MSTimer.kt b/src/main/java/net/ccbluex/liquidbounce/utils/timing/MSTimer.kt similarity index 91% rename from src/main/java/net/ccbluex/liquidbounce/utils/timer/MSTimer.kt rename to src/main/java/net/ccbluex/liquidbounce/utils/timing/MSTimer.kt index 782cb3cdbcd..a3f7fd0ade6 100644 --- a/src/main/java/net/ccbluex/liquidbounce/utils/timer/MSTimer.kt +++ b/src/main/java/net/ccbluex/liquidbounce/utils/timing/MSTimer.kt @@ -3,7 +3,7 @@ * A free open source mixin-based injection hacked client for Minecraft using Minecraft Forge. * https://github.com/CCBlueX/LiquidBounce/ */ -package net.ccbluex.liquidbounce.utils.timer +package net.ccbluex.liquidbounce.utils.timing class MSTimer { private var time = -1L diff --git a/src/main/java/net/ccbluex/liquidbounce/utils/timer/TickTimer.kt b/src/main/java/net/ccbluex/liquidbounce/utils/timing/TickTimer.kt similarity index 88% rename from src/main/java/net/ccbluex/liquidbounce/utils/timer/TickTimer.kt rename to src/main/java/net/ccbluex/liquidbounce/utils/timing/TickTimer.kt index d7479e1d4d7..bb1c1b8fd09 100644 --- a/src/main/java/net/ccbluex/liquidbounce/utils/timer/TickTimer.kt +++ b/src/main/java/net/ccbluex/liquidbounce/utils/timing/TickTimer.kt @@ -3,7 +3,7 @@ * A free open source mixin-based injection hacked client for Minecraft using Minecraft Forge. * https://github.com/CCBlueX/LiquidBounce/ */ -package net.ccbluex.liquidbounce.utils.timer +package net.ccbluex.liquidbounce.utils.timing class TickTimer { private var tick = 0 diff --git a/src/main/java/net/ccbluex/liquidbounce/utils/timing/TickedActions.kt b/src/main/java/net/ccbluex/liquidbounce/utils/timing/TickedActions.kt new file mode 100644 index 00000000000..6d5a5a00e1f --- /dev/null +++ b/src/main/java/net/ccbluex/liquidbounce/utils/timing/TickedActions.kt @@ -0,0 +1,53 @@ +/* + * LiquidBounce Hacked Client + * A free open source mixin-based injection hacked client for Minecraft using Minecraft Forge. + * https://github.com/CCBlueX/LiquidBounce/ + */ +package net.ccbluex.liquidbounce.utils.timing + +import net.ccbluex.liquidbounce.event.EventTarget +import net.ccbluex.liquidbounce.event.Listenable +import net.ccbluex.liquidbounce.event.TickEvent +import net.ccbluex.liquidbounce.event.WorldEvent +import net.ccbluex.liquidbounce.features.module.Module +import java.util.concurrent.CopyOnWriteArrayList + +object TickedActions : Listenable { + private val actions = CopyOnWriteArrayList Unit>>() + + private val calledThisTick = mutableListOf Unit>>() + + fun schedule(id: Int, module: Module, allowDuplicates: Boolean = false, action: () -> Unit) = + if (allowDuplicates || !isScheduled(id, module)) { + actions += Triple(module, id, action) + true + } else false + + fun isScheduled(id: Int, module: Module) = + actions.filter { it.first == module && it.second == id } + .any { it !in calledThisTick } + + fun clear(module: Module) = actions.removeIf { it.first == module } + + fun size(module: Module) = actions.count { it.first == module } + + fun isEmpty(module: Module) = size(module) == 0 + + @EventTarget(priority = 1) + fun onTick(event: TickEvent) { + // Prevent new scheduled ids from getting marked as duplicates even if they are going to be called next tick + actions.toCollection(calledThisTick) + + for (triple in calledThisTick) { + triple.third() + actions.removeFirst() + } + + calledThisTick.clear() + } + + @EventTarget + fun onWorld(event: WorldEvent) = actions.clear() + + override fun handleEvents() = true +} \ No newline at end of file diff --git a/src/main/java/net/ccbluex/liquidbounce/utils/timer/TimeUtils.kt b/src/main/java/net/ccbluex/liquidbounce/utils/timing/TimeUtils.kt similarity index 91% rename from src/main/java/net/ccbluex/liquidbounce/utils/timer/TimeUtils.kt rename to src/main/java/net/ccbluex/liquidbounce/utils/timing/TimeUtils.kt index d5fbaca4a1a..63f693d6051 100644 --- a/src/main/java/net/ccbluex/liquidbounce/utils/timer/TimeUtils.kt +++ b/src/main/java/net/ccbluex/liquidbounce/utils/timing/TimeUtils.kt @@ -3,7 +3,7 @@ * A free open source mixin-based injection hacked client for Minecraft using Minecraft Forge. * https://github.com/CCBlueX/LiquidBounce/ */ -package net.ccbluex.liquidbounce.utils.timer +package net.ccbluex.liquidbounce.utils.timing import net.ccbluex.liquidbounce.utils.misc.RandomUtils.nextInt import kotlin.math.roundToInt